循迹小车设计(附代码)
循迹小车代码

#include<reg52.h>#define uchar unsigned char#define uint unsigned intuint a,d,y,z,h,q;sbit out1 = P0^0 ;//电机驱动输出控制管脚配置sbit out2 = P0^1 ;sbit out3 = P0^2 ;sbit out4 = P0^3 ;sbit in1 = P2^0;//循迹模块的信号输入管脚配置sbit in2 = P2^1;sbit in3 = P2^2;sbit in4 = P2^3;sbit in5 = P2^4;delay(uint a);int zuozhuan(uint z)//控制小车做左转动作(参数z和a可以用来调节左转时间,本程序设定//为不同参数表示每次调用程序左转时间相同不可变,没有调节转弯时间的功能){out1=1;out2=0;out3=0;out4=1;delay(a);}int youzhuan(uint y)//控制小车做右转动作(参数y和a可以用来调节右转时间,本程序设定//为不同参数表示每次调用程序右转时间相同不可变,没有调节转弯时间的功能){out1=0;out2=1;out3=1;out4=0;}int houtui(uint h)//控制小车可以使小车倒退行驶(参数功能与转弯类似){out1=0;out2=1;out3=0;out4=1;delay(a);out1=0;out2=0;out3=0;out4=0;delay(20);}int dengdai (uint d) //使小车停止当前所有动作,停止时间可调。
{out1=0;out2=0;out3=0;out4=0;delay(d);}void qianjin(q)//使小车向前行驶,行驶时间可调{out1=1;out2=0;out3=1;out4=0;delay(q);}void xunji(){P1=P1|0XF0; d elay(5);if(in1==0){dengdai();youzhuan(100);while(in3==1);}else if(in5==0){dengdai();zuozhuan(100);while(in3==1);}else if(in2==0){dengdai();youzhuan(30);}else if(in4==0){dengdai();zuozhuan(30);}else if(in3==0) {qianjin(20); }else {qianjin(20);}}int delay(uint a)//延时子函数{uint x,y;for(x=a;x>0;x--)for(y=110;y>0;y--);}void main(){delay(2000);while(1)xunji();}#include<reg52.h>#define uchar unsigned char#define uint unsigned int//D0-D7:f,b,a,e,d,h,c,g 共阴依次编码//74LS04反相器驱动数码管uchar code table[10] = {0x5F,0x42,0x9E,0xD6,0xC3,0xD5,0xDD,0x46,0xDF,0xD7}; uchar i = 0; //用于0-3数码管轮流显示uint j = 0; //计时的次数uint time=0; //计时uint pwm=16; //占空比uint speed; //调制PWM波的当前的值sbit R=P3^2; //右边传感器P3^2 sbit L=P3^3; //左边传感器P3^3 //电机驱动口定义sbit ENB=P1^0; //前轮电机停止控制使能sbit ENA=P1^1; //后轮控制调速控制端口sbit IN1=P1^2; //前轮sbit IN2=P1^3; //前轮sbit IN3=P1^4; //后轮sbit IN4=P1^5; //后轮void Init() {TMOD = 0x12; //定时器0用方式2,定时器1用方式1TH0=(256-200)/256; //pwmTL0=(256-200)/256;TH1 = 0x0F8; //定时2msTL1 = 0x30;EA = 1;ET0 = 1;ET1 = 1;TR0 = 1;TR1 = 1;}void tim0(void) interrupt 1 //产生PWM{speed ++;if(speed <= pwm) //pwm 就相当于占100的比例{ENA = 1;}else if(speed < 100){ENA = 0;}elsespeed = 0;}void time1() interrupt 3 //定时2ms{TH1 = 0x0F8;TL1 = 0x30;i =(i+1) % 4; //0-3循环j++;if(i == 0) //显示最低位数码管{P0 = 0x00; //段选清零防止乱码P0 = table[time%10]; //送段码信号}if(i == 1){P0 = 0x00;P0 = table[time/ 10% 10];}if(i == 2){P0 = 0x00;P0 = table[time/ 100% 10];}if(i == 3){P0 = 0x00;P0 = table[time/ 1000% 10];}P2 = ( 0x10 << i ); //送位选信号if(j == 500){time ++;//500次为1秒j = 0;}}void forward() //前进{IN2=1;IN1=0;}void back() //后退{IN2=0;IN1=1;}void left() //左转{ENB=1; //打开使能IN3=1;IN4=0;}void right() //右转{ENB=1; //打开使能IN3=0;IN4=1;}void stop() //停止{IN2=0;IN1=0;IN3=0;IN4=0;}void main(){Init(); //定时器初始化while(1){if(R==0 && L==1) //右传感器检测到黑线{right(); //右转forward();while(R==0 && L==1);}if(R==1 && L==0) //左传感器检测到黑线{left();forward();while(R==1 && L==0);}if(R==0 && L==0) //都检测到黑线则停止{stop();j = 0; //定时器仍在工作,计数时间清空}else //都没有检测到黑线{ENB = 0; //关闭转向控制forward();}}}。
智能小车循迹、避障、红外遥控C语言代码

