⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ccd.c

📁 知能车源码,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 + -