中级会员
- 积分
- 357
- 威望
- 231
- 贡献
- 84
- 兑换币
- 15
- 注册时间
- 2012-4-20
- 在线时间
- 21 小时
- 毕业学校
- 福建工程学院
|
由于是第一次接触该小车,有些问题请见谅。
场中断:PT1; 行中断:PT2; 舵机:PP0、PP1;电机:PP3;采集:AD0;摄像头转90°;
采集程序大家都很熟悉,不多说了。
舵机控制程序比较简单,采用两个黑线中点的比较来决定舵机转角,转角大小通过试验得到。
由于是第一次接触该小车,有些问题请见谅。
#include <hidef.h>
#include <MC9S12XS128.h>
#pragma LINK_INFO DERIVATIVE "mc9s12xs128"
//------------------------------------------------
#define column_end 72
#define row 52
unsigned char c_row=0,g_row=0;
unsigned int row_count=0,column_count=0;
unsigned char data[row][column_end];
unsigned char ucRow,ucColumn,floag=0;
int x1=0,x2=0,x3=0,i,j,k,m,w,y,z;
int a1,a2;
unsigned int get_n[]={ 16,29,41,52,62,71,79,86,92,98,
103,108,112,116,120,124,128,132,135,138,
141,144,147,150,153,156,159,162,165,168,
170,172,174,176,178 ,180,182,184,186,188,
190,192,194,196,198,200,202,204,206,208,
210,211,212,242,243,245,246,247,248,249,250};
void PLL_init(void)
{
CLKSEL=0X00; //64MHZ
PLLCTL_PLLON=1;
SYNR =0xc0 | 0x07;
REFDV=0xc0 | 0x01;
POSTDIV=0x00;
_asm(nop);
_asm(nop);
_asm(nop);
_asm(nop);
while(!(CRGFLG_LOCK==1));
CLKSEL_PLLSEL =1; }
void ATD_init(void)
{
ATD0CTL1=0x00;
ATD0CTL2=0X40; //禁止中断 转换后自动清除寄存器
ATD0CTL3=0X88; //没有断点 没有FIFO 通道0开始 单通道 继续转换右对齐 转换序列1
ATD0CTL4=0X00; //4周期,64/2,最快
ATD0CTL5=0X30; // 连续转换 多通道转换 通道AN0开始
ATD0DIEN=0x00; //相应的数字信号输入禁止
}
void AD_init(void)
{
TIOS =0x00;//定时器通道0,1 为输入捕捉
TSCR1=0x80;//定时器使能
TCTL4=0x18;//通道 1 捕捉下降沿通道 2 捕捉上升沿
TIE=0x06; //通道 1,2 中断使能
TFLG1=0xFF;//清中断标志位
}
void PWM_int(void) {
//舵机初始化
PWMCTL_CON01=1; //0和1联合成16位PWM;
PWMCAE_CAE1=0; //选择输出模式为左对齐输出模式
PWMCNT01 = 0; //计数器清零;
PWMPOL_PPOL1=1; //先输出高电平,计数到DTY时,反转电平
PWMPRCLK = 0X62; //clockA 4分频,clockA=busclock/4=16MHz;CLK B 16分频:1Mhz
PWMSCLA = 0x08; //对clock SA 16分频,pwm clock=clockA/16=1MHz;
PWMCLK_PCLK1 = 1; //选择clock SA做时钟源
PWMPER01 = 20000; //周期20ms; 50Hz;
PWMDTY01 = 1500; //高电平时间为1.5ms;
PWME_PWME1 = 1;
//驱动电机初使化
PWMPRCLK=0X72;
PWMCLK_PCLK3=1;
PWMSCLB=0X7D;
PWMPOL_PPOL3=0XFF;
PWMCAE_CAE3=0X00;
PWMPER3=0X13;
PWMDTY3=0X04;
PWME_PWME3=1;
}
void image_int(void)//去噪
{
for(ucRow=0;ucRow<row;ucRow++)
{
for(ucColumn=0;ucColumn<column_end;ucColumn++)
{
if(data[ucRow][ucColumn]==0)
{
if((data[ucRow][ucColumn-1]==1)&&(data[ucRow][ucColumn+1]==1))
{
data[ucRow][ucColumn]=1;
}
}
if(data[ucRow][ucColumn]==1)
{
if((data[ucRow][ucColumn-1]==0)&&(data[ucRow][ucColumn+1]==0))
{
data[ucRow][ucColumn]=0;
}
}
}
}
}
void control_int(void)// 舵机控制
{
//两数组的黑线中点提取
for(i=0;((data[10]==0));i++)
{;}
for(j=i;((data[j][10]==1));j++)
{ ;}
x1=((j-i)/2+i);
for(k=0;((data[k][40]==0));k++)
{;}
for(m=k;((data[m][40]==1));m++)
{ ;}
x2=((m-k)/2+k);
if(k>=50)
for(w=0;((data[51][w]==0) && (data[51][w+1]==0));w++)
{
if(w<40)
a1=40;
else
a1=(-40);
}
//斜率的计算
else
if((x2-x1)>=0)
{
if((x2-x1)==0)
a1=0;
else
a1=30/(x2-x1);
}
else
a1=(-(30/(x1-x2)));
//斜率范围选择
if((a1>=10)&&(a1<=30)){a1=10;}
if((a1>=6)&&(a1<10)){a1=6;}
if((a1>=4)&&(a1<6)){a1=4;}
if((a1>=3)&&(a1<4)){a1=3;}
if((a1>0)&&(a1<3)){a1=1;}
if((a1<=(-10))&&(a1>=(-30))){a1=(-10);}
if((a1<=(-6))&&(a1>(-10))){a1=(-6);}
if((a1<=(-4))&&(a1>(-6))){a1=(-4);}
if((a1<=(-3))&&(a1>(-4))){a1=(-3);}
if((a1<0)&&(a1>(-3))){a1=(-1);}
//转角的选择
switch(a1)
{
case 10:
PWMDTY01 = 1700;
break;
case 6:
PWMDTY01 = 1700;
break;
case 4:
PWMDTY01 = 1800;
break;
case 3:
PWMDTY01 =1900;
break;
case 1:
PWMDTY01 =2000;
break;
case 0:
PWMDTY01 = 1600;
break;
case (-10):
PWMDTY01 = 1600;
break;
case (-6):
PWMDTY01 = 1500;
break;
case(-4):
PWMDTY01 =1300;
break;
case(-3):
PWMDTY01 =1200;
break;
case (-1):
PWMDTY01 = 1100;
break;
case(40):
PWMDTY01 =2000;
break;
case (-40):
PWMDTY01 = 1000;
break;
default:
break;
}
}
void main(void)
{
DisableInterrupts;
PLL_init();
ATD_init();
AD_init();
PWM_int();
EnableInterrupts;
{
unsigned int e,w;
for(e=1;e<6;e++)
for(w=0;w<10;w++);
}
for(;;)
{
if(floag==1)
{
floag=0;
TIE_C1I = 1;
}
}
}
//---------------------------------
#pragma CODE_SEG NON_BANKED
void interrupt 10 IC2ISR(void)
{
TFLG1_C2F=1; {
unsigned int i,j,num=1;
for(i=0;i<num;i++)
for(j=0;j<58;j++);
if(row_count==get_n[c_row])
{
for(column_count=0;column_count<=column_end;column_count++)
{
while(!ATD0STAT0_SCF);
{
data[c_row][column_count]=ATD0DR0L; //AD0口为信号输入
if(data[c_row][column_count]<88) //88二值化阀值
data[c_row][column_count]=1;
else
data[c_row][column_count]=0;
}
}
c_row++;
}
row_count++;
if(c_row>=row)
{floag=1;
TIE_C2I = 0;
}
else TIE_C2I = 1;
}
}
void interrupt 9 IC1ISR(void)
{
column_count=0;
row_count=0;
c_row=0;
TFLG1_C1F=1; //清场中断标志
TFLG1_C2F=1; //清行中断标志
image_int();
control_int();
TIE_C2I = 1; //开行中断
TIE_C1I = 0;
}
#pragma CODE_SEG DEFAULT
|
|