智能小车循迹、避障、红外遥控C语言代码//智能小车避障、循迹、红外遥控 C 语言代码// 实现功能有超声波避障,红外遥控智能小车,红外传感器实现小车自动循迹, 1602 显示小车的工作状态,另有三个独立按键分别控制三种状态的转换// 注:每个小车的引脚配置都不一样,要注意引脚的配置,但是我的代码注释比较多,看起来比较容易一点#include <> #include <> #include"" #include <> #define uchar unsigned char #define uint unsigned int uchar ENCHAR_PuZh1[8]=" uchar ENCHAR_PuZh2[8]=" uchar ENCHAR_PuZh3[8]=" uchar ENCHAR_PuZh4[8]=" uchar ENCHAR_PuZh5[8]=" run back stop left right "; ";//1602 显示数组H. H. H. uchar ENCHAR_PuZh6[8]=" xunji "; uchar ENCHAR_PuZh7[8]=" bizhang"; uchar ENCHAR_PuZh8[8]=" yaokong"; #define HW P2 #define PWM /****************************** P1 //红外传感器引脚配置P2k 口/* L298N 管脚定义*/ 超声波引脚控制******************************/ sbit ECHO=P3A2; sbit TRIG=P3A3;///// 红外控制引脚配置 sbit sbituchar KEY2=P3A7; KEY 仁 P3M;state_total=3,state_2=0;// 2 为红外遥控 ucharuchar time_1 uchar 局变量 // 超声波接收引脚定义 // 超声波发送引脚定义// 红外接收器数据线 // 独立按键控制总状态控制全局变量 state_1,DAT; // 红外扫描标志位time_1=0,time_2=0;// 定时器1 中断全局变量控制转弯延时计数也做延时一次time,timeH,timeL,state=0;// 超声波测量缓冲变量count=0;//1602 显示计数兼红外遥控按键state_total =2 兼循迹按键state_total= 0 自动避障 state_total=10 为自动循迹模块 1 为自动避障模块 time_ 2 控制 PWM 脉冲计数state 为超声波状态检测控制全uint /**************************/ unsigned char IRC0M[7]; // 红外接收头接收数据缓存unsigned char Number,distance[4],date_data[8]={0,0,0,0,0,0,0,0}; /********* voidvoid voidIRC0M[2 ]存放的为数据 // 红外接收缓存变量 **/ IRdelay(char x); //x* 红外头专用 delay run(); back();void stop(); void left_90(); void left_180(); void right_90(); void delay(uint dat); //void init_test();void delay_100ms(uint ms) ;void display(uchar temp); void bizhang_test(); void xunji_test(); void hongwai_test();void Delay10ms(void);void init_test()// 定时器 0{ 1 外部中断 // 超声波显示驱动 0 1 延时初始化 TMOD=0x11; TH1=0Xfe; TL1=0x0c; TF0=0; TF1=0; ET0=1; ET1=1; EA=1;// 设置定时器 0 1 // 装入初值定时一次为工作方式 1 16 位初值定时器2000hz// 定时器 // 定时器 // 允许定时器// 允许定时器 0 方式 1 计数溢出标志 1 方式 1 计数溢出标志 0 中断溢出 1 中断溢出//开总中断 if(state_total==1)// 为超声波模块时初始化 {TRIG=0; ECHO=0; EX0=0; IT0=1;}if(state_total==2)// 发射引脚低电平 // 接收引脚低电平 // 关闭外部中断// 由高电平变低电平,触发外部中断 0// 红外遥控初始化{ IT1=1; EX1=1;TRIG=1;}del ay(60);} void main(){ uint i; delay(50); init_test(); TR1=1; LCD1602_Init() ; delay(50); while(state_2==0)// 外部中断 1 为负跳变触发 // 允许外部中断 1 // 为高电平 I/O 口初始化// 等待硬件操作// 开启定时器 1{if(KEY1==0){Delay10ms(); // 消除抖动 if(KEY1==0) {state_total=0; // 总状态定义 0 为自动循迹模块 1 为自动避障模块2 为红外遥控while((i<30)&&(KEY1==0))// 检测按键是否松开{Delay10ms(); i++;}i=0;}}if(TRIG==0){while((i<30)&&(TRIG==0))// 检测按键是否松开{Delay10ms(); i++;}i=0;}if(KEY2==0){while((i<30)&&(KEY2==0))// 检测按键是否松开{Delay10ms(); i++; }i=0;// 检测按键 s1 是否按下//检测按键s2是否按下障模块Delay10ms(); // 消除抖动 if(TRIG==0) { state_total=1; 2 为红外遥控//总状态定义 0 为自动循迹模块 1 为自动避// 检测按键 s3 是否按下障模块Delay10ms(); // 消除抖动 if(KEY2==0) { state_total=2; 2 为红外遥控// 总状态定义 0 为自动循迹模块1 为自动避}}} init_test();delay(50); // 等待硬件操作50us TR1=0; // 关闭定时器 1 if(state_total==1) {//SPEED=90; bizhang_test();} if(state_total==0) {// SPEED=98; 电平// 自动循迹速度控制// 自动循迹速度控制高电平持续次数占空比为10 的低电平高电平持续次数占空比为40 的低xunji_test(); }if(state_total== 2){//SPEED=98; // 自动循迹速度控制高电平持续次数占空比为40 的低电平hongwai_test(); }void 断号init0_suspend(void)2 外部中断0 4 串口中断外部中断 1timeH=TH0;timeL=TL0;state=1;EX0=0;}void 断号0{if(state_total==1) { TH0=0X00;TL0=0x00;}if(state_total==0) { TH0=0Xec;TL0=0x78;time_1++;interrupt 0 //3 为定时器 1 的中断号 1 定时器0 的中// 记录高电平次数//// 标志状态为// 关闭外部中断1,表示已接收到返回信号//3 为定时器 1 的中断号2 外部中断0 4 串口中断time0_suspend0(void) interrupt 1外部中断 1// 自动避障初值装入// 装入初值// 自动循迹初值装入// 装入初值定时一次200hz// 控制转弯延时计数1 定时器0 的中}}void IR_IN(void){unsigned char j,k,N=0;EX1 = 0; IRdelay(5); if (TRIG==1) { EX1 =1; return;}//确认IR 信号出现//等IR 变为高电平,跳过 9ms 的前导低电平信号。
lm393循迹小车代码

