之前做的一个循迹小车,最后变成了一个遥控小车,可以采用电脑VB编写的画面控制,也可以采用在淘宝上买购买的串口触摸屏控制。小车已经被我拆了给我女做了一辆遥控小车。
附件中是程序代码。
VB控制智能小车.zip
(8.44 KB, 下载次数: 26)
智能小车遥控器.zip
(1.07 MB, 下载次数: 13)
智能小车C51.zip
(127.21 KB, 下载次数: 13)
YL-40 AD模块使用说明.pdf
(204.13 KB, 下载次数: 12)
串口HMI入门指南.pdf
(814.13 KB, 下载次数: 14)
单片机源程序如下:
- /**************************************
- #define N 1 //可一次接收数据量
- 中断0 外部中断
- 中断1 定时器/计数器0中断
- 中断2 外部中断1
- 中断3 定时器/计数器1中断
- 中断4 串口中断
- 中断5 定时器/计数器2中断
- 中断6 外部中断2(仅STC增强型8051系列单片机)
- 中断7 外部中断3(仅STC增强型8051系列单片机)
- 左转++ 右转--
- **************************************/
- #include <reg52.h>
- #include <intrins.h>
- #define uchar unsigned char // 0~255
- #define uint unsigned int //0~65535
- #define AddWr1 0x90 //AddWr1 地址 10010000
- #define AddRd1 0x91 //AddRd1 地址 10010001
- #define AddWr2 0x94 //AddWr2 地址 10010100
- #define AddRd2 0x95 //AddRd2 地址 10010101
- #define N 5 //可一次接收数据量
- void rs232_init(); //定义串口通信函数
- uchar flag,i; //删除无用变量
- uchar table[N]; //接收缓存数组
- uchar j=0; //接收计数器
- /*********总线端口********/
- sbit SCL1=P0^6; //串行时钟输入端
- sbit SDA1=P0^7; //串行数据输入端
- /*********功能端口********/
- sbit XJB=P0^5; //循迹开关
- /*********遥控端口********/
- sbit F=P1^0;//前进
- sbit SCB=P1^2;//刹车/后退
- sbit L=P1^3;//左转
- sbit R=P1^1;//右转
- /*********循迹端口********/
- sbit QL=P3^6;//前左雷达
- sbit QR=P3^5;//前右雷达
- sbit QM=P3^4;//前中雷达
- sbit XJL1=P3^7;//循迹L1
- sbit XJR1=P3^2;//循迹R1
- sbit XJL2=P1^6;//循迹L2
- sbit XJR2=P1^5;//循迹R2
- /*********驱动端口********/
- sbit ZFL=P0^0;//正反转L
- sbit SCL=P0^1;//刹车L
- sbit ZFR=P0^2;//正反转R
- sbit SCR =P0^3;//刹车R
- /*********转向端口********/
- sbit ZX=P2^7; //转向端口
- sbit SN=P2^6; //定义使能端口
- sbit OUT=P2^2; //定义OUT输出端口
- sbit HOME=P3^3; //方向回正标志
- signed int a=0,a1,a2;//当前位置,设定位置1,设定位置2 有符号 + -
- char code a3[]={0,67,111,222,333,444,556,667,778,889,1111,2000,
- -67,-111,-222,-333,-444,-556,-667,-778,-889,-1111,-2000};//位置数组
- uchar code jy[]={0x00,0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
- 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
- 0x01,0x02,0x05,0x0b,0x0f,0xf0,0xf1,0xf2,0xf3};
- uchar b;//差补值
- uchar c=0;//回正标志位
- uchar dir1;//方向判断开始标志
- uchar scb1;//刹车完成标志
- uchar snButton=0;//使能开关:0,自动;1,使能关闭
- uchar d1=0,d2=0,d=0;//左边速度
- uchar e1=0,e=0;//右边速度
- uchar forward=0,back=0; //前进后退标志位
- uint t1=0,t2=0,t3=0,t4=0,t5=0,t6=0,t7=0,t8=0,t9,t10,t11,t12;//定时器
- uchar z1,z2,z3,z4,z5,z6,z7,z8,z9,z10,z11,z12;
- uchar table2;//串口数据储存
- uchar jy1,jy2;//校验数据大小
- uchar autoN=0; //自动续航
- /*********************************
- t1 方向使能保时
- t2 前进锁定保时
- t3 后退锁定保时
- t4 备用
- t5 前进刹车保时
- t6 后退刹车保时
- t7
- t8
- t9
- t10
- t11
- *********************************/
- /********自动巡航状态*************/
- uchar l0,l1,l2,l3;//L雷达
- uchar m0,m1,m2,m3;//M雷达
- uchar r0,r1,r2,r3;//R雷达
- uchar lm0,lm1,lm2,lm3;//LM雷达
- uchar mr0,mr1,mr2,mr3;//MR雷达
- uchar lr0,lr1,lr2,lr3;//LR雷达
- uchar lmr0,lmr1,lmr2,lmr3;//LMR雷达
- uchar gear;//档位
- uchar speed;//速度
- uchar s1,s2,s3;//档位标志位
- uchar FS,BS;//前进刹车标志,后退刹车标志
- /*********延时4-5us********/
- void delay1()
- {;;}
- /*********延时 ********/
- void delay_1ms(uint z)
- {
- uint x,y;
- for(x=z;x>0;x--)
- for(y=speed;y>0;y--);
- }
- /*********开始信号********/
- void start() //开始信号
- {
- SDA1=1; //先把数据置1,再把时钟置1,后把数据置0. 以保证在时钟为1时,数据由高变低。
- delay1();
- SCL1=1; //时钟信号为1
- delay1();
- SDA1=0; //数据在时钟高电平时1-0则为开始信号。
- delay1();
- }
- /********* 停止信号 ********/
- void stop() //停止信号
- {
- SDA1=0; //先把数据置0,再把时钟置1,后把数据置1. 以保证在时钟为1时,数据由低变高。
- delay1();
- SCL1=1; //时钟信号为1
- delay1();
- SDA1=1; //数据在时钟高电平时0-1则为停止信号。
- delay1();
- }
- /*********应答 ********/
- void respons()//应答 相当于一个智能的延时函数
- {
- uchar i;
- SCL1=1;//scl高电平期间接收信号
- delay1();
- while((SDA1==1)&&(i<220))
- i++;
- SCL1=0;
- delay1();
- }
- /********* 初始化 ********/
- //void init() //初始化
- //{
- //SDA1=1;
- //delay1();
- //SCL1=1;
- //delay1();
- //}
- /*********用移位溢出的方式逐位输出数据********/
- void write_byte(uchar date) //写一字节数据
- {
- uchar i,temp;
- temp=date;
- for(i=0;i<8;i++)
- {
- temp=temp<<1; //左移一位 移出的一位在 CY 中
- SCL1=0;
- delay1();
- SDA1=CY;
- delay1();
- SCL1=1;//此时读取总线数据
- delay1();
- }
- SCL1=0;
- delay1();
- SDA1=1;
- delay1();
- }
- /*********L速度模拟量模块驱动 ********/
- void write_add(uchar address,uchar date)
- {
- start();
- write_byte(AddWr1); //10010000
- respons();
- write_byte(address);
- respons();
- write_byte(date);
- respons();
- stop();
- }
- /********R速度模拟量模块驱动 ********/
- void write_add1(uchar address,uchar date)
- {
- start(); //调用中断
- write_byte(AddWr2); //10010100
- respons();
- write_byte(address);
- respons();
- write_byte(date);
- respons();
- stop();
- }
- /***********初始化串口通信参数设定************/
- void rs232_init() //初始化串口通信参数设定
- {
- TMOD=0x20;
- TH1=0xfd;
- TL1=0xfd;
- TR1=1;
- SM0=0;//
- SM1=1;// SM0 SM1 0 1 工作方式1 10位异步收发,波特率可变(T1溢出率/n,n=32或16)
- REN=1;//先设定号工作方式,在打开允许接收
- EA=1;
- ES=1;
- }
- /***************************************************************************
- (1)SM0 SM1:串行口工作方式选择位。
- SM0 SM1 0 0 工作方式0 同步移位寄存器输入/输出,波特率固定为fosc/12
- SM0 SM1 0 1 工作方式1 10位异步收发,波特率可变(T1溢出率/n,n=32或16)
- SM0 SM1 1 0 工作方式2 11位异步收发,波特率固定为fosc/n,n=64或32)
- SM0 SM1 1 1 工作方式3 11位异步收发,波特率可变(T1溢出率/n,n=32或16)
- (2)SM2:多机通信控制器位。在方式0中,SM2必须设成0。在方式1中,当处于接收状态时,若
- SM2=1,则只有接收到有效的停止位“1”时,RI才能被激活成“1”(产生中断请求)。在方式2和方式
- 3中,若SM2=0,串行口以单机发送或接收方式工作,TI和RI以正常方式被激活并产生中断请求;若
- SM2=1,RB8=1时,RI被激活并产生中断请求。
- (3)REN:串行接受允许控制位。该位由软件置位或复位。当REN=1,允许接收;当REN=0,禁止接收。
- (4)TB0:方式2和方式3中要发送的第9位数据。该位由软件置位或复位。在方式2和方式3时,
- TB8是发送的第9位数据。在多机通信中,以TB8位的状态表示主机发送的是地址还是数据 :
- TB8=1表示地址,TB8=0表示数据。TB8还可用作奇偶校验位。
- (5)RB8:接收数据第9位。在方式2和方式3时,RB8存放接收到的第9位数据。RB8也可用作奇偶校验位。
- 在方式1中,若SM2=0,则RB8是接收到的停止位。在方式0中,该位未用。
- (6)TI:发送中断标志位。TI=1,表示已结束一帧数据发送,可由软件查询TI位标志,也可以向CPU申请
- 中断。
- 注意:TI在任何工作方式下都必须由软件清0。
- (7)RI:接收中断标志位。RI=1,表示一帧数据接收结束。可由软件查询RI位标志,也可以向CPU申请中断。
-
- 注意:RI在任何工作方式下也都必须由软件清0。
- 在AT89C51中,串行发送中断TI和接收中断RI的中断入口地址是同是0023H,因此在中断程序中
- 必须由软件查询TI和RI的状态才能确定究竟是接收还是发送中断,进而作出相应的处理。单片机复位时,
- SCON所有位均清0。
- *****************************************************************************/
- /***********左转弯控制***************/
- void Lpulse()//左转脉冲输出计数
- {
- if(a<2000)//左转极限
- {
- ZX=0;
- if(a1>a)
- {
- a++;
- OUT=~OUT;
- }
- }
- }
- /***********右转弯控制***************/
- void Rpulse()//右转脉冲输出计数
- {
- if(a>-2000)//右转极限
- {
- ZX=1;
- if(a1<a)
- {
- a--;
- OUT=~OUT;
- }
- }
- }
- /****************差速驱动***************************/
- void speed1()//
- {
- if(a>0)
- {
- if(a<2000)
- {
- d=speed -a/b; //a偏角数,b差速倍率
- e=speed;
- }
- else
- {
- d=speed;
- e=speed;
- }
- }
- if(a<0)
- {
- if(a>-2000)
- {
- d=speed;
- e=speed +a/b;
- }
- else
- {
- if(speed<150)
- {
- d=speed+20;
- e=0;
- }
- else
- {
- d=speed;
- e=0;
- }
- }
- }
- if(a==0)
- {
- d=speed;
- e=speed;
- }
- }
- /*************串口通信数据归零************************/
- void table1()
- {
- table[0]=0;
- }
- /*****************转向方向运算*****************************/
- /*****************前进刹车驱动*****************************/
- /*****************后退刹车驱动*****************************/
- /***************主程序******************/
- void main()
- {
- TMOD=0X11;//定时器0采用工作方式1
- TH0=(65536-200)/256;
- TL0=(65536-200)%256;//初值,定时
- TH2=(65536-50000)/256;//初值,定时1ms
- TL2=(65536-50000)%256;//
- T2CON=0;
- EA=1; //总中断打开
- ET0=1; //定时器0中断打开
- ET2=1; //定时器2中断打开
- TR0=1;//启动定时器0
- TR2=1;
- rs232_init(); //调用串口通信参数设定函数
- speed=90;
- b=22;
- jy1=1;
- while(1)
- {
- /*****************指令校验***************************/
- if(table[0]!=0)
- {
- for(jy1=0;jy1<43;jy1++)
- {
- if(jy[jy1]==table[0])
- {
- jy2=1;
- }
- }
- if(jy2==1&&jy1==42)//如果串口数据在列表中,校验成功,复位标志位jy2.
- {
- table[0]=table[0];
- SCL=1;
- SCR=1;
- }
- if(jy2==0&&jy1==42&&table[0]!=0) //如果校验失败,启动刹车
- {
- table1();
- F=1;
- SCB=1;
- forward=0;
- back=0;
- t2=0;
- t3=0;
- a1=0;
- dir1=1;
- speed=90;//刹车启动后设为一档
- b=22;//差速系数
- SCL=0;
- SCR=0;
- }
- }
- /**************转弯方向判断********************/
- if(dir1==1)
- {
- c=0;
- if(a1==a)
- {
- L=1;
- R=1;
- dir1=0;
- table1();
- }
- if(a1>a) //启动左转
- {
- L=0;
- R=1;
- }
- if(a1<a) //启动右转
- {
- L=1;
- R=0;
- }
- }
-
- /***************串口通信*************************/
- if(flag==1)
- {
- ES=0;
- for(j=0;j<N;j++) //回传接收数组
- {
- SBUF=table[j]; //把接收到的数据重新赋值给串口缓存寄存器
- while(!TI);
- TI=0;
- }
- j=0; //清零接收计数器
- ES=1;
- flag=0;
- }
- if(table[0]==0x01)//前进
- {
- F=0;
- SCB=1;
- t3=0;
- back=0;
- if(forward==1)//当前进锁定后,再次按下后退自动回正
- {
- c=1;//回正
- }
- }
- if(table[0]==0x02)//后退
- {
- F=1;
- SCB=0;
- t2=0;
- forward=0;
- if(back==1) //当后退锁定后,再次按下后退自动回正
- {
- c=1;
- }
- }
- if(table[0]==0x0f)//刹车
- {
- F=1;
- SCB=1;
- t2=0;
- t3=0;
- a1=0;
- dir1=1;
- speed=90;//刹车启动后设为一档
- b=22;//差速系数
- }
- if(table[0]==0xa0)//L3
- {
- a1=67;
- dir1=1;//方向判断
- }
- if(table[0]==0xa1)//L5
- {
- a1=111;
- dir1=1;//方向判断
- }
- if(table[0]==0xa2)//L10
- {
- a1=222;
- dir1=1;//方向判断
- }
- if(table[0]==0xa3)//L15
- {
- a1=333;
- dir1=1;//方向判断
- }
- if(table[0]==0xa4)//L20
- {
- a1=444;//设定角度
- dir1=1;//方向判断
- }
- if(table[0]==0xa5)//L25
- {
- a1=556;//设定角度
- dir1=1;//方向判断
- }
- if(table[0]==0xa6)//L30
- {
- a1=667;//设定角度
- dir1=1;//方向判断
- }
- if(table[0]==0xa7)//L35
- {
- a1=778;//设定角度
- dir1=1;//方向判断
- }
- if(table[0]==0xa8)//L40
- {
- a1=889;//设定角度
- dir1=1;//方向判断
- }
- if(table[0]==0xa9)//L45
- {
- a1=1000;//设定角度
- dir1=1;//方向判断
- }
- if(table[0]==0xaa)//L50
- {
- a1=1111;//设定角度
- dir1=1;//方向判断
- }
- if(table[0]==0xab)//L55
- {
- a1=1222;//设定角度
- dir1=1;//方向判断
- }
- if(table[0]==0xac)//L60
- {
- a1=1333;//设定角度
- dir1=1;//方向判断
- }
- if(table[0]==0xab)//L70
- {
- a1=1556;//设定角度
- dir1=1;//方向判断
- }
- if(table[0]==0xae)//L80
- {
- a1=1778;//设定角度
- dir1=1;//方向判断
- }
- if(table[0]==0xaf)//L90
- {
- a1=2000;//设定角度
- dir1=1;//方向判断
- }
- if(table[0]==0x05)//L微调
- {
- a=a+20;
- a1=0;
- dir1=1;
- table1();
- }
- if(table[0]==0x0b)//R微调
- {
- a=a-20;
- a1=0;
- dir1=1;
- table1();
- }
- if(table[0]==0x08)//回正
- {
- a1=0;
- dir1=1;
- }
- if(table[0]==0xb0)//R3
- {
- a1=-67;//设定角度
- dir1=1;//方向判断
- }
- if(table[0]==0xb1)//R3
- {
- a1=-111;//设定角度
- dir1=1;//方向判断
- }
- if(table[0]==0xb2)//R10
- {
- a1=-222;//设定角度
- dir1=1;//方向判断
- }
- if(table[0]==0xb3)//R15
- {
- a1=-333;//设定角度
- dir1=1;//方向判断
- }
- if(table[0]==0xb4)//R20
- {
- a1=-444;//设定角度
- dir1=1;//方向判断
- }
- if(table[0]==0xb5)//R25
- {
- a1=-556;//设定角度
- dir1=1;//方向判断
- }
- if(table[0]==0xb6)//R30
- {
- a1=-667;//设定角度
- dir1=1;//方向判断
- }
- if(table[0]==0xb7)//R35
- {
- a1=-778;//设定角度
- dir1=1;//方向判断
- }
- if(table[0]==0xb8)//R40
- {
- a1=-889;//设定角度
- dir1=1;//方向判断
- }
- if(table[0]==0xb9)//R45
- {
- a1=-1000;//设定角度
- dir1=1;//方向判断
- }
- if(table[0]==0xba)//R50
- {
- a1=-1111;//设定角度
- dir1=1;//方向判断
- }
- if(table[0]==0xbb)//R55
- {
- a1=-1222;//设定角度
- dir1=1;//方向判断
- }
- if(table[0]==0xbc)//R60
- {
- a1=-1333;//设定角度
- dir1=1;//方向判断
- }
- if(table[0]==0xbd)//R70
- {
- a1=-1556;//设定角度
- dir1=1;//方向判断
- }
- if(table[0]==0xbe)//R80
- {
- a1=-1778;//设定角度
- dir1=1;//方向判断
- }
- if(table[0]==0xbf)//R90
- {
- a1=-2000;//设定角度
- dir1=1;//方向判断
- }
- if(table[0]==0x12)//1档
- {
- speed=90;
- b=22;
- }
- if(table[0]==0x13)//2档
- {
- speed=120;
- b=17;
- }
- if(table[0]==0x14)//3档
- {
- speed=150;
- b=13;
- }
- if(table[0]==0xf0)//自动开始
- {
- autoN=1;
- }
- if(table[0]==0xf1)//自动关闭
- {
- autoN=0;
- }
- if(table[0]==0xf2)//使能手动关闭
- {
- snButton=1;
- }
- if(table[0]==0xf3)//使能自动
- {
- snButton=0;
- }
- /*************************************************/
- /*****************************************************/
- write_add(0x40,d1); //调用函数write_add(ox40,a) 在前面函数声明中,只是声明了变量并未作赋值
- write_add1(0x40,e1); //调用函数write_add(ox40,a) 在前面函数声明中,只是声明了变量并未作赋值
- d1=d;//左边速度
- e1=e;//右边速度
- /**************************************************/
- if(autoN==1)
- {
- scb1=0;//刹车完成标志rst
- if(QL==0&&QR==1)
- {
- a1=-1200;//设定角度
- dir1=1;//方向判断
- }
- if(QR==0&&QL==1)
- {
- a1=1200;//设定角度
- dir1=1;//方向判断
- }
- if(QR==0&&QL==0)
- {
- F=1;
- SCB=1;
- forward=0;
- back=0;
- t2=0;
- t3=0;
- a1=0;
- dir1=1;
- speed=90;//刹车启动后设为一档
- b=22;//差速系数
- }
- if(QM==0)
- {
- F=1;
- SCB=0;
- t2=0;
- forward=0;
- if(back==1) //当后退锁定后,再次按下后退自动回正
- {
- c=1;
- }
- if(QL==0&&QR==1)
- {
- a1=-1200;//设定角度
- dir1=1;//方向判断
- delay_1ms(400);
- }
- if(QR==0&&QL==1)
- {
- a1=1200;//设定角度
- dir1=1;//方向判断
- delay_1ms(400);
- }
- delay_1ms(800);
- }
- else
- {
- F=0;
- SCB=1;
- t3=0;
- back=0;
- if(forward==1)//当前进锁定后,再次按下后退自动回正
- {
- c=1;//回正
- }
- }
- if(QL==1&&QR==1&&a!=0)
- {
- a1=0;
- dir1=1;
- }
- }
- /****************************************************/
- if(F==0||t2>10)
- {
- t3=0;//后退自锁解除
- if((back==0&&XJB==1)||t2<10)//按下F按钮10以内启动点动模式
- {
- t3=0; //按压后退开关延时自锁取消
- speed1();//差速自动控制
- if(t2>10)//当前进按钮按下10以上时前进标志位置位
- {
- forward=1; //前进标志位置位
- }
- else //如果没有超过10,则不启动前进标志位
- {
- forward=0;
- }
- SCL=1;
- SCR=1; //关闭刹车
- if(a==0)
- {
- ZFL=1;
- ZFR=1;
- }
- if(a>0)
- {
- if(a<2000)
- {
- ZFL=1;
- ZFR=1;
- }
- else
- {
- ZFL=0;
- ZFR=1;
- }
- }
- if(a<0)
- {
- if(a>-2000)
- {
- ZFL=1;
- ZFR=1;
- }
- }
- }
-
- }
- /************倒车**********************/
- if(SCB==0||t3>10)
- {
- t2=0; //按压前进开关延时自锁取消
- if(forward==0)
- {
- speed1();//差速自动控制
- if(t3>10)
- {
- back=1; //后退标志位置位
- }
- else
- {
- back=0;
- }
- forward=0; //前进标志位复位
- SCL=1;
- SCR=1;
- t4=0;
- if(a==0)
- {
- ZFL=0;
- ZFR=0;
- }
- if(a>0)
- {
- if(a<2000)
- {
- ZFL=0;
- ZFR=0;
- }
- else
- {
- ZFL=1;
- ZFR=0;
- }
- }
- if(a<0)
- {
- if(a>-2000)
- {
- ZFL=0;
- ZFR=0;
- }
- else
- {
- ZFL=0;
- ZFR=0;
- }
- }
- }
- }
- if(F==1&&SCB==1&&t4<20) //当全部按钮释放,前进后退自锁取消时复位参数
- {
- t2=0;//前进自锁延时 复位
- t3=0;//后退自锁延时 复位
- d=0;//速度归零
- e=0;//
- d1=0;
- e1=0;
- if(back==1)
- {
- ZFL=1;
- ZFR=1;
- forward=0;
- back=0;
- }
- if(forward==1)
- {
- ZFL=0;
- ZFR=0;
- forward=0;
- back=0;
- }
- SCL=0;
- SCR=0;
- }
- else
- {
- if(t4>20)
- {
- SCL=1;
- SCR=1;
- ZFL=1;
- ZFR=1;
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
|