6 - 输入/输出:DMA

DMA, Direct Memory Access. 设定后,无需CPU干预即可将外设数据读到RAM中去。
摄像头组需要不断读取图像到内存,DMA可以分担图像读取的操作,大大减少了CPU的负担,于是我们可以有更多资源处理其他事情。
DMA另一个好处是可以跟着摄像头的PCLK读取数据,图像不会有噪点。
坏消息是,XS128不带DMA功能,呵呵。

通过DMA读取图像的方法:
1. 初始化摄像头管脚输入方向,初始化DMA;
2. 场中断到来,允许行中断;
3. 行中断到来,开启DMA,让DMA读取一行的数据;
4. 关闭DMA,等待下一次行中断。


1. 初始化管脚输入方向

    gpio_init(CCD_PORT,CCD0,GPI,0);
    gpio_init(CCD_PORT,CCD1,GPI,0);
    gpio_init(CCD_PORT,CCD2,GPI,0);
    gpio_init(CCD_PORT,CCD3,GPI,0);
    gpio_init(CCD_PORT,CCD4,GPI,0);
    gpio_init(CCD_PORT,CCD5,GPI,0);
    gpio_init(CCD_PORT,CCD6,GPI,0);
    gpio_init(CCD_PORT,CCD7,GPI,0);

2. 初始化行场中断(外部中断)

    //行中断
    FTM_Input_init(CCD_FTM,CCD_HR_CH,Rising);              //初始化FTM输入捕捉模式,上升沿触发
    //场中断
    FTM_Input_init(CCD_FTM,CCD_VS_CH,Falling);             //初始化FTM输入捕捉模式,下降沿触发

3. 初始化DMA
具体方法请参考野火手册。

    DMA_PORTx2BUFF_Init (CCD_DMA_CH,(void *)&CCD_DATA,&Pic_Buffer[0][0],PLCK_CH,DMA_BYTE1,COLUMN,DMA_rising);//DMA_falling DMA_rising
    //DMA通道4初始化,PTA27上升沿触发DMA传输,源地址为PTD_BYTE0_IN,目的地址为:BUFF ,每次传输1Byte,传输3次后停止传输,恢复目的地址   
    /* 开启中断 */
    //DMA_EN(CCD_DMA_CH);                                    //使能通道CHn 硬件请求
    //DMA_IRQ_EN(CCD_DMA_CH);                                //允许DMA通道传输 
    DMA_IRQ_CLEAN(CCD_DMA_CH);

4. 行场中断处理

/************************************************************************* 
*  函数名称:PORTB_IRQHandler
*  功能说明:摄像头行场中断服务函数
*  参数说明:无   
*  函数返回:无
*  修改时间:2014-3-29 modified by feichashao
*  备    注:
            < 使用了往届学长的代码 >
             原本杨向军的摄像头例程使用的是FTM模块完成行场中断任务,
             这里由于直立车的测速模块已经占用了FTM模块的两个子模块通道,
             因此这里我改用外部中断EXTI模块完成行场中断任务,
             当然也有人说建议使用FTM进行摄像头终端,但原因我也不太明白
*************************************************************************/
u32 tmpline = 0;//行号
u32 error_row = 0;//发生错误行号
u32 tmprow = 0; //列号
u32 tmpnum = 0; //场号
u32 picLineSum = 0;//总行数

void PORTB_IRQHandler()
{
     u32 tmpISFR = 0;
     tmpISFR=PORTB_ISFR;
     PORTB_ISFR |= 0xFFFFFFFF;
     
     // DisableInterrupts; //注释掉,以允许其他中断进入
     //========================== n = CAM_HR_CHn ========================================
     
     if((tmpISFR & (1<= ROW)
             {
                 photeCompleteFlag = 1;
             }
             
         }
     }
     //========================== n = CAM_VS_CHn ========================================
     if((tmpISFR & (1<