lm393循迹小车代码循迹小车涉及到硬件和代码两部分,下面给出一个基于Arduino的LM393循迹小车代码示例:```c#define IN1 2 //电机驱动IN1-4定义用D2,D3,D4,D5四个数字接口#define IN2 3 //其中D2、D3针对小车左侧电机;D4、D5针对小车右侧电机#define IN3 4#define IN4 5void setup() {pinMode(IN1, OUTPUT);pinMode(IN2, OUTPUT);pinMode(IN3, OUTPUT);pinMode(IN4, OUTPUT);}void loop() {int left = analogRead(A0); //读取左侧红外传感器的模拟值int right = analogRead(A1); //读取右侧红外传感器的模拟值if (left < 500 && right < 500) { //如果两侧均检测到黑线,则小车前进digitalWrite(IN1, HIGH);digitalWrite(IN2, LOW);digitalWrite(IN3, HIGH);digitalWrite(IN4, LOW);} else if (left < 500) { //左侧检测到黑线,则小车左转digitalWrite(IN1, HIGH);digitalWrite(IN2, LOW);digitalWrite(IN3, LOW);digitalWrite(IN4, LOW);} else if (right < 500) { //右侧检测到黑线,则小车右转digitalWrite(IN1, LOW);digitalWrite(IN2, LOW);digitalWrite(IN3, HIGH);digitalWrite(IN4, LOW);} else { //如果两侧均未检测到黑线,则小车停止digitalWrite(IN1, LOW);digitalWrite(IN2, LOW);digitalWrite(IN3, LOW);digitalWrite(IN4, LOW);}}```在此代码中,通过读取左右两侧的红外传感器信号来检测循迹情况,并根据检测结果控制小车的动作:前进、左转、右转、停止。
51的智能循迹小车代码

