|
![](static/image/common/ico_lz.png)
楼主 |
发表于 2008-12-26 22:27:46
|
显示全部楼层
还是把程序贴上来,不然说我不厚道,主要是我的程序判断十字口有点不准确。然后AD结果的值也没有处理即多次转换去掉最大值和最小值求平均,听说这样可以很好的抗干扰,自己没有试过不知道哈。出轨的情况没有考虑哈!这就是我这个程序的毛病。我写程序喜欢按照自己的思想去写,也不知道还有多少隐藏的毛病!
/*****************************************************
Project : 寻迹小车控制函数
Date : 2008-11-27
Author : 天下的人
Company : China
Chip type : ATmega16L
Clock frequency : 12.000000 MHz
*****************************************************/
#include <mega16.h>
#include <delay.h>
#define BIT(i) (1<<(i))
#define ADC_VREF_TYPE 0x60
#define uchar unsigned char
#define uint unsigned int
/******************** 变量定义 ********************************/
const unsigned char high=179; //AD转换有信号的比较值
const unsigned char low=153; //AD转换无信号比较值
flash uchar tiaos[5]={0x01,0xc0,0xEe,0xff,0xee}; //实现5级调速 分别是0% 75% 90% 100% 95%
unsigned char adc_dat[5]; //AD转换 比较值存放数组
unsigned char adc_hc[5]; //AD转换 缓冲存放数组
unsigned char js=0; //计数 js 计数AD装换通道和赋值给对应的数组中;
uchar OCR0_1=0x80,OCR2_1=0x80; //PWM 波占空比调节变量
uchar jiaod=78; //转向的角度时间延时
// uchar chuli[5][7]; //AD处理函数的变量
uchar cishu=0; //转换的次数
/************************ 中断处理函数 **************************************************/
interrupt [TIM0_COMP] void timer0_comp_isr(void) // 定时器 计数器0比较中断
{
OCR0=OCR0_1; //占空比调节
}
interrupt [TIM2_COMP] void timer2_comp_isr(void) // Timer 2 比较中断
{
OCR2=OCR2_1; //占空比调节
}
interrupt [ADC_INT] void adc_isr(void) // ADC interrupt service routine
{
// chuli[js][cishu]=ADCH;
adc_dat[js]=ADCH;
js++;
if(js==5)
{
cishu++;
// jsbz=1;
js=0;
adc_hc[0]=adc_dat[0];
adc_hc[1]=adc_dat[1];
adc_hc[2]=adc_dat[2];
adc_hc[3]=adc_dat[3];
adc_hc[4]=adc_dat[4];
}
switch (js)
{
case 0:
ADCSRA&=~BIT(3); //关中断
ADMUX=0x60; //转换通道
ADCSRA|=BIT(3); //开中断
break;
case 1:
ADCSRA&=~BIT(3);
ADMUX=0x61;
ADCSRA|=BIT(3);
break;
case 2:
ADCSRA&=~BIT(3);
ADMUX=0x62;
ADCSRA|=BIT(3);
break;
case 3:
ADCSRA&=~BIT(3);
ADMUX=0x63;
ADCSRA|=BIT(3);
break;
case 4:
ADCSRA&=~BIT(3);
ADMUX=0x64;
ADCSRA|=BIT(3);
break;
}
}
/*******************************************************************************************/
/******************************** 小车的应用函数 *****************************************/
/* void display(void)
{
char i;
for (i=0;i<=5;i++)
{
PORTB=led_7[dis_buff]; //rang A kou shu chu di i wei yu xian shi de shu
PORTC=~BIT(i); //第1位的显示; ||只有靠自己去区分了,如果用八段数码管则可以用小数点区分 可以修改此程序实现
delay_ms(2); //显示延时用,如果去掉则不能显示。
PORTC=0xFF; // 刷屏用
}
}
void shanshuo() //PD.0的指示灯闪烁10次;
{
uchar j;
for(j=0;j<10;j++)
{
PORTD.0=~PORTD.0;
delay_ms(100);
}
PORTD.0=1;
} */
/* void chul(uchar chuli[][7]) //本来是用来写AD处理函数的
{
uchar i,j;
for(i=0;i<5;i++)
{
for(j=0;j<7;j++)
{
}
}
} */
/******************* 调速函数 (测试通过) **********************/
void TiaoSu(uchar jishu,uchar dianjh) //jishu 即为级数输入 dianjh 表示要调速的电机号 第0或者第1个;
{
if(dianjh==0)
{
OCR0_1=tiaos[jishu]; //jishu只能是0~5中间的某一个数字;
}
else //dianjh (电机号)只可以是0或者1,而且1是对应的计数器2产生的PWM波;
{
OCR2_1=tiaos[jishu];
}
}
/********************** 转向函数(测试通过) ******************/
void zhuanx(uchar zx) //高速左转向(1)右转向(2)低速左转(3)
{ //右转(4)低速前行(5)高速前行(6)急停(7)倒退(8)
switch (zx) //外加转弯灯,左转PB.0控制左边2个黄灯亮,右转PD.0控制的黄灯亮
{ //急停灯(红色)有PD.1控制
case 1:
PORTD.0=0; //高速左转
PORTC.0=0; //正转
PORTC.1=1;
PORTB.1=0; //反转
PORTB.2=1;
TiaoSu(3,0);
TiaoSu(3,1);
PORTB.5=1;
delay_ms(jiaod); //转向一定的角度
break;
case 2:
PORTB.5=0; //高速右转
PORTC.0=1; //反转
PORTC.1=0;
PORTB.1=1; //正转
PORTB.2=0;
TiaoSu(3,0);
TiaoSu(3,1);
PORTD.0=1;
delay_ms(jiaod);
break;
case 3: //低速左转(3)
PORTC.0=0; //正转
PORTC.1=1;
PORTB.1=0; //反转
PORTB.2=1;
TiaoSu(2,0);
TiaoSu(3,1);
PORTD.0=0;
PORTB.5=1;
delay_ms(jiaod);
break;
case 4: //低速右转(4)
PORTC.0=1; //反转
PORTC.1=0;
PORTB.1=1; //正转
PORTB.2=0;
TiaoSu(3,0);
TiaoSu(2,1);
PORTB.5=0;
PORTD.0=1;
delay_ms(jiaod);
break;
case 5: //低速前行(5)
PORTC.0=0; //正转
PORTC.1=1;
PORTB.1=1;
PORTB.2=0;
TiaoSu(1,0);
TiaoSu(1,1);
PORTB.5=0;
PORTD.0=0;
delay_ms(jiaod);
break;
case 6: //高速前行(6)
PORTC.0=0; //正转
PORTC.1=1;
PORTB.1=1;
PORTB.2=0;
TiaoSu(2,0);
TiaoSu(2,1);
PORTB.5=0;
PORTD.0=0;
delay_ms(jiaod);
break;
case 7: //急停
PORTC.0=0; //不转
PORTC.1=0;
PORTB.1=0;
PORTB.2=0;
TiaoSu(1,0);
TiaoSu(1,1);
PORTB.5=0;
PORTD.0=0;
PORTD.1=1;
break;
case 8:
PORTC.0=1; //正转
PORTC.1=0;
PORTB.1=0;
PORTB.2=1;
TiaoSu(3,0);
TiaoSu(3,1);
PORTB.5=1;
PORTD.0=1;
PORTD.1=1;
break;
}
}
/********************************* 判别函数 ***************************************/
void panduan(unsigned char adc_da[]) //将得到的AD转换值导入
{
unsigned char lukou=0; //lukou变量用于路口判断
//单个传感器检测到信号的情况
//2号传感器检测到信号,其余没有检测到信号
if((adc_da[0]<=low)&&(adc_da[1]<=low)&&(adc_da[2]>=high)&&(adc_da[3]<=low)&&(adc_da[4]<=low))
{
zhuanx(6); //调用高速前行函数
}
// 1号传感器检测到信号,其余没有检测到信号
if((adc_da[0]<=low)&&(adc_da[1]>=high)&&(adc_da[2]<=low)&&(adc_da[3]<=low)&&(adc_da[4]<=low))
{
zhuanx(3);//调用低速左转函数
}
// 0号传感器检测到信号,其余没有检测到
if((adc_da[0]>=high)&&(adc_da[1]<=low)&&(adc_da[2]<=low)&&(adc_da[3]<=low)&&(adc_da[4]<=low))
{
zhuanx(1); //调用高速左转函数
}
//3号传感器检测到信号,其余没有检测到信号
if((adc_da[0]<=low)&&(adc_da[1]<=low)&&(adc_da[2]<=low)&&(adc_da[3]>=high)&&(adc_da[4]<=low))
{
zhuanx(4); //调用低速右转
}
//4 号传感器检测到信号,其余没有检测到信号
if((adc_da[0]<=low)&&(adc_da[1]<=low)&&(adc_da[2]<=low)&&(adc_da[3]<=low)&&(adc_da[4]>=high))
{
zhuanx(2); //调用高速右转
}
// 1,2号检测到信号 其余没有 白线在两个传感器中间
// if((adc_da[0]<=low)&&(adc_da[1]>=high)&&(adc_da[2]>=high)&&(adc_da[3]<=low)&&(adc_da[4]<=low))
// {
// zhuanx(3); // 调用低速左转函数
// }
//0,1号检测到信号
if((adc_da[0]>=high)&&(adc_da[1]>=high)&&(adc_da[2]<=low)&&(adc_da[3]<=low)&&(adc_da[4]<=low))
{
zhuanx(1); //调用高速左转函数
}
//2,3号检测到信号
if((adc_da[0]<=low)&&(adc_da[1]<=low)&&(adc_da[2]>=high)&&(adc_da[3]>=high)&&(adc_da[4]<=low))
{
zhuanx(4); //调用低速右转函数
}
//3,4检测到信号
if((adc_da[0]<=low)&&(adc_da[1]<=low)&&(adc_da[2]<=low)&&(adc_da[3]>=high)&&(adc_da[4]>=high))
{
zhuanx(2);//调用高速右转函数
}
//0,1,2有信号 ( 折线检测 )
if((adc_da[0]>=high)&&(adc_da[1]>=high)&&(adc_da[2]>=high)&&(adc_da[3]<=low)&&(adc_da[4]<=low))
{
zhuanx(1);//左转折线 调用高速左转函数
}
//2,3,4有信号
if((adc_da[0]<=low)&&(adc_da[1]<=low)&&(adc_da[2]>=high)&&(adc_da[3]>=high)&&(adc_da[4]>=high))
{
zhuanx(2); //右转折线 调用高速右转函数
}
//1,2,3 有信号
if((adc_da[0]<=low)&&(adc_da[1]>=high)&&(adc_da[2]>=high)&&(adc_da[3]>=high)&&(adc_da[4]<=low))
{
zhuanx(6); //备用函数 调用高速直行函数
}
//0,1,2,3,4 都有信号 (路口判断)
if((adc_da[0]>=high)&&(adc_da[1]>=high)&&(adc_da[2]>=high)&&(adc_da[3]>=high)&&(adc_da[4]>=high))
{
switch (lukou) //走折线分支 选择函数
{
case 0:
zhuanx(6); //调用高速直行函数
break;
case 1:
zhuanx(6); //调用高速右转函数
break;
case 2:
zhuanx(2); //调用高速左转函数
break;
case 3:
zhuanx(1);//调用低速直行函数
break;
}
/* switch(lukou) //走曲线分支 选择函数
{
case 0:
zhuanx(6); //调用直行函数
break;
case 1:
zhuanx(1); //调用高速左转函数
break;
case 2:
zhuanx(6); // 调用高速直行函数
break;
case 3:
zhuanx(6); // 调用直行函数
break;
case 4:
zhuanx(5); // 调用直行函数
break;
}
*/
lukou++;
}
//出轨处理,以及停车
if((adc_da[0]<=low)&&(adc_da[1]<=low)&&(adc_da[2]<=low)&&(adc_da[3]<=low)&&(adc_da[4]<=low))
{
if(lukou>=3) //选择折线分支 时是4 曲线分支是5
{
zhuanx(7); //高速停车
}
else //非正常情况出轨 (1)反向出跑到
{
//AD转换的到的状态设置缓冲,如果有缓冲数组,可以设置找回路径函数
// panduan(adc_hc);
;
}
}
}
/*******************************************************************************************/
/********************************** 主函数 ******************************************/
void main(void)
{
PORTA=0x00; //端口初始化
DDRA=0x00;
PORTB=0x00;
DDRB=0xff;
PORTC=0x00;
DDRC=0xff;
PORTD=0x00;
DDRD=0xff;
TCCR0=0x6B; // Timer/Counter 0 initialization
TCNT0=0xFF; // Clock source: System Clock
OCR0=0x6f; // Clock value: 187.500 kHz
// Mode: Fast PWM top=FFh
// OC0 output: Non-Inverted PWM
TCCR1A=0x00; // Timer/Counter 1 initialization 未使用
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
ASSR=0x00; // Timer/Counter 2 initialization
TCCR2=0x6C; // Clock source: System Clock
TCNT2=0xFF; // Clock value: 187.500 kHz
OCR2=0x6f; // Mode: Fast PWM top=FFh OC2 output: Non-Inverted PWM
MCUCR=0x00; // External Interrupt(s) initialization
MCUCSR=0x00; // INT0: Off INT1: Off INT2: Off
TIMSK=0x82; // 定时器 计数器 中断初始化
ACSR=0x80; // 模拟比较器 关
SFIOR=0x00;
ADMUX=0x60; // ADC initialization Clock frequency: 750.000 kHz
ADCSRA=0xec; // ADC Voltage Reference: AVCC pin Free Running
SFIOR&=0x1F; // Only the 8 most significant bits of
// 全局中断使能
#asm("sei")
while (1)
{
panduan(adc_hc);
};
}
|
|