今年的智能车竞赛,STC组别通常使用的是CCD图像传感器。
CCD图像传感器是什么呢?其实就是普通的摄像头只取一行的效果,对于普通的赛道循迹来说,完全是够用的。
不过随着车友们的速度越来越快,CCD图像的帧率就变得重要起来了,普通的70帧到80帧的速率已经不能满足车友们的控制需求了
那么,应该如何提高单片机读取CCD图像的速度呢?
这里给出一种使用PWM同步触发ADC,通过ADC中断对图像进行保存的思路,这种方法图像曝光间隔稳定,图像质量好,ADC采样点可以调节,并且不会堵塞占用系统资源。
这里给出一个示例程序,其中使用的是PWM1P引脚P2.0和ADC0引脚P1.0,设定的采样频率是300帧左右。
- <font size="5">u16 set_period = 1300;//采样周期
- u16 set_ccr = 250;//采样时间点
- u16 adc_tmp[128] = {0};
- u16 ADC_Cnt = 0; // ADC缓冲计数
- bit ADC_Finish = 0; // 成功置1
-
- void PWM_Init(void)
- {
- EAXFR = 1; // 使能访问外部XFR
- PWMA_PS = 0x01; // 高级 PWM 通道输出脚选择位
- PWMA_ENO = 0x01;
- PWMA_CNTRH = 0x00;
- PWMA_CNTRL = 0x00;
- PWMA_ARRH = (u8)(set_period >> 8); // 设置周期时间
- PWMA_ARRL = (u8)set_period;
-
- PWMA_CCR1H = (u8)(set_ccr >> 8);
- PWMA_CCR1L = (u8)(set_ccr);
-
- PWMA_CR2 = 0x30; // 设置比较捕获打开ADC
-
- PWMA_CCER1 = 0x00; // 写 CCMRx 前必须先清零 CCxE 关闭通道
- PWMA_CCMR1 = 0x60; // 通道模式配置
- PWMA_CCER1 = 0x01; // 配置通道输出使能和极性
-
- PWMA_BKR = 0x80; // 使能主输出
- PWMA_CR1 |= 0x01; // 使能计数器
-
- ADC_CONTR = 0; // 固定打开0通道
- ADC_POWER = 1;
- ADC_EPWMT = 1;
- ADC_FLAG = 0;
- ADCCFG = 0x20; // 调整为右对齐,ADC时钟速度最快
- ADCTIM = 0x9f; // 最大采样时间
- EADC = 1;
- PWMA_IER = 0x01;
- }
-
- void ADC_Isr(void) interrupt 5
- {
- ADC_FLAG = 0;
- if (ADC_Cnt >= 128)
- {
- PWMA_CR1 &= ~0x01; // 暂时关闭PWMA
- ADC_Finish = 1;
- }
- else
- {
- adc_tmp[ADC_Cnt] = ((u16)ADC_RES << 8 | ADC_RESL);
- ADC_Cnt++;
- }
- }
-
- void Start_Get_Image(void)
- {
- PWMA_CR1 &= ~0x01; // 暂时关闭PWMA
- PWMA_CNTRH = 0x00;
- PWMA_CNTRL = 0x00; // 计数清零
- PWMA_ENO = 0x00; // 关闭PWMA端口输出
- CCD_CLK = 1;
- CCD_SI = 0;
- CCD_CLK = 0;
- CCD_SI = 1;
- CCD_CLK = 1;
- CCD_SI = 0;
- CCD_CLK = 0;
- ADC_START = 1;
- PWMA_ENO = 0x01; // 使能输出,小脉冲
- ADC_Cnt = 0; // 从零开始计数
- PWMA_CR1 |= 0x01; // 启动PWMA定时器计数
- ADC_Finish = 0;
- }</font>
复制代码
这里,使用的是PWM1P的CCR比较事件触发的ADC采样,adc_tmp[128]是用于缓存一帧图像的数组,每次读取完成以后会给ADC_Finish标志位置1。
程序内只需要启动Start_Get_Image()函数,然后等待ADC_Finish标志位变成1,处理完图像后,再次将ADC_Finish标志位变成0后,重新开始获取图像流程即可。
当然,如果追求更快的速度,可以加入双缓冲机制,使得图像采样可以不用等待图像处理完成。
以上程序仅供交流,确保是能用的。如果想要更改为其他的引脚,可以参考技术手册进行更改。
|