#include<reg52.h>#define sense P1 /*宏定义光电传感器端口*/#define input1 P0 /*左电机的IN1,IN2定义在P0口*/#define input2 P2 /*右电机的IN3,IN4及ENA,ENB定义在P2口*/ //宏定义电机的具体端口sbit MOTO1_INT1=P0^0;sbit MOTO1_INT2=P0^1;sbit MOTO1_ENA=P2^0;sbit MOTO2_INT3=P2^5;sbit MOTO2_INT4=P2^4;sbit MOTO2_ENB=P2^2;//宏定义传感器的具体端口sbit sense_L=P1^3;sbit sense_R=P1^6;//宏定义金属传感器端口sbit METAL=P1^1;//宏定义DELAY函数中的一些变量int Dtime1=20000;int Dtime2=2000;int i=0;unsigned char SIGNAL(void); //传感器信号分析函数void DELAY(void); //延时函数void main(){int a;MOTO1_INT1=1; //使车开始时运动MOTO1_INT2=0;MOTO1_ENA=1;MOTO2_INT3=1;MOTO2_INT4=0;MOTO2_ENB=1;while(1){if(METAL==1) //有金属时车停止DELAY();else{a=SIGNAL();switch(a){case 1:input2=0x25;break; //前进case 2:input2=0x24;break; //左转case 3:input2=0x21;break; //右转default:break;}}}}void DELAY() //延时函数{input2=0x20; //使驱动芯片的两个使能端为0,使两个电机停转for(i=0;i<Dtime1;i++); //实现延时,用DTIME控制input2=0x25; //使驱动芯片的两个使能端为1,使两个电机重新转for(i=0;i<Dtime2;i++);}unsigned char SIGNAL(){unsigned char Re;Re=sense&0x28;if(Re==40)return 1;//前进else if(Re==8)return 2;//左转else if(Re==32)return 3;//右转else return 1;//有错时前进}。
循迹小车程序代码

//(在MAIN中接受铁片颜色判断传感器的信号来赋值) unsigned char Light_Flag=0;//进入光引导区的标志(1) unsigned int cntTime_5Min=0;//时间周期数,用于 T0 精确定时 unsigned int cntTime_Plues=0; //霍尔开关产生的脉冲数 /*============================全局变量定义区 ============================*/ /*------------------------------------------------*/ /*-----------------通用延迟程序-------------------*/ /*------------------------------------------------*/ void delay(unsigned int time) { unsigned int i,j; for(j=0;j<time;j++) { for(i=0;i<60;i++) {;} } } /*-----------------------------------------------*/ /*-------------------显示控制模块----------------*/ /*-----------------------------------------------*/ /*数码管显示,显示铁片的数目(设接在P0,共阴)*/ void Display(unsigned char n) { char Numb[12]= {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x37,0x77}; P0=Numb[n]; } // time*0.5ms延时
四路循迹小车单片机代码

#include<reg52.h>#define uchar unsigned char#define uint unsigned intsbit p0_0=P0^0;sbit p0_7=P0^7;sbit p1_7=P0^7;sbit EN1=P1^2;//m1脉冲输入sbit EN2=P1^5;//m2脉冲输入//*****************************sbit HW1=P2^0;//加建sbit HW2=P2^1;//减键m1//***************************sbit p2_2=P2^2;sbit p2_3=P2^3; // m2//*********************sbit p1_3=P1^3;sbit p1_4=P1^4;//M2转向组合//******************************sbit p1_1=P1^1;sbit p1_0=P1^0;//M1转向组合//*****M1***********************************************uint t=100;//载波周期uint time0; // 低电平可按键调整量我这里是把周期和低电平设为一个是程序内可调,一个是程序外可调而高电平是死的,也可以反之是一样的uint time1; // 高点平基准量uint timeing0;//立即低电平动态变量uint timeing1; //立即高电平动态变量//*****M2****************//uint t=500;//载波周期uint time_0; // 低电平可按键调整量我这里是把周期和低电平设为一个是程序内可调,一个是程序外可调而高电平是死的,也可以反之是一样的uint time_1; // 高点平基准量uint timeing_0;//立即低电平动态变量uint timeing_1; //立即高电平动态变量//********传感器中间变量定义****************************uchar middate,middate1,middate2;//********************************//void delay(uint z) //延时1ms程序//{//uint x,a,b;//for (x=0;x<z;x++)//{//for(b=120;b>0;b--)//{//for(a=3;a>0;a--);// }// }//// }void stop() //停止函停止HW1=HW2=0;{EA=0;//禁止中断EN1=0;EN2=0;}void goon()//直着走HW1=1=HW2;{EA=1;time0=50;time_0=50;time1=50;time_1=50;}void left()//向左转弯HW1=1;HW2=0; 修改定时数据,实现实时PWM调制{EA=1;//********* time_0=50;time_1=50;// //通过调整左轮的转速来调整转弯力度,这里要配合传感器实时采集才行time0=(time0-1);time1=(t-time0);//***********************timeing0=0;timeing1=0;}void right()//向右转弯HW1=0;HW2=1;{EA=1;//***************time0=50;time1=50;//通过调整右轮的转速来调整转弯力度,这里要配合传感器实时采集才行time_0=(time_0-1);time_1=(t-time_0);//******************timeing_0=0;timeing_1=0;//太关键了!这一步,因为不加的话,当再一次的time0被修改时timeing0,和timeing1不为0//所以才会发生错误,表现为波形时断时续,而且有尖锋脉冲,这都是没有在刷新TIME0的同时刷新tineing的后果//没想到很简单的一点事竟差点酿成PWM做不出来!真是有有教训了//}void InitTimer0(void) //10us 定时器初始化设置函数{TMOD = 0x01;TH0 =0xff;TL0 =0xf7;EA = 1;ET0 = 1;TR0 = 1;}void main(void)//主函数{P2=0x0f;InitTimer0(); //10 us(可变啊,根据不同的精准度和频率要求)//************p1_0=0;p1_1=1;//M2//决策转向p1_3=1;p1_4=0;//M1//************time0=50;//***************************************************************************** *********************************//time1=50; ////time_0=50; ////time_1=50; //通知////L293B的8脚是要接>5V的,16脚要接5V,但是别人的不是这样的,我是看了手册,和失败后这样做的//////这里我用了周期是1000us的但是我的定时器是10us一次的所以我这里取t=100;表示我把周期分成100份////占空比(q)=高电平(time1)/周期(t);故而time1/100=占空比;////电压(u)=占空比*最大电压(Um)故而我的输出电压函数为:U0=Um*q =time1/100*5V(这里我用的是5v电压=Um)// // 根据上述公式可以算出MCU输出电压:例如:我要输出1.5V电压只要让time1=30即可,当然time0=70(保证频率不变) ///我要输出3V只要让time1=60,tim0=40;即可呵呵呵呵// //大概这也就是数模转换的原理吧/////2010年10月24日下午与天津第四项目部宿舍////***************************************************************************** *********************************//while(1) //主循环{//***********************middate=0x00;middate1=0x00;middate2=0x00;middate1=HW1;//传感器信号采集后处理middate2=HW2;CY=0;middate2=(middate2<<1) ;middate=(middate1+middate2) ;// ****************************switch(middate)//转向关键步函数{case 3:{stop();break;}//停止>>>>>>>>>>>>>>HW1=0=HW2;case 1:{left();break;}//左转>>>>>>>>>>>>>>HW1=1;HW2=0;case 2:{right();break;}//右转>>>>>>>>>>>>>>HW1=0;HW2=1;case 0:{goon();break;}//直行>>>>>>>>>>>>>>HW1=1=HW2;}}}void Timer0Interrupt(void) interrupt 1/定时器中断函数生成PWM,接口单元为:time0(PWM1号低电平时间),time1(PWM1号高电平时间),time_0(PWM2号低电平时间),time_1(PWM2号高电平时间),t(周期){//MCU:P1.2是第一路PWM,P1.5是第二路PWMif(time0==timeing0){if(time1!=timeing1){//高电平时间段TH0 =0xff;TL0 =0xf7;EN1=1;timeing1++;}//中断子函数(定时器参量修改)}elseif(time0!=timeing0){TH0 =0xff;EN1=0;//低电平时间段timeing0++;}if(time0==timeing0){if(time1==timeing1){timeing0=0;timeing1=0;}}//****************M2的******************************************************************************* *****************************************************************************if(time_0==timeing_0){if(time_1!=timeing_1){//高电平时间段TH0 =0xff;TL0 =0xf7;EN2=1;timeing_1++;}//中断子函数(定时器参量修改)}elseif(time_0!=timeing_0){TH0 =0xff;TL0 =0xf7;EN2=0;//低电平时间段timeing_0++;}if(time_0==timeing_0){if(time_1==timeing_1){timeing_1=0; }}。
循迹小车程序 带注释

