DMA, Direct Memory Access. 设定后,无需CPU干预即可将外设数据读到RAM中去。
摄像头组需要不断读取图像到内存,DMA可以分担图像读取的操作,大大减少了CPU的负担,于是我们可以有更多资源处理其他事情。
DMA另一个好处是可以跟着摄像头的PCLK读取数据,图像不会有噪点。
坏消息是,XS128不带DMA功能,呵呵。
通过DMA读取图像的方法:
1. 初始化摄像头管脚输入方向,初始化DMA;
2. 场中断到来,允许行中断;
3. 行中断到来,开启DMA,让DMA读取一行的数据;
4. 关闭DMA,等待下一次行中断。
1. 初始化管脚输入方向
[cc lang=”C”]
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);
[/cc]
2. 初始化行场中断(外部中断)
[cc lang=”C”]
//行中断
FTM_Input_init(CCD_FTM,CCD_HR_CH,Rising); //初始化FTM输入捕捉模式,上升沿触发
//场中断
FTM_Input_init(CCD_FTM,CCD_VS_CH,Falling); //初始化FTM输入捕捉模式,下降沿触发
[/cc]
3. 初始化DMA
具体方法请参考野火手册。
[cc lang=”C”]
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);
[/cc]
4. 行场中断处理
[cc lang=”C”]
/*************************************************************************
* 函数名称: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<
{
photeCompleteFlag = 1;
}
}
}
//========================== n = CAM_VS_CHn ========================================
if((tmpISFR & (1<