3.1 采集分析
本系统所使用的CCD摄像头输出的是PAL制式的视频信号,其一幅图像包含575个图像行,每行最多有767个点(按荧光屏的长宽比为4:3计算),因此其图像解析度能达到575×767≈440000个象素。而对于智能车系统而言,由于受MC9S12DG128单片机内存和运算速度的限制,这么大解析度的图像是无法处理的。因此必须降低图像的分辨率。根据实际需要,在分辨率为30×30的情况下,仍然能够获得清晰的赛道图像,满足控制车辆的需要。
路径检测需要的图像的特点是水平分辨率高,垂直分辨率低,而S12单片机受ATD转换速率的限制,在水平方向上每一行中只能采集8个点,而垂直方向上则能够采集数百行,因此该文作者提出了将摄像头旋转90度的方法解决这一矛盾。而本文作者经过实验验证,通过降低ATD的采集精度,将单片机CPU超频,配合提高ATD时钟,能够在一行数据有效的52μs时间内,最多采集48个点,这对于路径检测来说也已经足够了,无需将摄像头旋转90度。不旋转摄像头的好处还在于能够一边采集数据,一边完成对数据的初步处理。我们最终确定采集图像的分辨率为48×40,即每行采集48个点,每幅图像采集40行。
3.2 采集时序
具体说来,采集一场的流程是这样的:
第一步,LM1881分离出的奇场同步信号在DG128的H口产生中断。根据PAL规范,此时意味着还有22行(约1408μs,视LM1881的信号延时而定)将开始第一个数据行。为确保正确的采集到数据,使定时器定时23.5行(23.5×64μs=1504μs),定时结束后,开启行中断,准备采集数据。
第二步,定时器定时1504μs时间到,此时开启行通道,允许中断,并使控制ATD转换的行计数器归零,以标志一幅图像的开始。
第三步,大约32μs(0.5行)后,行中断到。由于一场中有280多个行,但ATD只采集其中的40行,为此设置了一个行计数器,每次行中断都将该计数器加一,当该计数器的值与预存数组里的某个数相等时,表示该行应该采集。根据PAL的规范,在数据行中,行同步信号后6μs(上升沿,如果选下降沿有效,应该是10.3μs)才会有真正的图像数据出现,并持续52μs到该行结束。为此在该行的行中断中使定时器定时6μs,定时时结束后才能开始采集。
第四步,定时器定时6μs时间到。此时应立即开始ATD采集。由于ATD是按序列采集的,一个序列可以连续采集1~8个点,并可设置是单序列还是扫描方式。每个序列采集完成后将产生一次ATD中断。为减少ATD中断次数,在ATD初始化中已设置转换序列长度为8。此时以扫描方式开启ATD,采集48个点需要6次ATD中断。
第五步,每隔约8μs,ATD中断发生一次。该步中最重要的就是把ATD的数据转移到存储图像的数组中。由于一行中ATD要采集6个序列,因此要记录已经采集的序列数,每次进入ATD中断,都使之加一,当序列数为6时,标志着一个行已经采集完了。一行采集完后将采集行计数器(注意:不是第三步中提到的行计数器)加一,并应停止ATD,但是S12中并没有使ATD停止直接方法,唯一的办法是使ATD以单序列采集方式再采集一次。但是这次完成后仍然会发生中断,中断处理程序可根据采集的序列数来判断是否是这种额外的情况,如果是,中断处理程序除了读一下ATD数据寄存器以清中断标志位之外,并不需要做任何事。
第六步,ATD中断不断的向图像数组中写入数据,直到行计数器计到40。此时意味着一幅图像数据已经采集完成。此时应关掉行中断,以免其产生额外动作。
第七步,偶场中断到。其实就是奇场同步信号的下降沿,如果没有进行相应设置和接线,将没有这个中断。PAL制式的信号中,奇场同步信号和偶场同步信号以20ms的间隔交替出现,因此可以将此两种信号作为小车调整的基准时间。此后直到下一个奇场中断到来,开始另一场的采集。
可见,程序的运行完全是由各个中断的来推动的。程序的流程图如图3.1。
![]() ![]() |
|
图3.1 视频采集流程图 |
视频采集共涉及到6个中断:奇场中断、偶场中断、行中断、定时器中断1、定时器中断2、ATD中断。但是只有3个硬件中断源,即H口中断、定时器中断和
ATD中断,对应只有3个中断服务程序。为此需要在中断程序中区分中断的类型。
1)H口中断
H口中断服务程序要区分是奇场中断、偶场中断还是行中断,这是通过寄存器的中断标志为来实现的。中断程序如下:
void interrupt PORTH_ISR(void){
if(PIFH_PIFH2&&PIEH_PIEH2){ //行同步中断
if((!FrameFinish)&&VideoEnable){ //如果视频采集允许
if(vRow==VROW[Row]){ //如果行数等于预定的行数,采集该行
MCCTL=MCCTL_MCZI_MASK|MCCTL_MCEN_MASK;
MCCNT=154; //定时6.25us
MdcServiceNumber=2; //置服务标志
}
vRow++; //更新行计数
}
}
else if(PIFH_PIFH0&&PIEH_PIEH0){ //奇场同步中断
OddValid=1; //置奇场标志
OddCounter++; //更新奇场计数
if(VideoEnable==1){ //如果视频采集允许
FrameFinish=0; //清场完成标志
MCCTL=MCCTL_MCZI_MASK|MCCTL_MCEN_MASK; //打开定时器
MCCNT=34560; //定时22+1.5行
MdcServiceNumber=1; //置定时器服务标志
}
}
else if(PIFH_PIFH1&&PIEH_PIEH1){ //偶场同步中断
EvenValid=1; //置偶场标志
EvenCounter++; //更新偶场计数
}
PIFH=PIFH; //清中断标志
}
2)定时器中断
定时器中断要区分是定时了多少时间。为此我们设置了一个“服务标志”,不同的定时时间设置不同的服务标志,以使定时器中断程序做不同的处理。
void interrupt MDC_ISR(void){
MCFLG|=MCFLG_MCZF_MASK; //清中断标志
MCCTL=0x00; //关闭计数器
if(MdcServiceNumber==1){ //如果奇场定时时间到
//makerecord(FEILD_START); //记录此事件
PIFH=PIFH; //清中断标志
PERH=0x07; //开启行同步信号通道
PIEH=0x07; //开启行同步信号中断
vRow=0; //修改以改变第一个采样行的位置
Row=0; //清行计数器
}
else if(MdcServiceNumber==2){ //如果行定时时间到
ATD0CTL5=ATD0CTL5_SCAN_MASK; //以扫描方式开启AD
AdCounter=0; //置AD序列计数器初值
}
MdcServiceNumber=0; //清服务标志
}
3)ATD中断
ATD中断的首要任务是及时把结果寄存器中的值转移出来,因为ATD是以扫描方式不停的在采集转移不及时,新的结果会把原来的结果覆盖掉。然后ATD中断程序需要根据一系列计数器的值计算本次采集结果对应的图像位置,然后保存到数组中。最后ATD中断还要判断何时一行结束、何时一场结束。ATD在采集时每隔8μs就要发生一次中断,中断服务程序必须要在这段时间内完成,因此要求程序不能过于冗杂。