left_qian;
//左边电机前进
right_hou;
//右边电机后退
}
else if((left_2==1)&&(left_1==1)&&(righ_1==1)&&(righ_2==0)) //右转弯 幅度大
{
zkb_l=100;
//左边占空比100%
zkb_r=100;
//右边占空比100%
left_qian;
/*********************************************************************/
void timer0() interrupt 1
{
TH0=0xff;
//定时器0高8位初值(65536-100)/256;
TL0=0x9c;
//定时器0低8位初值(65536-100)%256;
//右边占空比20%
left_qian;
//左边电机前进
right_qian;
//右边电机前进
}
else if((left_2==1)&&(left_1==1)&&(righ_1==0)&&(righ_2==0)) //右转弯 幅度中
{
zkb_l=100;
//左边占空比100%
zkb_r=40;
//右边占空比40%
//左转弯 幅度大
{
zkb_l=100;
//左边占空比100%
zkb_r=100;
//右边占空比100%
left_hou;
//左边电机后退
right_qian;
//右边电机前进
循迹小车代码

#include<reg52.h>#define uchar unsigned char#define uint unsigned intuint a,d,y,z,h,q;sbit out1 = P0^0 ;//电机驱动输出控制管脚配置sbit out2 = P0^1 ;sbit out3 = P0^2 ;sbit out4 = P0^3 ;sbit in1 = P2^0;//循迹模块的信号输入管脚配置sbit in2 = P2^1;sbit in3 = P2^2;sbit in4 = P2^3;sbit in5 = P2^4;delay(uint a);int zuozhuan(uint z)//控制小车做左转动作(参数z和a可以用来调节左转时间,本程序设定//为不同参数表示每次调用程序左转时间相同不可变,没有调节转弯时间的功能){out1=1;out2=0;out3=0;out4=1;delay(a);}int youzhuan(uint y)//控制小车做右转动作(参数y和a可以用来调节右转时间,本程序设定//为不同参数表示每次调用程序右转时间相同不可变,没有调节转弯时间的功能){out1=0;out2=1;out3=1;out4=0;}int houtui(uint h)//控制小车可以使小车倒退行驶(参数功能与转弯类似){out1=0;out2=1;out3=0;out4=1;delay(a);out1=0;out2=0;out3=0;out4=0;delay(20);}int dengdai (uint d) //使小车停止当前所有动作,停止时间可调。
{out1=0;out2=0;out3=0;out4=0;delay(d);}void qianjin(q)//使小车向前行驶,行驶时间可调{out1=1;out2=0;out3=1;out4=0;delay(q);}void xunji(){P1=P1|0XF0; d elay(5);if(in1==0){dengdai();youzhuan(100);while(in3==1);}else if(in5==0){dengdai();zuozhuan(100);while(in3==1);}else if(in2==0){dengdai();youzhuan(30);}else if(in4==0){dengdai();zuozhuan(30);}else if(in3==0) {qianjin(20); }else {qianjin(20);}}int delay(uint a)//延时子函数{uint x,y;for(x=a;x>0;x--)for(y=110;y>0;y--);}void main(){delay(2000);while(1)xunji();}#include<reg52.h>#define uchar unsigned char#define uint unsigned int//D0-D7:f,b,a,e,d,h,c,g 共阴依次编码//74LS04反相器驱动数码管uchar code table[10] = {0x5F,0x42,0x9E,0xD6,0xC3,0xD5,0xDD,0x46,0xDF,0xD7}; uchar i = 0; //用于0-3数码管轮流显示uint j = 0; //计时的次数uint time=0; //计时uint pwm=16; //占空比uint speed; //调制PWM波的当前的值sbit R=P3^2; //右边传感器P3^2 sbit L=P3^3; //左边传感器P3^3 //电机驱动口定义sbit ENB=P1^0; //前轮电机停止控制使能sbit ENA=P1^1; //后轮控制调速控制端口sbit IN1=P1^2; //前轮sbit IN2=P1^3; //前轮sbit IN3=P1^4; //后轮sbit IN4=P1^5; //后轮void Init() {TMOD = 0x12; //定时器0用方式2,定时器1用方式1TH0=(256-200)/256; //pwmTL0=(256-200)/256;TH1 = 0x0F8; //定时2msTL1 = 0x30;EA = 1;ET0 = 1;ET1 = 1;TR0 = 1;TR1 = 1;}void tim0(void) interrupt 1 //产生PWM{speed ++;if(speed <= pwm) //pwm 就相当于占100的比例{ENA = 1;}else if(speed < 100){ENA = 0;}elsespeed = 0;}void time1() interrupt 3 //定时2ms{TH1 = 0x0F8;TL1 = 0x30;i =(i+1) % 4; //0-3循环j++;if(i == 0) //显示最低位数码管{P0 = 0x00; //段选清零防止乱码P0 = table[time%10]; //送段码信号}if(i == 1){P0 = 0x00;P0 = table[time/ 10% 10];}if(i == 2){P0 = 0x00;P0 = table[time/ 100% 10];}if(i == 3){P0 = 0x00;P0 = table[time/ 1000% 10];}P2 = ( 0x10 << i ); //送位选信号if(j == 500){time ++;//500次为1秒j = 0;}}void forward() //前进{IN2=1;IN1=0;}void back() //后退{IN2=0;IN1=1;}void left() //左转{ENB=1; //打开使能IN3=1;IN4=0;}void right() //右转{ENB=1; //打开使能IN3=0;IN4=1;}void stop() //停止{IN2=0;IN1=0;IN3=0;IN4=0;}void main(){Init(); //定时器初始化while(1){if(R==0 && L==1) //右传感器检测到黑线{right(); //右转forward();while(R==0 && L==1);}if(R==1 && L==0) //左传感器检测到黑线{left();forward();while(R==1 && L==0);}if(R==0 && L==0) //都检测到黑线则停止{stop();j = 0; //定时器仍在工作,计数时间清空}else //都没有检测到黑线{ENB = 0; //关闭转向控制forward();}}}。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
基于单片机的智能寻迹小车
一.方案设计与论证
1.1控制模块采用STC89C52单片机
设计中采用了一款十分常用的51系列单片机作为处理器,特点是价格低廉、使用方便,且可与其他处理器进行通讯。
系统时钟:晶振频率1/12,本设计采用12M晶振,因此系统时钟为1us。
I/O口资源:4个通用8位准双向I/O口(P0、P1、P2、P3,其中P3为特殊功能口)。
通讯:一对全双工串行通讯口(P3.0、P3.1),可与其他单片机或上位机进行通讯。
中断:2个外部中断(/INT0、/INT1),2个定时器中断(T0、T1),1个串行通讯中断,共5个中断资源并有2级中断优先级可供配置。
ROM:该单片机提供8K的ROM供用户编写程序。
1.2 寻黑胶带方案
方案一、
可见光发光二级管组成的发射-接收电路。
这种方案的缺点在于其他环境光源会对光敏二极管的工作产生很大干扰,一旦外界光亮条件改变,很可能造成误判和漏判;虽然采取超高亮发光管可以降低一定的干扰,但这又将增加额外的功率损耗。
方案二、
反射式红外发射-接收器。
由于采用红外管代替普通可见光管,可以降低环境光源干扰,大大减小了误判和漏判的可能性。
经过比较选择方案二。
电机的选择和控制
方案一:
采用电阻网络或数字电位器调整电动机的分压,从而达到调速的目的。
但是电阻网络只能实现有级调速,而数字电阻元件价格比较昂贵。
更主要的问题在于一般电动机的电阻比较小,但电流比较大;分压不仅降低了效率,而且实现很困难。
方案二:
采用继电器对电动机的开或关进行控制,通过开关的切换对电动机的转速进行控制,此方案的优点是电路比较简单,缺点是继电器的响应时间慢,机械结构易损坏,寿命较短、可靠性不高。
方案三:
采用由达林顿管组成的H型PWM电路。
用单片机控制达林顿管使之工作在占空比可调的开关状态,精准调整电动机转速。
这种电路由于工作在管子的饱和截至状态下,效率非常高;H 型电路保证了可以简单的实现转速的控制;电子开关的速度很快,稳定性也较之继电器高的多,是一种广泛采用的PWM调速技术。
经过比较选择方案三。
二.硬件电路设计
2.1反射式红外发送接收对管的使用
本设计采用的是tcrt5000反射式光电传感器,原理图如下,传感器采用高
发射功率红外光电二极管和高灵敏光电晶体管组成,输出信号经施密特电路整形,稳定可靠。
其工作电压为DC3V~5.5V,推荐工作电压为5V,检测距离为1mm~8mm,焦点距离为2.5mm。
传感器检测到黑线输出为高电平,发光二极管为熄灭状态;检测到白色时输出低电平,发光二极管被点亮。
2.2 电源模块
小车的供电采用的是由两节输出电压为3.7的可充电锂电池串联的电池组,选用锂电池的原因在于锂电池可以多次充电,输出电流大可保证电机正常工作
2.3 电机驱动电路
小车采用两轮驱动,另外一个为万向轮,为了使小车灵活运动,要求小车在速度和方向上能够大范围调整。
为此我们选择了控制可靠、便于单片机控制的脉宽调制专用集成电路L298N,一片L298N可驱动两个直流电机。
L298N为Multiwatt15封装,工作电压最高为50V,通过电流达5A。
既可以与整个系统使用同一电源,又有足够的输出电流驱动电机。
L298N 驱动芯片上集成有5V稳压芯片,可从L298N上连线给单片机及红外对管供电。
我们用单片机产生PWM波,通过调节占空比来控制电机的转速。
A、B连接小车的左电机,C、D连接小车的右电机。
左右电机速度相同时可实现小车的前进或后退;速度不同时可实现小车的转弯;当两个电机反向等速运转时,小车可原地转圈。
循迹控制程序设计
整体电路如下:
车前从左至右安装3个红外发送接收对管。
(白色输出0,黑色输出1)
源代码如下:
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
uchar x3,x4;
uint zkb1,zkb2,t=0;
sbit d0=P1^0; /*d1到d3为控制电机的输出口*/ sbit d1=P1^1;
sbit d2=P1^2;
sbit d3=P1^3;
sbit d5=P1^5; /*d5到d7为红外信号输入口*/ sbit d6=P1^6;
sbit d7=P1^7;
sbit ENA=P0^0; /*定义使能端ENA ENB接口*/ sbit ENB=P0^1;
void qianjin() //前进
{
d0=0;
d1=1;
d2=0;
d3=1;
zkb1=50;
zkb2=50;
}
void back()
{
d0=1;
d1=0;
d2=1;
d3=0;
zkb1=40;
zkb2=40;
}
void turn_left1() //1级左转
{
d0=0;
d1=0;
d2=0;
d3=1;
zkb1=0;
zkb2=30;
}
void turn_left2() //2级左转
{
d0=0;
d1=0;
d2=0;
d3=1;
zkb1=0;
zkb2=50;
}
void turn_right1() //1级右转
{
d0=0;
d1=1;
d2=0;
d3=0;
zkb1=30;
zkb2=0;
}
void turn_right2()//2级右转
{
d0=0;
d1=1;
d2=0;
d3=0;
zkb1=50;
zkb2=0;
}
void xunji() /*检测到黑线输出为高电平1,检测到白色为低电平0*/ {
if((d5==1&&d6==1&&d7==1)||(d5==0&&d6==1&&d7==0))
qianjin();
if(d5==0&&d6==0&&d7==0)
back();
if(d5==0&&d6==1&&d7==1)//右边压黑线
turn_right1();
if(d5==0&&d6==0&&d7==1)
turn_right2();
if(d5==1&&d6==1&&d7==0) //左边压黑线
turn_left1();
if(d5==1&&d6==0&&d7==0)
turn_left2();
}
void init()//初始化函数;
{
TMOD=0X01;
TH0=(65536-100)/256; //设置计时时间长度100us
TL0=(65536-100)%256;
ET0=1;
EA=1;
TR0=1;
ENA=1;
ENB=1;
d0=0;
d1=1;
d2=0;
d3=1;
}
void main()
{
init();
while(1) //主函数等待中断请求;
{
xunji();
}
}
void time0() interrupt 1
{
TH0=(65536-100)/256; //设置计时时间长度
TL0=(65536-100)%256;
if(t<=zkb1)
ENA=1;
else
ENA=0;
if(t<=zkb2)
ENB=1;
else
ENB=0;
t++;
if(t>=50)//周期为5ms
t=0;
}。