网站开发都用什么浏览器,网站设计的创新点,湖南营销型网站建设,深圳网站免费制作目录
1. 蓝牙控制小车
2. 蓝牙控制并测速小车
3. wifi控制测速小车
4. 4g控制小车
5. 语音控制小车 1. 蓝牙控制小车
使用蓝牙模块#xff0c;串口透传蓝牙模块#xff0c;又叫做蓝牙串口模块
串口透传技术#xff1a;
透传即透明传送#xff0c;是指在数据的传输过…目录
1. 蓝牙控制小车
2. 蓝牙控制并测速小车
3. wifi控制测速小车
4. 4g控制小车
5. 语音控制小车 1. 蓝牙控制小车
使用蓝牙模块串口透传蓝牙模块又叫做蓝牙串口模块
串口透传技术
透传即透明传送是指在数据的传输过程中通过无线的方式这组数据不发生任何形式的改变仿 佛传输过程是透明的一样同时保证传输的质量原封不动地到了最终接收者手里。以太网蓝牙Zigbee, GPRS 等模块玩法一样对嵌入式程序员来说不需要关心通讯模块内部数据 及协议栈工作原理只要通过串口编程获得数据即可 代码实现
//main.c
#include motor.h
#include delay.h
#include uart.hvoid main()
{UartInit();while(1){stop();}
}//uart.c
#include reg52.h
#include motor.h
#include string.h
#include delay.h
sbit D5 P3^7;
#define SIZE 12sfr AUXR 0x8E;
char buffer[SIZE];void UartInit(void) //9600bps11.0592MHz
{AUXR 0x01;SCON 0x50; //配置串口工作方式1REN使能接收TMOD 0x0F;TMOD | 0x20;//定时器1工作方式位8位自动重装TH1 0xFD;TL1 0xFD;//9600波特率的初值TR1 1;//启动定时器EA 1;//开启总中断ES 1;//开启串口中断
}//M1qian M2 hou M3 zuo M4 you
void Uart_Handler() interrupt 4
{static int i 0;//静态变量被初始化一次char tmp;if(RI)//中断处理函数中对于接收中断的响应{RI 0;//清除接收中断标志位tmp SBUF;if(tmp M){i 0;}buffer[i] tmp;//灯控指令if(buffer[0] M){switch(buffer[1]){case 1:goForward();Delay10ms();break;case 2:goBack();Delay10ms();break;case 3:goLeft();Delay10ms();break;case 4:goRight();Delay10ms();break;default:stop();break;}}if(i 12) {memset(buffer, \0, SIZE);i 0;}}}//motor.c
#include reg52.hsbit RightCon1A P3^2;
sbit RightCon1B P3^3;sbit LeftCon1A P3^4;
sbit LeftCon1B P3^5;void goForward()
{LeftCon1A 0;LeftCon1B 1;RightCon1A 0;RightCon1B 1;
}void goRight()
{LeftCon1A 0;LeftCon1B 1;RightCon1A 0;RightCon1B 0;
}void goLeft()
{LeftCon1A 0;LeftCon1B 0;RightCon1A 0;RightCon1B 1;
}void goBack()
{LeftCon1A 1;LeftCon1B 0;RightCon1A 1;RightCon1B 0;
}void stop()
{LeftCon1A 0;LeftCon1B 0;RightCon1A 0;RightCon1B 0;
}//delay.c#include intrins.hvoid Delay10ms() //11.0592MHz
{unsigned char i, j;i 18;j 235;do{while (--j);} while (--i);
}void Delay1000ms() //11.0592MHz
{unsigned char i, j, k;_nop_();i 8;j 1;k 243;do{do{while (--k);} while (--j);} while (--i);
}
2. 蓝牙控制并测速小车
原理运用上面讲到的蓝牙模块和测速模块
代码实现
//main.c
#include motor.h
#include delay.h
#include uart.h
#include reg52.h
#include time.h
#include stdio.h
#include Oled.hsbit speedIO P3^2;//外部中断0
unsigned int speedCnt 0; //统计格子脉冲次数
extern unsigned int speed;//速度
extern char signal; //主程序发速度数据的通知
char speedMes[24]; //主程序发送速度数据的字符串缓冲区void Ex0Init()
{EX0 1;//允许中断//EA 1;在串口初始化函数中已经打开了总中断IT0 1;//外部中断的下降沿触发
}void main()
{Time0Init();//定时器0初始化UartInit();//串口相关初始化//外部中断初始化Ex0Init();Oled_Init();Oled_Clear();while(1){if(signal){//定时器1s到点把signal置一主程序发送速度sprintf(speedMes,speed:%d cm/s,speed);//串口数据的字符串拼装speed是格子每个格子1cmSendString(speedMes);//速度发出去signal 0;//清0speed,下次由定时器1s后的中断处理中再置一}Oled_Show_Str(2,2,speedMes);}
}void speedHandler() interrupt 0 //外部中断处理函数
{speedCnt;//码盘转动了一个格子
}//uart.c
#include reg52.h
#include motor.h
#include string.h
sbit D5 P3^7;
#define SIZE 12sfr AUXR 0x8E;
char buffer[SIZE];void UartInit(void) //9600bps11.0592MHz
{AUXR 0x01;SCON 0x50; //配置串口工作方式1REN使能接收TMOD 0x0F;TMOD | 0x20;//定时器1工作方式位8位自动重装TH1 0xFD;TL1 0xFD;//9600波特率的初值TR1 1;//启动定时器EA 1;//开启总中断ES 1;//开启串口中断
}void SendByte(char mydata)
{SBUF mydata;while(!TI);TI 0;
}void SendString(char *str)
{while(*str ! \0){SendByte(*str);str;}
}//M1qian M2 hou M3 zuo M4 you
void Uart_Handler() interrupt 4
{static int i 0;//静态变量被初始化一次char tmp;if(RI)//中断处理函数中对于接收中断的响应{RI 0;//清除接收中断标志位tmp SBUF;if(tmp M){i 0;}buffer[i] tmp;//灯控指令if(buffer[0] M){switch(buffer[1]){case 1:goForward();break;case 2:goBack();break;case 3:goLeft();break;case 4:goRight();break;default:stop();break;}}if(i 12) {memset(buffer, \0, SIZE);i 0;}}}//motor.c
#include reg52.hsbit RightCon1A P3^7;
sbit RightCon1B P3^3;sbit LeftCon1A P3^4;
sbit LeftCon1B P3^5;void goForward()
{LeftCon1A 0;LeftCon1B 1;RightCon1A 0;RightCon1B 1;
}void goRight()
{LeftCon1A 0;LeftCon1B 1;RightCon1A 0;RightCon1B 0;
}void goLeft()
{LeftCon1A 0;LeftCon1B 0;RightCon1A 0;RightCon1B 1;
}void goBack()
{LeftCon1A 1;LeftCon1B 0;RightCon1A 1;RightCon1B 0;
}void stop()
{LeftCon1A 0;LeftCon1B 0;RightCon1A 0;RightCon1B 0;
}//time.c
#include motor.h
#include reg52.hextern unsigned int speedCnt;
unsigned int speed;
char signal 0;
unsigned int cnt 0;void Time0Init()
{//1. 配置定时器0工作模式位16位计时TMOD 0x01;//2. 给初值定一个0.5出来TL00x33;TH00xFE;//3. 开始计时TR0 1;TF0 0;//4. 打开定时器0中断ET0 1;//5. 打开总中断EAEA 1;
}void Time0Handler() interrupt 1
{cnt; //统计爆表的次数. cnt1的时候报表了1//重新给初值TL00x33;TH00xFE;if(cnt 2000){//爆表2000次经过了1ssignal 1;cnt 0; //当100次表示1s重新让cnt从0开始计算下一次的1s//计算小车的速度也就是拿到speedCnt的值speed speedCnt;speedCnt 0;//1秒后拿到speedCnt个格子就能算出这1s的速度格子清零}}//oled.c
#include reg52.h
#include intrins.h
#include Oledfont.hsbit scl P1^2;
sbit sda P1^3;void IIC_Start()
{scl 0;sda 1;scl 1;_nop_();sda 0;_nop_();
}void IIC_Stop()
{scl 0;sda 0;scl 1;_nop_();sda 1;_nop_();
}char IIC_ACK()
{char flag;sda 1;//就在时钟脉冲9期间释放数据线_nop_();scl 1;_nop_();flag sda;_nop_();scl 0;_nop_();return flag;
}void IIC_Send_Byte(char dataSend)
{int i;for(i 0;i8;i){scl 0;//scl拉低让sda做好数据准备sda dataSend 0x80;//1000 0000获得dataSend的最高位给sda_nop_();//发送数据建立时间scl 1;//scl拉高开始发送_nop_();//数据发送时间scl 0;//发送完毕拉低_nop_();//dataSend dataSend 1;}
}void Oled_Write_Cmd(char dataCmd)
{// 1. start()IIC_Start();// // 2. 写入从机地址 b0111 1000 0x78IIC_Send_Byte(0x78);// 3. ACKIIC_ACK();// 4. cotrol byte: (0)(0)000000 写入命令 (0)(1)000000写入数据IIC_Send_Byte(0x00);// 5. ACKIIC_ACK();//6. 写入指令/数据IIC_Send_Byte(dataCmd);//7. ACKIIC_ACK();//8. STOPIIC_Stop();
}void Oled_Write_Data(char dataData)
{// 1. start()IIC_Start();// // 2. 写入从机地址 b0111 1000 0x78IIC_Send_Byte(0x78);// 3. ACKIIC_ACK();// 4. cotrol byte: (0)(0)000000 写入命令 (0)(1)000000写入数据IIC_Send_Byte(0x40);// 5. ACKIIC_ACK();///6. 写入指令/数据IIC_Send_Byte(dataData);//7. ACKIIC_ACK();//8. STOPIIC_Stop();
}void Oled_Init(void){Oled_Write_Cmd(0xAE);//--display offOled_Write_Cmd(0x00);//---set low column addressOled_Write_Cmd(0x10);//---set high column addressOled_Write_Cmd(0x40);//--set start line address Oled_Write_Cmd(0xB0);//--set page addressOled_Write_Cmd(0x81); // contract controlOled_Write_Cmd(0xFF);//--128 Oled_Write_Cmd(0xA1);//set segment remap Oled_Write_Cmd(0xA6);//--normal / reverseOled_Write_Cmd(0xA8);//--set multiplex ratio(1 to 64)Oled_Write_Cmd(0x3F);//--1/32 dutyOled_Write_Cmd(0xC8);//Com scan directionOled_Write_Cmd(0xD3);//-set display offsetOled_Write_Cmd(0x00);//Oled_Write_Cmd(0xD5);//set osc divisionOled_Write_Cmd(0x80);//Oled_Write_Cmd(0xD8);//set area color mode offOled_Write_Cmd(0x05);//Oled_Write_Cmd(0xD9);//Set Pre-Charge PeriodOled_Write_Cmd(0xF1);//Oled_Write_Cmd(0xDA);//set com pin configuartionOled_Write_Cmd(0x12);//Oled_Write_Cmd(0xDB);//set VcomhOled_Write_Cmd(0x30);//Oled_Write_Cmd(0x8D);//set charge pump enableOled_Write_Cmd(0x14);//Oled_Write_Cmd(0xAF);//--turn on oled panel
}void Oled_Clear()
{unsigned char i,j; //-128 --- 127for(i0;i8;i){Oled_Write_Cmd(0xB0 i);//page0--page7//每个page从0列Oled_Write_Cmd(0x00);Oled_Write_Cmd(0x10);//0到127列依次写入0每写入数据列地址自动偏移for(j 0;j128;j){Oled_Write_Data(0);}}
}void Oled_Show_Char(char row,char col,char oledChar){ //row*2-2unsigned int i;Oled_Write_Cmd(0xb0(row*2-2)); //page 0Oled_Write_Cmd(0x00(col0x0f)); //lowOled_Write_Cmd(0x10(col4)); //high for(i((oledChar-32)*16);i((oledChar-32)*168);i){Oled_Write_Data(F8X16[i]); //写数据oledTable1}Oled_Write_Cmd(0xb0(row*2-1)); //page 1Oled_Write_Cmd(0x00(col0x0f)); //lowOled_Write_Cmd(0x10(col4)); //highfor(i((oledChar-32)*168);i((oledChar-32)*1688);i){Oled_Write_Data(F8X16[i]); //写数据oledTable1}
}/******************************************************************************/
// 函数名称Oled_Show_Char
// 输入参数oledChar
// 输出参数无
// 函数功能OLED显示单个字符
/******************************************************************************/
void Oled_Show_Str(char row,char col,char *str){while(*str!0){Oled_Show_Char(row,col,*str);str;col 8; }
} 3. wifi控制测速小车
Wifi模块-ESP-01s蓝牙ESP-01sZigbee, NB-Iot等通信模块都是基于AT指令的设计
AT指令介绍
AT指令集是从终端设备Terminal EquipmentTE)或数据终端设备Data Terminal EquipmentDTE)向终端适配器(Terminal AdapterTA)或数据电路终端设备(Data Circuit Terminal EquipmentDCE)发送的。其对所传输的数据包大小有定义即对于AT指令的发送除AT两个字符外最多可以接收1056个 字符的长度包括最后的空字符。每个AT命令行中只能包含一条AT指令对于由终端设备主动向PC端报告的URC指示或者response 响应也要求一行最多有一个不允许上报的一行中有多条指示或者响应。AT指令以回车作为结 尾响应或上报以回车换行为结尾。
代码实现
//main.c
#include motor.h
#include delay.h
#include uart.h
#include reg52.h
#include time.h
#include stdio.h
#include Oled.h
#include esp8266.hsbit speedIO P3^2;//外部中断0
unsigned int speedCnt 0; //统计格子脉冲次数
extern unsigned int speed;//速度
extern char signal; //主程序发速度数据的通知
char speedMes[24]; //主程序发送速度数据的字符串缓冲区
//发送数据
char FSSJ[] ATCIPSEND0,5\r\n;void Ex0Init()
{EX0 1;//允许中断//EA 1;在串口初始化函数中已经打开了总中断IT0 1;//外部中断的下降沿触发
}void main()
{Time0Init();//定时器0初始化UartInit();//串口相关初始化Delay1000ms();//给espwifi模块上电时间initWifi_AP(); //初始化wifi工作在ap模式waitConnect(); //等待客户端的连接//外部中断初始化Ex0Init();Oled_Init();Oled_Clear();while(1){if(signal){//定时器1s到点把signal置一主程序发送速度SendString(FSSJ);Delay1000ms();sprintf(speedMes,%dcms,speed);//串口数据的字符串拼装speed是格子每个格子1cmSendString(speedMes);//速度发出去signal 0;//清0speed,下次由定时器1s后的中断处理中再置一}Oled_Show_Str(2,2,speedMes);}
}void speedHandler() interrupt 0 //外部中断处理函数
{speedCnt;//码盘转动了一个格子
}//uart.c
#include reg52.h
#include motor.h
#include string.h
sbit D5 P3^7;
#define SIZE 12sfr AUXR 0x8E;
char buffer[SIZE];extern char AT_OK_Flag; //OK返回值的标志位
extern char Client_Connect_Flag;void UartInit(void) //9600bps11.0592MHz
{AUXR 0x01;SCON 0x50; //配置串口工作方式1REN使能接收TMOD 0x0F;TMOD | 0x20;//定时器1工作方式位8位自动重装TH1 0xFD;TL1 0xFD;//9600波特率的初值TR1 1;//启动定时器EA 1;//开启总中断ES 1;//开启串口中断
}void SendByte(char mydata)
{SBUF mydata;while(!TI);TI 0;
}void SendString(char *str)
{while(*str ! \0){SendByte(*str);str;}
}//M1qian M2 hou M3 zuo M4 you
void Uart_Handler() interrupt 4
{static int i 0;//静态变量被初始化一次char tmp;if(RI)//中断处理函数中对于接收中断的响应{RI 0;//清除接收中断标志位tmp SBUF;if(tmp M || tmp O || tmp 0){i 0;}buffer[i] tmp;//连接服务器等OK返回值指令的判断if(buffer[0] O buffer[1] K){AT_OK_Flag 1;memset(buffer, \0, SIZE);}if(buffer[0] 0 buffer[2] C){Client_Connect_Flag 1;memset(buffer, \0, SIZE);}//灯控指令if(buffer[0] M){switch(buffer[1]){case 1:goForward();break;case 2:goBack();break;case 3:goLeft();break;case 4:goRight();break;default:stop();break;}}if(i 12) {memset(buffer, \0, SIZE);i 0;}}}//motor.c
#include reg52.hsbit RightCon1A P3^7;
sbit RightCon1B P3^3;sbit LeftCon1A P3^4;
sbit LeftCon1B P3^5;void goForward()
{LeftCon1A 0;LeftCon1B 1;RightCon1A 0;RightCon1B 1;
}void goRight()
{LeftCon1A 0;LeftCon1B 1;RightCon1A 0;RightCon1B 0;
}void goLeft()
{LeftCon1A 0;LeftCon1B 0;RightCon1A 0;RightCon1B 1;
}void goBack()
{LeftCon1A 1;LeftCon1B 0;RightCon1A 1;RightCon1B 0;
}void stop()
{LeftCon1A 0;LeftCon1B 0;RightCon1A 0;RightCon1B 0;
}//time.c
#include motor.h
#include reg52.hextern unsigned int speedCnt;
unsigned int speed;
char signal 0;
unsigned int cnt 0;void Time0Init()
{//1. 配置定时器0工作模式位16位计时TMOD 0x01;//2. 给初值定一个0.5出来TL00x33;TH00xFE;//3. 开始计时TR0 1;TF0 0;//4. 打开定时器0中断ET0 1;//5. 打开总中断EAEA 1;
}void Time0Handler() interrupt 1
{cnt; //统计爆表的次数. cnt1的时候报表了1//重新给初值TL00x33;TH00xFE;if(cnt 2000){//爆表2000次经过了1ssignal 1;cnt 0; //当100次表示1s重新让cnt从0开始计算下一次的1s//计算小车的速度也就是拿到speedCnt的值speed speedCnt;speedCnt 0;//1秒后拿到speedCnt个格子就能算出这1s的速度格子清零}}//oled.c
#include reg52.h
#include intrins.h
#include Oledfont.hsbit scl P1^2;
sbit sda P1^3;void IIC_Start()
{scl 0;sda 1;scl 1;_nop_();sda 0;_nop_();
}void IIC_Stop()
{scl 0;sda 0;scl 1;_nop_();sda 1;_nop_();
}char IIC_ACK()
{char flag;sda 1;//就在时钟脉冲9期间释放数据线_nop_();scl 1;_nop_();flag sda;_nop_();scl 0;_nop_();return flag;
}void IIC_Send_Byte(char dataSend)
{int i;for(i 0;i8;i){scl 0;//scl拉低让sda做好数据准备sda dataSend 0x80;//1000 0000获得dataSend的最高位给sda_nop_();//发送数据建立时间scl 1;//scl拉高开始发送_nop_();//数据发送时间scl 0;//发送完毕拉低_nop_();//dataSend dataSend 1;}
}void Oled_Write_Cmd(char dataCmd)
{// 1. start()IIC_Start();// // 2. 写入从机地址 b0111 1000 0x78IIC_Send_Byte(0x78);// 3. ACKIIC_ACK();// 4. cotrol byte: (0)(0)000000 写入命令 (0)(1)000000写入数据IIC_Send_Byte(0x00);// 5. ACKIIC_ACK();//6. 写入指令/数据IIC_Send_Byte(dataCmd);//7. ACKIIC_ACK();//8. STOPIIC_Stop();
}void Oled_Write_Data(char dataData)
{// 1. start()IIC_Start();// // 2. 写入从机地址 b0111 1000 0x78IIC_Send_Byte(0x78);// 3. ACKIIC_ACK();// 4. cotrol byte: (0)(0)000000 写入命令 (0)(1)000000写入数据IIC_Send_Byte(0x40);// 5. ACKIIC_ACK();///6. 写入指令/数据IIC_Send_Byte(dataData);//7. ACKIIC_ACK();//8. STOPIIC_Stop();
}void Oled_Init(void){Oled_Write_Cmd(0xAE);//--display offOled_Write_Cmd(0x00);//---set low column addressOled_Write_Cmd(0x10);//---set high column addressOled_Write_Cmd(0x40);//--set start line address Oled_Write_Cmd(0xB0);//--set page addressOled_Write_Cmd(0x81); // contract controlOled_Write_Cmd(0xFF);//--128 Oled_Write_Cmd(0xA1);//set segment remap Oled_Write_Cmd(0xA6);//--normal / reverseOled_Write_Cmd(0xA8);//--set multiplex ratio(1 to 64)Oled_Write_Cmd(0x3F);//--1/32 dutyOled_Write_Cmd(0xC8);//Com scan directionOled_Write_Cmd(0xD3);//-set display offsetOled_Write_Cmd(0x00);//Oled_Write_Cmd(0xD5);//set osc divisionOled_Write_Cmd(0x80);//Oled_Write_Cmd(0xD8);//set area color mode offOled_Write_Cmd(0x05);//Oled_Write_Cmd(0xD9);//Set Pre-Charge PeriodOled_Write_Cmd(0xF1);//Oled_Write_Cmd(0xDA);//set com pin configuartionOled_Write_Cmd(0x12);//Oled_Write_Cmd(0xDB);//set VcomhOled_Write_Cmd(0x30);//Oled_Write_Cmd(0x8D);//set charge pump enableOled_Write_Cmd(0x14);//Oled_Write_Cmd(0xAF);//--turn on oled panel
}void Oled_Clear()
{unsigned char i,j; //-128 --- 127for(i0;i8;i){Oled_Write_Cmd(0xB0 i);//page0--page7//每个page从0列Oled_Write_Cmd(0x00);Oled_Write_Cmd(0x10);//0到127列依次写入0每写入数据列地址自动偏移for(j 0;j128;j){Oled_Write_Data(0);}}
}void Oled_Show_Char(char row,char col,char oledChar){ //row*2-2unsigned int i;Oled_Write_Cmd(0xb0(row*2-2)); //page 0Oled_Write_Cmd(0x00(col0x0f)); //lowOled_Write_Cmd(0x10(col4)); //high for(i((oledChar-32)*16);i((oledChar-32)*168);i){Oled_Write_Data(F8X16[i]); //写数据oledTable1}Oled_Write_Cmd(0xb0(row*2-1)); //page 1Oled_Write_Cmd(0x00(col0x0f)); //lowOled_Write_Cmd(0x10(col4)); //highfor(i((oledChar-32)*168);i((oledChar-32)*1688);i){Oled_Write_Data(F8X16[i]); //写数据oledTable1}
}/******************************************************************************/
// 函数名称Oled_Show_Char
// 输入参数oledChar
// 输出参数无
// 函数功能OLED显示单个字符
/******************************************************************************/
void Oled_Show_Str(char row,char col,char *str){while(*str!0){Oled_Show_Char(row,col,*str);str;col 8; }
}//esp8266.c
#include uart.h//1 工作在路由模式
code char LYMO[] ATCWMODE2\r\n;
//2 使能多链接
code char DLJ[] ATCIPMUX1\r\n;
//3 建立TCPServer
code char JLFW[] ATCIPSERVER1\r\n; // default port 333 char AT_OK_Flag 0; //OK返回值的标志位
char Client_Connect_Flag 0;void initWifi_AP()
{SendString(LYMO);while(!AT_OK_Flag);AT_OK_Flag 0;SendString(DLJ);while(!AT_OK_Flag);AT_OK_Flag 0;
}void waitConnect()
{SendString(JLFW);while(!Client_Connect_Flag);AT_OK_Flag 0;
}//delay.c
#include intrins.hvoid Delay1000ms() //11.0592MHz
{unsigned char i, j, k;_nop_();i 8;j 1;k 243;do{do{while (--k);} while (--j);} while (--i);
}
4. 4g控制小车
原理运用EC03-DNC4G通信模块
模块介绍
基于串口AT指令的开发方式有两种工作模式默认是透传模式通过其他方式进入AT指令模式注意插卡不要出错下图红色位置为SIM卡状态灯亮才是正常
代码不做修改直接基于蓝牙小车整合 4g模块只要做好外网透传就可以了
5. 语音控制小车
语音模块配置
使用SU-03T / LD3320
具体介绍看我之前写过的博客https://blog.csdn.net/m0_74712453/article/details/13171085
语音控制小车开发和调试代码
代码示例
//main.c
#include reg52.h
#include hc04.h
#include delay.h
#include sg90.h
#include Oled.h
#include motor.h#define MIDDLE 0
#define LEFT 1
#define RIGHT 2#define BZ 1
#define XJ 2
#define GS 3sbit A25 P1^5;
sbit A26 P1^6;
sbit A27 P1^7;sbit leftSensorX P2^7;
sbit rightSensorX P2^6;sbit leftSensorG P2^5;
sbit rightSensorG P2^4;char dir;double disMiddle;
double disLeft;
double disRight;void xunjiMode()
{if(leftSensorX 0 rightSensorX 0){goForward();}if(leftSensorX 1 rightSensorX 0){goLeft();}if(leftSensorX 0 rightSensorX 1){goRight();}if(leftSensorX 1 rightSensorX 1){//停stop();}
}void gensuiMode()
{if(leftSensorG 0 rightSensorG 0){goForward();}if(leftSensorG 1 rightSensorG 0){goRight();}if(leftSensorG 0 rightSensorG 1){goLeft();}if(leftSensorG 1 rightSensorG 1){//停stop();}
}void bizhangMode()
{if(dir ! MIDDLE){sgMiddle();dir MIDDLE;Delay300ms();}disMiddle get_distance();if(disMiddle 35){//前进goForward();}else if(disMiddle 10){goBack();}else{//停止stop();//测左边距离sgLeft();Delay300ms();disLeft get_distance();sgMiddle();Delay300ms();sgRight();dir RIGHT;Delay300ms();disRight get_distance();if(disLeft disRight){goRight();Delay150ms();stop();}if(disRight disLeft){goLeft();Delay150ms();stop();}}}void main()
{int mark 0;Time0Init();Time1Init();//舵机的初始位置sgMiddle();Delay300ms();Delay300ms();dir MIDDLE;Oled_Init();Oled_Clear();Oled_Show_Str(2,2,-----Ready----);while(1){//满足寻迹模式的条件if(A25 0 A26 1 A27 1){if(mark ! XJ){Oled_Clear();Oled_Show_Str(2,2,-----XunJi----);}mark XJ;xunjiMode();}//满足跟随模式的条件if(A25 1 A26 0 A27 1){if(mark ! GS){Oled_Clear();Oled_Show_Str(2,2,-----GenSui----);}mark GS;gensuiMode();}//满足避障模式的条件if(A25 1 A26 1 A27 0){if(mark ! BZ){Oled_Clear();Oled_Show_Str(2,2,-----BiZhang----);}mark BZ;bizhangMode();}}
}//hc04.c
#include reg52.h
#include delay.hsbit Trig P2^3;
sbit Echo P2^2;void Time1Init()
{ TMOD 0x0F; //设置定时器模式TMOD | 0x10;TH1 0;TL1 0;//设置定时器0工作模式1初始值设定0开始数数不着急启动定时器
}void startHC()
{Trig 0;Trig 1;Delay10us();Trig 0;
}double get_distance()
{double time;//定时器数据清零以便下一次测距TH1 0;TL1 0;//1. Trig 给Trig端口至少10us的高电平startHC();//2. echo由低电平跳转到高电平表示开始发送波while(Echo 0);//波发出去的那一下开始启动定时器TR1 1;//3. 由高电平跳转回低电平表示波回来了while(Echo 1);//波回来的那一下我们开始停止定时器TR1 0;//4. 计算出中间经过多少时间time (TH1 * 256 TL1)*1.085;//us为单位//5. 距离 速度 340m/s* 时间/2return (time * 0.017);
}//delay.c
#include intrins.hvoid Delay2000ms() //11.0592MHz
{unsigned char i, j, k;i 15;j 2;k 235;do{do{while (--k);} while (--j);} while (--i);
}void Delay10us() //11.0592MHz
{unsigned char i;i 2;while (--i);
}void Delay300ms() //11.0592MHz
{unsigned char i, j, k;_nop_();i 3;j 26;k 223;do{do{while (--k);} while (--j);} while (--i);
}void Delay150ms() //11.0592MHz
{unsigned char i, j, k;i 2;j 13;k 237;do{do{while (--k);} while (--j);} while (--i);
}void Delay450ms() //11.0592MHz
{unsigned char i, j, k;_nop_();i 4;j 39;k 209;do{do{while (--k);} while (--j);} while (--i);
}//sg90.c
#include reg52.h
#include delay.hsbit sg90_con P1^1;int jd;
int cnt 0;void Time0Init()
{//1. 配置定时器0工作模式位16位计时TMOD 0xF0; //设置定时器模式TMOD | 0x01;//2. 给初值定一个0.5出来TL00x33;TH00xFE;//3. 开始计时TR0 1;TF0 0;//4. 打开定时器0中断ET0 1;//5. 打开总中断EAEA 1;
}void sgMiddle()
{//中间位置jd 3; //90度 1.5ms高电平cnt 0;
}void sgLeft()
{//左边位置jd 5; //135度 1.5ms高电平cnt 0;
}void sgRight()
{//右边位置jd 1; //0度cnt 0;
}void Time0Handler() interrupt 1
{cnt; //统计爆表的次数. cnt1的时候报表了1//重新给初值TL00x33;TH00xFE;//控制PWM波if(cnt jd){sg90_con 1;}else{sg90_con 0;}if(cnt 40){//爆表40次经过了20mscnt 0; //当100次表示1s重新让cnt从0开始计算下一次的1ssg90_con 1;}}//motor.c
#include reg52.hsbit RightCon1A P3^7;
sbit RightCon1B P3^3;sbit LeftCon1A P3^4;
sbit LeftCon1B P3^5;void goForward()
{LeftCon1A 0;LeftCon1B 1;RightCon1A 0;RightCon1B 1;
}void goRight()
{LeftCon1A 0;LeftCon1B 1;RightCon1A 0;RightCon1B 0;
}void goLeft()
{LeftCon1A 0;LeftCon1B 0;RightCon1A 0;RightCon1B 1;
}void goBack()
{LeftCon1A 1;LeftCon1B 0;RightCon1A 1;RightCon1B 0;
}void stop()
{LeftCon1A 0;LeftCon1B 0;RightCon1A 0;RightCon1B 0;
}//oled.c
#include reg52.h
#include intrins.h
#include Oledfont.hsbit scl P1^2;
sbit sda P1^3;void IIC_Start()
{scl 0;sda 1;scl 1;_nop_();sda 0;_nop_();
}void IIC_Stop()
{scl 0;sda 0;scl 1;_nop_();sda 1;_nop_();
}char IIC_ACK()
{char flag;sda 1;//就在时钟脉冲9期间释放数据线_nop_();scl 1;_nop_();flag sda;_nop_();scl 0;_nop_();return flag;
}void IIC_Send_Byte(char dataSend)
{int i;for(i 0;i8;i){scl 0;//scl拉低让sda做好数据准备sda dataSend 0x80;//1000 0000获得dataSend的最高位给sda_nop_();//发送数据建立时间scl 1;//scl拉高开始发送_nop_();//数据发送时间scl 0;//发送完毕拉低_nop_();//dataSend dataSend 1;}
}void Oled_Write_Cmd(char dataCmd)
{// 1. start()IIC_Start();// // 2. 写入从机地址 b0111 1000 0x78IIC_Send_Byte(0x78);// 3. ACKIIC_ACK();// 4. cotrol byte: (0)(0)000000 写入命令 (0)(1)000000写入数据IIC_Send_Byte(0x00);// 5. ACKIIC_ACK();//6. 写入指令/数据IIC_Send_Byte(dataCmd);//7. ACKIIC_ACK();//8. STOPIIC_Stop();
}void Oled_Write_Data(char dataData)
{// 1. start()IIC_Start();// // 2. 写入从机地址 b0111 1000 0x78IIC_Send_Byte(0x78);// 3. ACKIIC_ACK();// 4. cotrol byte: (0)(0)000000 写入命令 (0)(1)000000写入数据IIC_Send_Byte(0x40);// 5. ACKIIC_ACK();///6. 写入指令/数据IIC_Send_Byte(dataData);//7. ACKIIC_ACK();//8. STOPIIC_Stop();
}void Oled_Init(void){Oled_Write_Cmd(0xAE);//--display offOled_Write_Cmd(0x00);//---set low column addressOled_Write_Cmd(0x10);//---set high column addressOled_Write_Cmd(0x40);//--set start line address Oled_Write_Cmd(0xB0);//--set page addressOled_Write_Cmd(0x81); // contract controlOled_Write_Cmd(0xFF);//--128 Oled_Write_Cmd(0xA1);//set segment remap Oled_Write_Cmd(0xA6);//--normal / reverseOled_Write_Cmd(0xA8);//--set multiplex ratio(1 to 64)Oled_Write_Cmd(0x3F);//--1/32 dutyOled_Write_Cmd(0xC8);//Com scan directionOled_Write_Cmd(0xD3);//-set display offsetOled_Write_Cmd(0x00);//Oled_Write_Cmd(0xD5);//set osc divisionOled_Write_Cmd(0x80);//Oled_Write_Cmd(0xD8);//set area color mode offOled_Write_Cmd(0x05);//Oled_Write_Cmd(0xD9);//Set Pre-Charge PeriodOled_Write_Cmd(0xF1);//Oled_Write_Cmd(0xDA);//set com pin configuartionOled_Write_Cmd(0x12);//Oled_Write_Cmd(0xDB);//set VcomhOled_Write_Cmd(0x30);//Oled_Write_Cmd(0x8D);//set charge pump enableOled_Write_Cmd(0x14);//Oled_Write_Cmd(0xAF);//--turn on oled panel
}void Oled_Clear()
{unsigned char i,j; //-128 --- 127for(i0;i8;i){Oled_Write_Cmd(0xB0 i);//page0--page7//每个page从0列Oled_Write_Cmd(0x00);Oled_Write_Cmd(0x10);//0到127列依次写入0每写入数据列地址自动偏移for(j 0;j128;j){Oled_Write_Data(0);}}
}void Oled_Show_Char(char row,char col,char oledChar){ //row*2-2unsigned int i;Oled_Write_Cmd(0xb0(row*2-2)); //page 0Oled_Write_Cmd(0x00(col0x0f)); //lowOled_Write_Cmd(0x10(col4)); //high for(i((oledChar-32)*16);i((oledChar-32)*168);i){Oled_Write_Data(F8X16[i]); //写数据oledTable1}Oled_Write_Cmd(0xb0(row*2-1)); //page 1Oled_Write_Cmd(0x00(col0x0f)); //lowOled_Write_Cmd(0x10(col4)); //highfor(i((oledChar-32)*168);i((oledChar-32)*1688);i){Oled_Write_Data(F8X16[i]); //写数据oledTable1}
}/******************************************************************************/
// 函数名称Oled_Show_Char
// 输入参数oledChar
// 输出参数无
// 函数功能OLED显示单个字符
/******************************************************************************/
void Oled_Show_Str(char row,char col,char *str){while(*str!0){Oled_Show_Char(row,col,*str);str;col 8; }
}