📄 ccd.c
字号:
#include <hidef.h> /* common defines and macros */
#include <mc9s12dg128.h> /* derivative information */
#include "lib.c"
#include "funtion.h"
volatile uchar rdd1[1024]= //一场的临时数据
{0};
volatile uchar rdd2[1024]= //一场的临时数据
{0};
volatile uint hc=0; //行计数器
volatile uint ofs; //offset
volatile uchar vc; //场设换标志
volatile uchar vcrf; //场改新标志
volatile char gg1[16]= //当前场重心
{0};
volatile uchar cinc=0; //正方向计数
volatile uchar cdec=0; //负方向计数
volatile char gg0[16]= //前一场行重心
{0};
volatile char gx[10]=0; //10场图像场重心
volatile uint cu=0; //曲率
volatile uchar us[10]={
0 }; //不可见点数
//volatile uint us5; //最近5次不可见点数和
volatile uint n; //测速转感器计数
interrupt 6 void VH(void) //视频行同步信号中断
{
uchar j;
uchar *pd,*pd_end;
hc++;
if(hc>60&&hc<310&&(hc&0x000f)==0) //采集条件
{
if(vc)
pd=(rdd2+ofs); //第一场
else
pd=(rdd1+ofs); //第二场
pd_end=pd+63; //求最后一个点的指针
while((PORTE&0x02)==0) //等等PE2变为高电压
;
ATD1CTL5=0xA0; //启动AD
dy(5);
//PORTB=0x00;
for(;pd<pd_end;)
{
while((ATD1STAT0&0x80)==0)
;
*(pd++)=ATD1DR0;
// asm(nop);
}
ATD1CTL5=0x80; //一行采集完成
ofs+=64;
//PORTB=0xff;
} //*/
}
interrupt 24 void VV(void) //场同步中断
{
if(PIFJ&0x80) //PJ7
{
PIFJ=0x80;
hc=0;
ofs=0;
vc=0;
vcrf=1;
}
else if(PIFJ&0x40) //PJ6
{
PIFJ=0x40;
hc=0;
ofs=0;
vc=1;
vcrf=1;
}
}
void pass() //数字滤波, 此办法最多可滤去4个连续的干扰点,滤波用行相关方法
{
uchar i,j;
uchar ta[18]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; //错误标记, 16个数,
}
void sg(void) //求重心
{
char i,j,k;
char tmp;
uchar *pd; //数据指针
uchar *pd0;
uchar fu=0; //找到黑线标志
if(vc) //正在采集第二场,使用第一场
pd0=rdd1;
else //正在采集第一场,使用第二场
pd0=rdd2;
//计算黑点
for(i=0;i<16;i++) //一场16行
{
fu=0;
pd=pd0+64*i; //求取当行首指针
for(j=-31;j<29&&(fu==0);j++)
{
if(*(pd)<GATE0&&*(pd+1)<GATE0&&*(pd+2)<GATE0) //出现黑线条件
{
for(k=3;*(pd+k)<GATE0&&(j+k)<31;k++) //找出黑线最右点
;
fu=1;
}
pd++;
}
if(fu) //找到黑线,求黑线中心位置
*(gg1+i)=((j*2)+k)/2;
else //找不到黑线, 依靠上一场断判从哪边冲出
{
if(*(gg0+i)<0)
*(gg1+i)=-32;
else
*(gg1+i)=32;
}
}
pass(); //数字滤波
for(i=0;i<16;i++) //复制当前场数据到gg0
*(gg0+i)=*(gg1+i);
//PORTB=0xff;
}
void gc(void) //求场重心和弯率
{
uchar i,j;
char tmp0;
int tmp2=0;
int tmp=0;
for(i=9;i;i--) //保存最近十场的重心
*(gx+i)=*(gx+i-1);
i=0;
for(j=0;j<16&&i<4;j++)
{
tmp0=*(gg1+15-j); //从最近行开始取数
tmp+=tmp0; //累加
if(abs(tmp0)>18) //当出现3点绝对值大于20时,不再取其它行
{
i++;
tmp2+=tmp0;
}
}
*us=16-j; //求项部不可见点数
tmp0=tmp2/i;
for(;j<16;j++) //剩下的行按绝对值大于24这3行的平均值算
tmp+=tmp0; //*/
tmp0=tmp/16;
if(abs(tmp0-*gx)<24) //状态有效条件
*gx=tmp0; //出现突变时使用前一场的数据
for(j=4;j;j--)
*(us+j)=*(us+j-1);
/* *us=0;
for(j=0;j<8;j++) //求顶部不可见点数
{
if(abs(*(gg1+j))>30) //不可见点
(*us)++;
} //*/
cinc=0;cdec=0;
for(i=0;i<15;i++) //求正向增长和负向增长点数
{
if(abs(*(gg1+i+1)-*(gg1+i))<5) //没有出现突变才允许记数
{
if(*(gg1+i+1)>*(gg1+i)) //正向增长条件
cinc++;
else if(*(gg1+i+1)<*(gg1+i))
cdec++;
}
}
cu=0; //曲率
for(j=i;j<16;j++)
cu+=abs(*(gg1+j)-*gx);
cu/=(16-i);
}
void t_ccd(void) //CCD 测试
{
uchar kv=0;
uchar kd=0;
uint t2;
uchar *pd;
uint dir_c0=0; //flash 计数器
uchar fr[2]={0,0}; //帧计数器
clr_pr();
while(kv!=7) //等待返回键按下
{
// ATD0CTL5=0x81; //启动AD(测量电池电压)
kv=key();
if(kv==1) //转向开关
kd=(kd==1?0:1);
else if(kv==2) //保存一帧图像
{
if(vc) //正在采集第二场,使用第一场
pd=rdd1;
else //正在采集第一场,使用第二场
pd=rdd2;
for(dir_c0=0;dir_c0<256;) //一帧有1K字节,需4个block
buf[dir_c0++]=*(pd++);
for(dir_c0=264;dir_c0<520;)
buf[dir_c0++]=*(pd++);
sent(1);
delay(10);
load(1,4*(*fr));
delay(10);
sent(2);
delay(10);
load(2,4*(*fr)+1);
delay(10);
for(dir_c0=0;dir_c0<256;)
buf[dir_c0++]=*(pd++);
for(dir_c0=264;dir_c0<520;)
buf[dir_c0++]=*(pd++);
sent(1);
delay(10);
load(1,4*(*fr)+2);
delay(10);
sent(2);
delay(10);
load(2,4*(*fr)+3);
delay(10);
(*fr)++;
}
else if(kv==3&&GATE1<75) //提高门槛1
GATE1++;
else if(kv==5&&GATE0<75) //提高门槛
GATE0++;
else if(kv==6&&GATE0>30) //降低门槛
GATE0--;
else if(kv==8) //保存门槛
{
save_s();
clr_pr(); //清除文字
}
else if(kv==10) //输出一帧数据
{
d_out(2*(*(fr+1)));
d_out(2*(*(fr+1))+1);
if((*(fr+1))<(*fr))
(*(fr+1))++;
else
(*(fr+1))=0;
}
dr();
sg(); //求重心
dg(); //画重心
gc(); //求行重心和曲率
wgc(fr); //向液晶写入重心和曲率
if(kd) //转向
dir(15*(*gx));
else
dir(0);
ATD0CTL5=0x87 ; //测量电压
while(ATD0STAT0==0) //waiting for finish
;
t2=ATD0DR0*39; //读取AD值
go(5,0);
wn(t2/1000,'.');
wn((t2%1000)/100,(t2%100)/10);
wn(t2%10,'V'); //向液晶写入电压
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -