目录
基本概述
硬件组成
功能
关键字
模块介绍
电机模块L9110S
循迹模块(TCRT5000传感器)
红外避障模块
测速模块
小车
移动小车(控制电机转动,使小车前进、后退、左转、右转 )
遥控小车( 使用蓝牙模块,通过串口发送信息控制小车移动)
调速小车(利用PWM波对电机进行调速)
循迹小车 (利用循迹模块进行黑白色的检测)
跟随小车(利用红外避障模块完成跟随行为)
避障小车(利用超声波测距完成避障行为)
测速小车,使用OLED屏显示小车速度
语音控制小车,循迹、跟随、避障三种功能切换
基本概述
硬件组成
电机模块L9110S、循迹模块、红外避障模块、超声波模块、测速模块、OLED屏、蓝牙模块、4G,模块、语音模块SU-03T
功能
蓝牙控制小车、WiFi控制小车、4G控制小车、小车的避障、跟随、循迹
关键字
单片机中一般都有两块存储区域,ROM和RAM,程序代码存储在ROM中,程序要用的变量存储在RAM中。而“code”的作用就是将其修饰过的变量存储在ROM中而非RAM。 在单片机中,RAM空间都比较小,是比较宝贵的,当存放在RAM中的数据过多时,会导致编译不成功。
- exturn:使用exturn关键字修饰的全局变量或函数,作用域不再局限本文件,其他文件同样能访问到这些变量或函数,跟static关键字恰恰相反。
- code:使用code关键字修饰的变量(一般是初始化后,值保持不变的变量)后会被存放到ROM区,从而节省RAM的空间。
模块介绍
电机模块L9110S
L0110S模块的A、B分别控制着两个电机,如果需要控制四个电机,则需要两个L0110S模块
- 当B-1A为高电平,B-2A为低电平时,电机反转或正转
- 当B-1A为低电平,B-2A为高电平时,电机正转反转
- 当B-1A为低电平,B-2A为低电平时,电机不转
- 电机的正转和反转与跟电机的接线不同而不同,注意自己调试
循迹模块(TCRT5000传感器)
- 当发射出的红外线没有被反射回来或被反射回来但强度不够大时,DO输出高电平,灯灭。 黑色吸收红外线,DO输出高电平,灯亮
- 当发射出的红外线被反射回来或被反射回来且强度足够大,DO输出低电平,灯亮。 白色反射红外线,DO输出低电平,灯亮
- 即黑色输出高电平,灯灭,白色输出低电平,灯亮
红外避障模块
- 当发射出的红外线没有被反射回来或被反射回来但强度不够大时,DO输出高电平,灯灭。没有障碍物
- 当发射出的红外线被反射回来,DO输出低电平,灯亮。有障碍物
- 即有障碍物输出低电平,灯亮,没有障碍物输出高电平,灯灭
测速模块
- 发射的红外线被物体遮挡时,输出高电平,发射的红外线没被物体遮挡时,输出低电平
- 有物体高电平,没物体低电平
- 当搭配小车测速盘,会形成下降沿(有遮挡高电平,没遮挡低电平)
小车
移动小车(控制电机转动,使小车前进、后退、左转、右转 )
#include "reg52.h"
#include <intrins.h>sbit left_con1A = P1^1;
sbit left_con2A = P1^2;
sbit right_con1A = P1^3;
sbit right_con2A = P1^4;void Delay2000ms() //@11.0592MHz
{unsigned char i, j, k;_nop_();i = 15;j = 2;k = 235;do{do{while (--k);} while (--j);} while (--i);
}//两个电机反转,前进
void goForward()
{left_con1A = 1;left_con2A = 0;right_con1A = 1; right_con2A = 0;
}//两个电机正转,后退
void goBack()
{left_con1A = 0;left_con2A = 1;right_con1A = 0; right_con2A = 1;
}//两个电机不转,停止
void goStop()
{left_con1A = 0;left_con2A = 0;right_con1A = 0; right_con2A = 0;
}//左电机不转,右电机反转,左转
void goLeft()
{left_con1A = 0;left_con2A = 0;right_con1A = 1; right_con2A = 0;
}//左电机反转,右电机不转,右转
void goRight()
{left_con1A = 1;left_con2A = 0;right_con1A = 0; right_con2A = 0;
}void main()
{while(1){goForward();Delay2000ms();goBack();Delay2000ms();goLeft();Delay2000ms();goRight();Delay2000ms();goStop();Delay2000ms();}
}
遥控小车( 使用蓝牙模块,通过串口发送信息控制小车移动)
#include "reg52.h"
#include <intrins.h>
#include <string.h>sfr AUXR = 0x8E;sbit left_con1A = P1^1;
sbit left_con2A = P1^2;
sbit right_con1A = P1^3;
sbit right_con2A = P1^4;
sbit led1 = P3^7;
char mybuf[24] ;void Delay1000ms() //@11.0592MHz
{unsigned char i, j, k;_nop_();i = 8;j = 1;k = 243;do{do{while (--k);} while (--j);} while (--i);
}void uartInit()
{AUXR = 0x01;PCON &= 0x7F; //配置波特率正常SCON = 0x50; //配置串口选择工作方式1,允许串口接收数据//配置定时器1为8位自动重装模式TMOD &= 0x0F;TMOD |= 0x20;//给定时器1,9600波特率初值TH1 = 0xFD; //定时器1初值TL1 = 0xFD; //定时器1重装值ET1 = 0; //不允许定时器1产生中断TR1 = 1; //开启定时器1EA = 1; //开启总中断ES = 1; //开启串口中断}void sendByte(char mydata)
{SBUF = mydata; //向串口发送一帧信息while(!TI); //等待硬件置位TI = 0; //TI软件清0
}void sendString(char *str)
{while(*str != '\0'){sendByte(*str);str++;}
}//两个电机反转,前进
void goForward()
{left_con1A = 1;left_con2A = 0;right_con1A = 1; right_con2A = 0;
}//两个电机正转,后退
void goBack()
{left_con1A = 0;left_con2A = 1;right_con1A = 0; right_con2A = 1;
}//两个电机不转,停止
void goStop()
{left_con1A = 0;left_con2A = 0;right_con1A = 0; right_con2A = 0;
}//左电机不转,右电机反转,左转
void goLeft()
{left_con1A = 0;left_con2A = 0;right_con1A = 1; right_con2A = 0;
}//左电机反转,右电机不转,右转
void goRight()
{left_con1A = 1;left_con2A = 0;right_con1A = 0; right_con2A = 0;
}void main()
{uartInit();while(1){sendString("jiangxiaoya\r\n"); //发送心跳包,确保串口通信没有中断Delay1000ms();}
}void myUart() interrupt 4
{static int i = 0;char tmp;//接收数据后,RI硬件置位产生的中断if(RI){RI = 0; //RI软件清0//获取从pc端接收到的数据tmp = SBUF;if(tmp == 'f' || tmp == 'b' || tmp == 'l' || tmp == 'r' || tmp == 's'){i = 0;}mybuf[i] = tmp;i++;//forwardif(mybuf[0] == 'f' && mybuf[1] == 'o'){goForward();memset(mybuf,'\0',24);}//forwardif(mybuf[0] == 'b' && mybuf[1] == 'a'){goBack();memset(mybuf,'\0',24);}//leftif(mybuf[0] == 'l' && mybuf[1] == 'e'){goLeft();memset(mybuf,'\0',24);}//rightif(mybuf[0] == 'r' && mybuf[1] == 'i'){goRight();memset(mybuf,'\0',24);}//stopif(mybuf[0] == 's' && mybuf[1] == 't'){goStop();memset(mybuf,'\0',24);}if(i == 24){i = 0;}}//发送数据后,TI硬件置位产生的中断if(TI);
}
调速小车(利用PWM波对电机进行调速)
- 利用定时器0软件模拟PWM波控制小车左轮速度,定时器1软件模拟PWM波控制小车右轮速度,通过控制轮子的速度来达到前进、停止、左转、右转
- 在20ms的过程中,部分时间让电机正转,剩下时间让电机停止不动就能改变电机获得的功率,从而改变电机速度。
#include "reg52.h"
#include <intrins.h>
#include <string.h>sfr AUXR = 0x8E;sbit left_con1A = P1^1;
sbit left_con2A = P1^2;
sbit right_con1A = P1^3;
sbit right_con2A = P1^4;
sbit led1 = P3^7;char mybuf[24] ;
char leftSpeed;
char rightSpeed;
int cntLeft = 0;
int cntRight = 0;void Delay1000ms() //@11.0592MHz
{unsigned char i, j, k;_nop_();i = 8;j = 1;k = 243;do{do{while (--k);} while (--j);} while (--i);
}//左电机反转
void goLeftForward()
{left_con1A = 1;left_con2A = 0;
}//左电机不转
void goLeftStop()
{left_con1A = 0;left_con2A = 0;
}//右电机反转
void goRightForward()
{right_con1A = 1; right_con2A = 0;
}//右电机不转
void goRightStop()
{right_con1A = 0; right_con2A = 0;
}//前进
void goForward()
{leftSpeed = 18;rightSpeed = 20;
}//停止
void goStop()
{leftSpeed = 0;rightSpeed = 0;
}//左转
void goLeft()
{leftSpeed = 10;rightSpeed = 20;
}//右转
void goRight()
{leftSpeed = 20;rightSpeed = 10;
}void Timer0Init(void) //1毫秒@11.0592MHz
{AUXR &= 0x7F; //定时器时钟12T模式TMOD &= 0xF0; //设置定时器模式TMOD |= 0x01; //设置定时器模式//定时器初值为1msTL0 = 0x66; TH0 = 0xFC; TF0 = 0; //清除TF0标志TR0 = 1; //定时器0开始计时ET0 = 1;EA = 1;
}void Timer1Init(void) //1毫秒@11.0592MHz
{AUXR |= 0x40; //定时器时钟1T模式TMOD &= 0x0F; //设置定时器模式TMOD |= 0x10; //设置定时器模式//定时器初值为1msTL1 = 0xCD; TH1 = 0xD4; TF1 = 0; //清除TF1标志TR1 = 1; //定时器1开始计时ET1 = 1;EA = 1;
}void main()
{Timer0Init();Timer1Init();while(1){Delay1000ms();goForward();Delay1000ms();goLeft();Delay1000ms();goRight();}
}//定时器0的中断函数
void Time0Handler() interrupt 1
{cntLeft++;TL0 = 0x66; TH0 = 0xFC;if(cntLeft < leftSpeed){goLeftForward();}else{goLeftStop();}if(cntLeft == 20){cntLeft = 0;}
}void Time1Handler() interrupt 3
{cntRight++;TL1 = 0x66; TH1 = 0xFC;if(cntRight < rightSpeed){goRightForward();}else{goRightStop();}if(cntRight == 20){cntRight = 0;}
}
循迹小车 (利用循迹模块进行黑白色的检测)
#include "reg52.h"
#include <intrins.h>
#include <string.h>sfr AUXR = 0x8E;sbit left_con1A = P1^1;
sbit left_con2A = P1^2;
sbit right_con1A = P1^3;
sbit right_con2A = P1^4;
sbit tracingLeft = P1^5;
sbit tracingRight = P1^6;char leftSpeed;
char rightSpeed;
int cntLeft = 0;
int cntRight = 0;//左电机反转
void goLeftForward()
{left_con1A = 1;left_con2A = 0;
}//左电机不转
void goLeftStop()
{left_con1A = 0;left_con2A = 0;
}//右电机反转
void goRightForward()
{right_con1A = 1; right_con2A = 0;
}//右电机不转
void goRightStop()
{right_con1A = 0; right_con2A = 0;
}//前进
void goForward()
{leftSpeed = 17;rightSpeed = 20;
}//停止
void goStop()
{leftSpeed = 0;rightSpeed = 0;
}//左转
void goLeft()
{leftSpeed = 5;rightSpeed = 20;
}//右转
void goRight()
{leftSpeed = 20;rightSpeed = 5;
}void Timer0Init(void) //1毫秒@11.0592MHz
{AUXR &= 0x7F; //定时器时钟12T模式TMOD &= 0xF0; //设置定时器模式TMOD |= 0x01; //设置定时器模式//定时器初值为1msTL0 = 0x66; TH0 = 0xFC; TF0 = 0; //清除TF0标志TR0 = 1; //定时器0开始计时ET0 = 1;EA = 1;
}void Timer1Init(void) //1毫秒@11.0592MHz
{AUXR |= 0x40; //定时器时钟1T模式TMOD &= 0x0F; //设置定时器模式TMOD |= 0x10; //设置定时器模式//定时器初值为1msTL1 = 0xCD; TH1 = 0xD4; TF1 = 0; //清除TF1标志TR1 = 1; //定时器1开始计时ET1 = 1;EA = 1;
}void tracingMode()
{ if(tracingLeft == 0 && tracingRight == 0){ //goForward();}if(tracingLeft == 0 && tracingRight == 1){goRight();}if(tracingLeft == 1 && tracingRight == 0){goLeft();}if(tracingLeft == 1 && tracingRight == 1){goStop();}
}void main()
{Timer0Init();Timer1Init();while(1){tracingMode();}
}//定时器0的中断函数
void Time0Handler() interrupt 1
{cntLeft++;TL0 = 0x66; TH0 = 0xFC;if(cntLeft < leftSpeed){goLeftForward();}else{goLeftStop();}if(cntLeft == 20){cntLeft = 0;}
}void Time1Handler() interrupt 3
{cntRight++;TL1 = 0x66; TH1 = 0xFC;if(cntRight < rightSpeed){goRightForward();}else{goRightStop();}if(cntRight == 20){cntRight = 0;}
}
跟随小车(利用红外避障模块完成跟随行为)
#include "reg52.h"
#include <intrins.h>
#include <string.h>sfr AUXR = 0x8E;sbit left_con1A = P1^1;
sbit left_con2A = P1^2;
sbit right_con1A = P1^3;
sbit right_con2A = P1^4;
sbit followLeft = P2^1;
sbit followRight = P2^2;char leftSpeed;
char rightSpeed;
int cntLeft = 0;
int cntRight = 0;//左电机反转
void goLeftForward()
{left_con1A = 1;left_con2A = 0;
}//左电机不转
void goLeftStop()
{left_con1A = 0;left_con2A = 0;
}//右电机反转
void goRightForward()
{right_con1A = 1; right_con2A = 0;
}//右电机不转
void goRightStop()
{right_con1A = 0; right_con2A = 0;
}//前进
void goForward()
{leftSpeed = 17;rightSpeed = 20;
}//停止
void goStop()
{leftSpeed = 0;rightSpeed = 0;
}//左转
void goLeft()
{leftSpeed = 8;rightSpeed = 20;
}//右转
void goRight()
{leftSpeed = 20;rightSpeed = 10;
}void Timer0Init(void) //1毫秒@11.0592MHz
{AUXR &= 0x7F; //定时器时钟12T模式TMOD &= 0xF0; //设置定时器模式TMOD |= 0x01; //设置定时器模式//定时器初值为1msTL0 = 0x66; TH0 = 0xFC; TF0 = 0; //清除TF0标志TR0 = 1; //定时器0开始计时ET0 = 1;EA = 1;
}void Timer1Init(void) //1毫秒@11.0592MHz
{AUXR |= 0x40; //定时器时钟1T模式TMOD &= 0x0F; //设置定时器模式TMOD |= 0x10; //设置定时器模式//定时器初值为1msTL1 = 0xCD; TH1 = 0xD4; TF1 = 0; //清除TF1标志TR1 = 1; //定时器1开始计时ET1 = 1;EA = 1;
}void followMode()
{ if(followLeft == 0 && followRight == 0){ //goForward();}if(followLeft == 0 && followRight == 1){goRight();}if(followLeft == 1 && followRight == 0){goLeft();}if(followLeft == 1 && followRight == 1){goStop();}
}void main()
{Timer0Init();Timer1Init();while(1){followMode();}
}//定时器0的中断函数
void Time0Handler() interrupt 1
{cntLeft++;TL0 = 0x66; TH0 = 0xFC;if(cntLeft < leftSpeed){goLeftForward();}else{goLeftStop();}if(cntLeft == 20){cntLeft = 0;}
}void Time1Handler() interrupt 3
{cntRight++;TL1 = 0x66; TH1 = 0xFC;if(cntRight < rightSpeed){goRightForward();}else{goRightStop();}if(cntRight == 20){cntRight = 0;}
}
避障小车(利用超声波测距完成避障行为)
- 利用定时器0软件模拟PWM波控制sg90舵机转动方向
- 利用定时器1和超声波不断测量前方距离
#include "reg52.h"
#include <intrins.h>sbit left_con1A = P1^1;
sbit left_con2A = P1^2;
sbit right_con1A = P1^3;
sbit right_con2A = P1^4;
sbit Trig = P2^3;
sbit Echo = P2^4;
sbit sg90 = P2^5;int angle;
int angleBack;
int cnt = 0;void Delay100ms() //@11.0592MHz
{unsigned char i, j;i = 180;j = 73;do{while (--j);} 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 Delay500ms() //@11.0592MHz
{unsigned char i, j, k;_nop_();i = 4;j = 129;k = 119;do{do{while (--k);} while (--j);} while (--i);
}void Delay10us() //@11.0592MHz
{unsigned char i;i = 2;while (--i);
}//两个电机反转,前进
void goForward()
{left_con1A = 1;left_con2A = 0;right_con1A = 1; right_con2A = 0;
}//两个电机正转,后退
void goBack()
{left_con1A = 0;left_con2A = 1;right_con1A = 0; right_con2A = 1;
}//两个电机不转,停止
void goStop()
{left_con1A = 0;left_con2A = 0;right_con1A = 0; right_con2A = 0;
}//左电机不转,右电机反转,左转
void goLeft()
{left_con1A = 0;left_con2A = 0;right_con1A = 1; right_con2A = 0;
}//左电机反转,右电机不转,右转
void goRight()
{left_con1A = 1;left_con2A = 0;right_con1A = 0; right_con2A = 0;
}void timer0Init()
{//设置定时器0为16为计时模式TMOD &=0xF0; TMOD |=0x01; //设置定时器0定时时间为0.5msTH0 = 0xFE;TL0 = 0x33;TR0 = 1; //定时器0开始计时TF0 = 0; //不执行定时器0爆表时导致的中断ET0 = 1; //定时器0中断开关EA = 1; //总中断开关
}void timer1Init()
{ //设置定时器1为16为计时模式TMOD &= 0x0F;TMOD |= 0x10; TH1 = 0x00;TL1 = 0x00;
}void ultrasonicStart()
{Trig = 0;Trig = 1;Delay10us();Trig = 0;
}double getDistance()
{double time = 0;//定时器1清0TH1 = 0x00;TL1 = 0x00;ultrasonicStart();while(Echo == 0); //当Echo引脚从低电平跳到高电平时开启定时器1TR1 = 1;while(Echo == 1); //当Echo引脚从高电平跳到低电平时关闭定时器1TR1 = 0;time = (TH1*256 + TL1) * 1.085; //微秒return (time * 0.017);
}void sg90Left()
{angle = 5; //180°if(angleBack != angle){ cnt = 0;}angleBack = angle;Delay100ms();
} void sg90Middle()
{angle = 3; //90°if(angleBack != angle){ cnt = 0;}angleBack = angle;Delay100ms();
} void sg90Right()
{angle = 1; //0°if(angleBack != angle){ cnt = 0;}angleBack = angle;Delay100ms();
} void main()
{double leftDistance;double rightDistance;double middleDistance;timer0Init();timer1Init();sg90Middle();Delay500ms();while(1){sg90Middle();Delay300ms();middleDistance = getDistance();if(middleDistance > 35){goForward();}else{goStop();sg90Left();Delay300ms();leftDistance = getDistance();sg90Middle();Delay300ms();sg90Right();Delay300ms();rightDistance = getDistance();if(leftDistance < 15 && rightDistance < 15){goBack();Delay500ms();goStop();}else{if(leftDistance > rightDistance){goLeft();Delay500ms();goStop();}if(rightDistance > leftDistance){goRight();Delay500ms();goStop();}}}}
}//定时器0的中断函数
void Time0Handler() interrupt 1
{TH0 = 0xFE;TL0 = 0x33;cnt++;//控制占空比if(cnt < angle){sg90 = 1;}else{sg90 = 0;}if(cnt == 40){ //每个周期为20mscnt = 0;sg90 = 1;}
}
测速小车,使用OLED屏显示小车速度
- 轮子走一圈,经过一个周长,C = 2x3.14x半径= 3.14 x 直径(6.5cm),对应的转速码盘也转了一圈
- 码盘有20个格子,每经过一个格子,会遮挡(高电平)和不遮挡(低电平),即产生下降沿,一个下降沿就是走了 3.14 * 6.5 cm /20 = 1.0205CM
- 定时器可以设计成一秒,统计下降沿,一个下降沿就是1cm,假设一秒有80脉冲,那么就是80cm/s
#include "reg52.h"
#include <intrins.h>
#include <string.h>
#include <stdio.h>sfr AUXR = 0x8E;sbit left_con1A = P1^1;
sbit left_con2A = P1^2;
sbit right_con1A = P1^3;
sbit right_con2A = P1^4;
sbit Tachometer = P3^2; //测速模块产生下降沿,让外部中断0产生中断
sbit scl = P2^6;
sbit sda = P2^7;char mybuf[24];int signal;
unsigned int cnt;
unsigned int speedCnt = 0;
unsigned int speed;
char speedMsg[24];void Delay5us() //@11.0592MHz
{
}//两个电机反转,前进
void goForward()
{left_con1A = 1;left_con2A = 0;right_con1A = 1; right_con2A = 0;
}//两个电机正转,后退
void goBack()
{left_con1A = 0;left_con2A = 1;right_con1A = 0; right_con2A = 1;
}//两个电机不转,停止
void goStop()
{left_con1A = 0;left_con2A = 0;right_con1A = 0; right_con2A = 0;
}//左电机不转,右电机反转,左转
void goLeft()
{left_con1A = 0;left_con2A = 0;right_con1A = 1; right_con2A = 0;
}//左电机反转,右电机不转,右转
void goRight()
{left_con1A = 1;left_con2A = 0;right_con1A = 0; right_con2A = 0;
}//串口初始化
void uartInit()
{AUXR = 0x01;PCON &= 0x7F; //配置波特率正常SCON = 0x50; //配置串口选择工作方式1,允许串口接收数据//配置定时器1为8位自动重装模式TMOD &= 0x0F;TMOD |= 0x20;//给定时器1,9600波特率初值TH1 = 0xFD; //定时器1初值TL1 = 0xFD; //定时器1重装值ET1 = 0; //不允许定时器1产生中断TR1 = 1; //开启定时器1EA = 1; //开启总中断ES = 1; //开启串口中断}//定时器0初始化,初值为1ms
void Time0Init()
{TMOD &=0xF0; TMOD |=0x01;//1msTL0 = 0x66; TH0 = 0xFC;TR0 = 1;ET0 = 1;EA =1;
}//外部中断0初始化
void int0Init()
{EX0 = 1;EA = 1;IT0 = 1; //下降沿触发外部中断0
}//IIC起始信号
void IIC_start()
{sda = 0;scl = 1;sda = 1;Delay5us();sda = 0;Delay5us();scl = 0;
}//IIC终止信号
void IIC_stop()
{scl = 0;sda = 0;scl = 1;Delay5us();sda = 1;Delay5us();sda = 0;
}//IIC的ACK应答信号
char IIC_ack()
{char flag;scl = 0;sda = 1; //在时钟脉冲9期间释放数据线Delay5us(); //延时5微秒后,为读取sda数据做准备scl = 1; Delay5us(); flag = sda; //读取数据线,0为应答Delay5us(); scl = 0;Delay5us();return flag;
}//IIC发送一个字节
void IIC_sendByte(char myData)
{int i;for ( i = 0; i < 8; i++){//发生数据翻转,选择即将发送的是0还是1scl = 0;sda = myData & 0x80; //获取需要发送字节的最高位到SDADelay5us(); //数据建立时间//开始发送数据scl = 1;Delay5us(); //数据发送时间scl = 0; //发送完毕拉低,等待下1bit数据的传输Delay5us();myData = myData << 1;}
}//OLED写入一条指令
void oledWriteCmd(char writeCmd)
{IIC_start();IIC_sendByte(0x78); //选择一个OLED屏,写模式IIC_ack();IIC_sendByte(0x00); //写入命令,D/C位为0IIC_ack();IIC_sendByte(writeCmd);IIC_ack();IIC_stop();
}//OLED写入一个数据
void oledWriteData(char writeData)
{IIC_start();IIC_sendByte(0x78); //选择一个OLED屏,写模式IIC_ack();IIC_sendByte(0x40); //写入命令,D/C位为0IIC_ack();IIC_sendByte(writeData);IIC_ack();IIC_stop();
}//OLCD初始化
void oledInit()
{oledWriteCmd(0xAE);oledWriteCmd(0x00);oledWriteCmd(0x10);oledWriteCmd(0x40);oledWriteCmd(0xB0);oledWriteCmd(0x81);oledWriteCmd(0xFF);oledWriteCmd(0xA1);oledWriteCmd(0xA6);oledWriteCmd(0xA8);oledWriteCmd(0x3F);oledWriteCmd(0xC8);oledWriteCmd(0xD3);oledWriteCmd(0x00);oledWriteCmd(0xD5);oledWriteCmd(0x80);oledWriteCmd(0xD8);oledWriteCmd(0x05);oledWriteCmd(0xD9);oledWriteCmd(0xF1);oledWriteCmd(0xDA);oledWriteCmd(0x12);oledWriteCmd(0xDB);oledWriteCmd(0x30);oledWriteCmd(0x8D);oledWriteCmd(0x14);oledWriteCmd(0xAF);
}void olceClean()
{int i,j;for(i=0;i<8;i++){oledWriteCmd(0xB0 + i); //选择PAGE//选择PAGE的第0列开始显示oledWriteCmd(0x00); oledWriteCmd(0x10);for(j = 0;j < 128; j++){oledWriteData(0); //写入字符0}}
}//OLED的字符构造点阵
const unsigned char code oledFont[]=
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,// 00x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x30,0x00,0x00,0x00,//! 10x00,0x10,0x0C,0x06,0x10,0x0C,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//" 20x40,0xC0,0x78,0x40,0xC0,0x78,0x40,0x00,0x04,0x3F,0x04,0x04,0x3F,0x04,0x04,0x00,//# 30x00,0x70,0x88,0xFC,0x08,0x30,0x00,0x00,0x00,0x18,0x20,0xFF,0x21,0x1E,0x00,0x00,//$ 40xF0,0x08,0xF0,0x00,0xE0,0x18,0x00,0x00,0x00,0x21,0x1C,0x03,0x1E,0x21,0x1E,0x00,//% 50x00,0xF0,0x08,0x88,0x70,0x00,0x00,0x00,0x1E,0x21,0x23,0x24,0x19,0x27,0x21,0x10,//& 60x10,0x16,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//' 70x00,0x00,0x00,0xE0,0x18,0x04,0x02,0x00,0x00,0x00,0x00,0x07,0x18,0x20,0x40,0x00,//( 80x00,0x02,0x04,0x18,0xE0,0x00,0x00,0x00,0x00,0x40,0x20,0x18,0x07,0x00,0x00,0x00,//) 90x40,0x40,0x80,0xF0,0x80,0x40,0x40,0x00,0x02,0x02,0x01,0x0F,0x01,0x02,0x02,0x00,//* 100x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x1F,0x01,0x01,0x01,0x00,//+ 110x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xB0,0x70,0x00,0x00,0x00,0x00,0x00,//, 120x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,//- 130x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00,//. 140x00,0x00,0x00,0x00,0x80,0x60,0x18,0x04,0x00,0x60,0x18,0x06,0x01,0x00,0x00,0x00,/// 150x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,//0 160x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//1 170x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,//2 180x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,//3 190x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00,//4 200x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00,//5 210x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00,//6 220x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,//7 230x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00,//8 240x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00,//9 250x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,//: 260x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x60,0x00,0x00,0x00,0x00,//; 270x00,0x00,0x80,0x40,0x20,0x10,0x08,0x00,0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x00,//< 280x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00,//= 290x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00,0x00,0x20,0x10,0x08,0x04,0x02,0x01,0x00,//> 300x00,0x70,0x48,0x08,0x08,0x08,0xF0,0x00,0x00,0x00,0x00,0x30,0x36,0x01,0x00,0x00,//? 310xC0,0x30,0xC8,0x28,0xE8,0x10,0xE0,0x00,0x07,0x18,0x27,0x24,0x23,0x14,0x0B,0x00,//@ 320x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00,0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20,//A 330x08,0xF8,0x88,0x88,0x88,0x70,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x11,0x0E,0x00,//B 340xC0,0x30,0x08,0x08,0x08,0x08,0x38,0x00,0x07,0x18,0x20,0x20,0x20,0x10,0x08,0x00,//C 350x08,0xF8,0x08,0x08,0x08,0x10,0xE0,0x00,0x20,0x3F,0x20,0x20,0x20,0x10,0x0F,0x00,//D 360x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x20,0x23,0x20,0x18,0x00,//E 370x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x00,0x03,0x00,0x00,0x00,//F 380xC0,0x30,0x08,0x08,0x08,0x38,0x00,0x00,0x07,0x18,0x20,0x20,0x22,0x1E,0x02,0x00,//G 390x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20,//H 400x00,0x08,0x08,0xF8,0x08,0x08,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//I 410x00,0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,0x00,//J 420x08,0xF8,0x88,0xC0,0x28,0x18,0x08,0x00,0x20,0x3F,0x20,0x01,0x26,0x38,0x20,0x00,//K 430x08,0xF8,0x08,0x00,0x00,0x00,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x20,0x30,0x00,//L 440x08,0xF8,0xF8,0x00,0xF8,0xF8,0x08,0x00,0x20,0x3F,0x00,0x3F,0x00,0x3F,0x20,0x00,//M 450x08,0xF8,0x30,0xC0,0x00,0x08,0xF8,0x08,0x20,0x3F,0x20,0x00,0x07,0x18,0x3F,0x00,//N 460xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x10,0x20,0x20,0x20,0x10,0x0F,0x00,//O 470x08,0xF8,0x08,0x08,0x08,0x08,0xF0,0x00,0x20,0x3F,0x21,0x01,0x01,0x01,0x00,0x00,//P 480xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x18,0x24,0x24,0x38,0x50,0x4F,0x00,//Q 490x08,0xF8,0x88,0x88,0x88,0x88,0x70,0x00,0x20,0x3F,0x20,0x00,0x03,0x0C,0x30,0x20,//R 500x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00,0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00,//S 510x18,0x08,0x08,0xF8,0x08,0x08,0x18,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//T 520x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//U 530x08,0x78,0x88,0x00,0x00,0xC8,0x38,0x08,0x00,0x00,0x07,0x38,0x0E,0x01,0x00,0x00,//V 540xF8,0x08,0x00,0xF8,0x00,0x08,0xF8,0x00,0x03,0x3C,0x07,0x00,0x07,0x3C,0x03,0x00,//W 550x08,0x18,0x68,0x80,0x80,0x68,0x18,0x08,0x20,0x30,0x2C,0x03,0x03,0x2C,0x30,0x20,//X 560x08,0x38,0xC8,0x00,0xC8,0x38,0x08,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//Y 570x10,0x08,0x08,0x08,0xC8,0x38,0x08,0x00,0x20,0x38,0x26,0x21,0x20,0x20,0x18,0x00,//Z 580x00,0x00,0x00,0xFE,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x7F,0x40,0x40,0x40,0x00,//[ 590x00,0x0C,0x30,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x06,0x38,0xC0,0x00,//\ 600x00,0x02,0x02,0x02,0xFE,0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x7F,0x00,0x00,0x00,//] 610x00,0x00,0x04,0x02,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//^ 620x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,//_ 630x00,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//` 640x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x19,0x24,0x22,0x22,0x22,0x3F,0x20,//a 650x08,0xF8,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x3F,0x11,0x20,0x20,0x11,0x0E,0x00,//b 660x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x00,0x0E,0x11,0x20,0x20,0x20,0x11,0x00,//c 670x00,0x00,0x00,0x80,0x80,0x88,0xF8,0x00,0x00,0x0E,0x11,0x20,0x20,0x10,0x3F,0x20,//d 680x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x22,0x22,0x22,0x22,0x13,0x00,//e 690x00,0x80,0x80,0xF0,0x88,0x88,0x88,0x18,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//f 700x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x6B,0x94,0x94,0x94,0x93,0x60,0x00,//g 710x08,0xF8,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//h 720x00,0x80,0x98,0x98,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//i 730x00,0x00,0x00,0x80,0x98,0x98,0x00,0x00,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,//j 740x08,0xF8,0x00,0x00,0x80,0x80,0x80,0x00,0x20,0x3F,0x24,0x02,0x2D,0x30,0x20,0x00,//k 750x00,0x08,0x08,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//l 760x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F,//m 770x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//n 780x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//o 790x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00,0x80,0xFF,0xA1,0x20,0x20,0x11,0x0E,0x00,//p 800x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0E,0x11,0x20,0x20,0xA0,0xFF,0x80,//q 810x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x20,0x20,0x3F,0x21,0x20,0x00,0x01,0x00,//r 820x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x33,0x24,0x24,0x24,0x24,0x19,0x00,//s 830x00,0x80,0x80,0xE0,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x1F,0x20,0x20,0x00,0x00,//t 840x80,0x80,0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20,//u 850x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x00,0x01,0x0E,0x30,0x08,0x06,0x01,0x00,//v 860x80,0x80,0x00,0x80,0x00,0x80,0x80,0x80,0x0F,0x30,0x0C,0x03,0x0C,0x30,0x0F,0x00,//w 870x00,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x31,0x2E,0x0E,0x31,0x20,0x00,//x 880x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x80,0x81,0x8E,0x70,0x18,0x06,0x01,0x00,//y 890x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x21,0x30,0x2C,0x22,0x21,0x30,0x00,//z 900x00,0x00,0x00,0x00,0x80,0x7C,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x3F,0x40,0x40,//{ 910x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,//| 920x00,0x02,0x02,0x7C,0x80,0x00,0x00,0x00,0x00,0x40,0x40,0x3F,0x00,0x00,0x00,0x00,//} 930x00,0x06,0x01,0x01,0x02,0x02,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//~ 94
};//OLED显示一个字符
void oledShowByte(char rows,char columns,char oledByte)
{ unsigned int i;//显示字符的上半部分oledWriteCmd(0xb0+(rows*2-2)); //选择行//选择列 oledWriteCmd(0x00+(columns&0x0f)); oledWriteCmd(0x10+(columns>>4)); //显示数据 for(i=((oledByte-32)*16);i<((oledByte-32)*16+8);i++){oledWriteData(oledFont[i]); }//显示字符的上半部分oledWriteCmd(0xb0+(rows*2-1)); //选择行 //选择列 oledWriteCmd(0x00+(columns&0x0f)); oledWriteCmd(0x10+(columns>>4)); //显示数据 for(i=((oledByte-32)*16+8);i<((oledByte-32)*16+8+8);i++){oledWriteData(oledFont[i]); }
}//OLED显示一个字符串
void oledShowString(char rows,char columns,char *str)
{while(*str != '\0'){oledShowByte(rows,columns,*str);str++;columns += 8; }
}void main()
{uartInit();Time0Init();int0Init();oledInit();olceClean(); //清屏函数oledWriteCmd(0x20); //设置内存oledWriteCmd(0x02); //选择页寻址模式while(1){if(signal == 1){sprintf(speedMsg,"speed:%dcm/s ",speed);olceClean();oledShowString(2,5,speedMsg);signal = 0;}}
}//定时器0产生的中断的处理函数
void Time0Handle() interrupt 1
{cnt++;TL0 = 0x66; TH0 = 0xFC;//每过一秒统计一次产生了多少次下降沿,让main函数向串口发送当前小车速度if(cnt == 1000){cnt = 0;signal = 1; speed = speedCnt;speedCnt = 0;}
}//外部中断0产生的中断的处理函数
void int0Handle() interrupt 0
{speedCnt++; //每产生一个下降沿让标志位+1
}//串口产生的中断的处理函数
void myUart() interrupt 4
{static int i = 0;char tmp;//接收数据后,RI硬件置位产生的中断if(RI){RI = 0; //RI软件清0//获取从pc端接收到的数据tmp = SBUF;if(tmp == 'f' || tmp == 'b' || tmp == 'l' || tmp == 'r' || tmp == 's'){i = 0;}mybuf[i] = tmp;i++;//forwardif(mybuf[0] == 'f' && mybuf[1] == 'o'){goForward();memset(mybuf,'\0',24);}//forwardif(mybuf[0] == 'b' && mybuf[1] == 'a'){goBack();memset(mybuf,'\0',24);}//leftif(mybuf[0] == 'l' && mybuf[1] == 'e'){goLeft();memset(mybuf,'\0',24);}//rightif(mybuf[0] == 'r' && mybuf[1] == 'i'){goRight();memset(mybuf,'\0',24);}//stopif(mybuf[0] == 's' && mybuf[1] == 't'){goStop();memset(mybuf,'\0',24);}if(i == 24){i = 0;}}//发送数据后,TI硬件置位产生的中断if(TI);
}
语音控制小车,循迹、跟随、避障三种功能切换
#include "reg52.h"
#include <intrins.h>#define BZ 1
#define XJ 2
#define GS 3sfr AUXR = 0x8E;//sg90
sbit sg90 = P2^5;
//ultrasonic
sbit Trig = P2^3;
sbit Echo = P2^4;
//oled
sbit scl = P2^6;
sbit sda = P2^7;
//car
sbit left_con1A = P1^1;
sbit left_con2A = P1^2;
sbit right_con1A = P1^3;
sbit right_con2A = P1^4;
//循迹
sbit tracingLeft = P1^5;
sbit tracingRight = P1^6;
//跟随
sbit followLeft = P2^1;
sbit followRight = P2^2;
//su-03t
sbit A25 = P0^1;
sbit A26 = P0^2;
sbit A27 = P0^3;int angle;
int angleBack;
int cnt = 0;double leftDistance;
double rightDistance;
double middleDistance;//OLED的字符构造点阵
const unsigned char code oledFont[]=
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,// 00x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x30,0x00,0x00,0x00,//! 10x00,0x10,0x0C,0x06,0x10,0x0C,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//" 20x40,0xC0,0x78,0x40,0xC0,0x78,0x40,0x00,0x04,0x3F,0x04,0x04,0x3F,0x04,0x04,0x00,//# 30x00,0x70,0x88,0xFC,0x08,0x30,0x00,0x00,0x00,0x18,0x20,0xFF,0x21,0x1E,0x00,0x00,//$ 40xF0,0x08,0xF0,0x00,0xE0,0x18,0x00,0x00,0x00,0x21,0x1C,0x03,0x1E,0x21,0x1E,0x00,//% 50x00,0xF0,0x08,0x88,0x70,0x00,0x00,0x00,0x1E,0x21,0x23,0x24,0x19,0x27,0x21,0x10,//& 60x10,0x16,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//' 70x00,0x00,0x00,0xE0,0x18,0x04,0x02,0x00,0x00,0x00,0x00,0x07,0x18,0x20,0x40,0x00,//( 80x00,0x02,0x04,0x18,0xE0,0x00,0x00,0x00,0x00,0x40,0x20,0x18,0x07,0x00,0x00,0x00,//) 90x40,0x40,0x80,0xF0,0x80,0x40,0x40,0x00,0x02,0x02,0x01,0x0F,0x01,0x02,0x02,0x00,//* 100x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x1F,0x01,0x01,0x01,0x00,//+ 110x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xB0,0x70,0x00,0x00,0x00,0x00,0x00,//, 120x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,//- 130x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00,//. 140x00,0x00,0x00,0x00,0x80,0x60,0x18,0x04,0x00,0x60,0x18,0x06,0x01,0x00,0x00,0x00,/// 150x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,//0 160x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//1 170x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,//2 180x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,//3 190x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00,//4 200x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00,//5 210x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00,//6 220x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,//7 230x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00,//8 240x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00,//9 250x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,//: 260x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x60,0x00,0x00,0x00,0x00,//; 270x00,0x00,0x80,0x40,0x20,0x10,0x08,0x00,0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x00,//< 280x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00,//= 290x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00,0x00,0x20,0x10,0x08,0x04,0x02,0x01,0x00,//> 300x00,0x70,0x48,0x08,0x08,0x08,0xF0,0x00,0x00,0x00,0x00,0x30,0x36,0x01,0x00,0x00,//? 310xC0,0x30,0xC8,0x28,0xE8,0x10,0xE0,0x00,0x07,0x18,0x27,0x24,0x23,0x14,0x0B,0x00,//@ 320x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00,0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20,//A 330x08,0xF8,0x88,0x88,0x88,0x70,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x11,0x0E,0x00,//B 340xC0,0x30,0x08,0x08,0x08,0x08,0x38,0x00,0x07,0x18,0x20,0x20,0x20,0x10,0x08,0x00,//C 350x08,0xF8,0x08,0x08,0x08,0x10,0xE0,0x00,0x20,0x3F,0x20,0x20,0x20,0x10,0x0F,0x00,//D 360x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x20,0x23,0x20,0x18,0x00,//E 370x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x00,0x03,0x00,0x00,0x00,//F 380xC0,0x30,0x08,0x08,0x08,0x38,0x00,0x00,0x07,0x18,0x20,0x20,0x22,0x1E,0x02,0x00,//G 390x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20,//H 400x00,0x08,0x08,0xF8,0x08,0x08,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//I 410x00,0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,0x00,//J 420x08,0xF8,0x88,0xC0,0x28,0x18,0x08,0x00,0x20,0x3F,0x20,0x01,0x26,0x38,0x20,0x00,//K 430x08,0xF8,0x08,0x00,0x00,0x00,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x20,0x30,0x00,//L 440x08,0xF8,0xF8,0x00,0xF8,0xF8,0x08,0x00,0x20,0x3F,0x00,0x3F,0x00,0x3F,0x20,0x00,//M 450x08,0xF8,0x30,0xC0,0x00,0x08,0xF8,0x08,0x20,0x3F,0x20,0x00,0x07,0x18,0x3F,0x00,//N 460xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x10,0x20,0x20,0x20,0x10,0x0F,0x00,//O 470x08,0xF8,0x08,0x08,0x08,0x08,0xF0,0x00,0x20,0x3F,0x21,0x01,0x01,0x01,0x00,0x00,//P 480xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x18,0x24,0x24,0x38,0x50,0x4F,0x00,//Q 490x08,0xF8,0x88,0x88,0x88,0x88,0x70,0x00,0x20,0x3F,0x20,0x00,0x03,0x0C,0x30,0x20,//R 500x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00,0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00,//S 510x18,0x08,0x08,0xF8,0x08,0x08,0x18,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//T 520x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//U 530x08,0x78,0x88,0x00,0x00,0xC8,0x38,0x08,0x00,0x00,0x07,0x38,0x0E,0x01,0x00,0x00,//V 540xF8,0x08,0x00,0xF8,0x00,0x08,0xF8,0x00,0x03,0x3C,0x07,0x00,0x07,0x3C,0x03,0x00,//W 550x08,0x18,0x68,0x80,0x80,0x68,0x18,0x08,0x20,0x30,0x2C,0x03,0x03,0x2C,0x30,0x20,//X 560x08,0x38,0xC8,0x00,0xC8,0x38,0x08,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//Y 570x10,0x08,0x08,0x08,0xC8,0x38,0x08,0x00,0x20,0x38,0x26,0x21,0x20,0x20,0x18,0x00,//Z 580x00,0x00,0x00,0xFE,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x7F,0x40,0x40,0x40,0x00,//[ 590x00,0x0C,0x30,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x06,0x38,0xC0,0x00,//\ 600x00,0x02,0x02,0x02,0xFE,0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x7F,0x00,0x00,0x00,//] 610x00,0x00,0x04,0x02,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//^ 620x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,//_ 630x00,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//` 640x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x19,0x24,0x22,0x22,0x22,0x3F,0x20,//a 650x08,0xF8,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x3F,0x11,0x20,0x20,0x11,0x0E,0x00,//b 660x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x00,0x0E,0x11,0x20,0x20,0x20,0x11,0x00,//c 670x00,0x00,0x00,0x80,0x80,0x88,0xF8,0x00,0x00,0x0E,0x11,0x20,0x20,0x10,0x3F,0x20,//d 680x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x22,0x22,0x22,0x22,0x13,0x00,//e 690x00,0x80,0x80,0xF0,0x88,0x88,0x88,0x18,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//f 700x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x6B,0x94,0x94,0x94,0x93,0x60,0x00,//g 710x08,0xF8,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//h 720x00,0x80,0x98,0x98,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//i 730x00,0x00,0x00,0x80,0x98,0x98,0x00,0x00,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,//j 740x08,0xF8,0x00,0x00,0x80,0x80,0x80,0x00,0x20,0x3F,0x24,0x02,0x2D,0x30,0x20,0x00,//k 750x00,0x08,0x08,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//l 760x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F,//m 770x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//n 780x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//o 790x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00,0x80,0xFF,0xA1,0x20,0x20,0x11,0x0E,0x00,//p 800x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0E,0x11,0x20,0x20,0xA0,0xFF,0x80,//q 810x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x20,0x20,0x3F,0x21,0x20,0x00,0x01,0x00,//r 820x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x33,0x24,0x24,0x24,0x24,0x19,0x00,//s 830x00,0x80,0x80,0xE0,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x1F,0x20,0x20,0x00,0x00,//t 840x80,0x80,0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20,//u 850x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x00,0x01,0x0E,0x30,0x08,0x06,0x01,0x00,//v 860x80,0x80,0x00,0x80,0x00,0x80,0x80,0x80,0x0F,0x30,0x0C,0x03,0x0C,0x30,0x0F,0x00,//w 870x00,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x31,0x2E,0x0E,0x31,0x20,0x00,//x 880x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x80,0x81,0x8E,0x70,0x18,0x06,0x01,0x00,//y 890x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x21,0x30,0x2C,0x22,0x21,0x30,0x00,//z 900x00,0x00,0x00,0x00,0x80,0x7C,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x3F,0x40,0x40,//{ 910x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,//| 920x00,0x02,0x02,0x7C,0x80,0x00,0x00,0x00,0x00,0x40,0x40,0x3F,0x00,0x00,0x00,0x00,//} 930x00,0x06,0x01,0x01,0x02,0x02,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//~ 94
};void Delay5us() //@11.0592MHz
{
}void Delay10us() //@11.0592MHz
{unsigned char i;i = 2;while (--i);
}void Delay100ms() //@11.0592MHz
{unsigned char i, j;i = 180;j = 73;do{while (--j);} 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 Delay500ms() //@11.0592MHz
{unsigned char i, j, k;_nop_();i = 4;j = 129;k = 119;do{do{while (--k);} while (--j);} while (--i);
}//sg90
void timer0Init()
{//设置定时器0为16为计时模式TMOD &=0xF0; TMOD |=0x01; //设置定时器0定时时间为0.5msTH0 = 0xFE;TL0 = 0x33;TR0 = 1; //定时器0开始计时TF0 = 0; //不执行定时器0爆表时导致的中断ET0 = 1; //定时器0中断开关EA = 1; //总中断开关
}void sg90Left()
{angle = 5; //180°if(angleBack != angle){ cnt = 0;}angleBack = angle;Delay100ms();
} void sg90Middle()
{angle = 3; //90°if(angleBack != angle){ cnt = 0;}angleBack = angle;Delay100ms();
} void sg90Right()
{angle = 1; //0°if(angleBack != angle){ cnt = 0;}angleBack = angle;Delay100ms();
}//ultrasonic
void timer1Init()
{ //设置定时器1为16为计时模式TMOD &= 0x0F;TMOD |= 0x10; TH1 = 0x00;TL1 = 0x00;
}void ultrasonicStart()
{Trig = 0;Trig = 1;Delay10us();Trig = 0;
}double getDistance()
{double time = 0;//定时器1清0TH1 = 0x00;TL1 = 0x00;ultrasonicStart();while(Echo == 0); //当Echo引脚从低电平跳到高电平时开启定时器1TR1 = 1;while(Echo == 1); //当Echo引脚从高电平跳到低电平时关闭定时器1TR1 = 0;time = (TH1*256 + TL1) * 1.085; //微秒return (time * 0.017);
}//oled
//IIC起始信号
void IIC_start()
{sda = 0;scl = 1;sda = 1;Delay5us();sda = 0;Delay5us();scl = 0;
}//IIC终止信号
void IIC_stop()
{scl = 0;sda = 0;scl = 1;Delay5us();sda = 1;Delay5us();sda = 0;
}//IIC的ACK应答信号
char IIC_ack()
{char flag;scl = 0;sda = 1; //在时钟脉冲9期间释放数据线Delay5us(); //延时5微秒后,为读取sda数据做准备scl = 1; Delay5us(); flag = sda; //读取数据线,0为应答Delay5us(); scl = 0;Delay5us();return flag;
}//IIC发送一个字节
void IIC_sendByte(char myData)
{int i;for ( i = 0; i < 8; i++){//发生数据翻转,选择即将发送的是0还是1scl = 0;sda = myData & 0x80; //获取需要发送字节的最高位到SDADelay5us(); //数据建立时间//开始发送数据scl = 1;Delay5us(); //数据发送时间scl = 0; //发送完毕拉低,等待下1bit数据的传输Delay5us();myData = myData << 1;}
}//OLED写入一条指令
void oledWriteCmd(char writeCmd)
{IIC_start();IIC_sendByte(0x78); //选择一个OLED屏,写模式IIC_ack();IIC_sendByte(0x00); //写入命令,D/C位为0IIC_ack();IIC_sendByte(writeCmd);IIC_ack();IIC_stop();
}//OLED写入一个数据
void oledWriteData(char writeData)
{IIC_start();IIC_sendByte(0x78); //选择一个OLED屏,写模式IIC_ack();IIC_sendByte(0x40); //写入命令,D/C位为0IIC_ack();IIC_sendByte(writeData);IIC_ack();IIC_stop();
}//OLCD初始化
void oledInit()
{oledWriteCmd(0xAE);oledWriteCmd(0x00);oledWriteCmd(0x10);oledWriteCmd(0x40);oledWriteCmd(0xB0);oledWriteCmd(0x81);oledWriteCmd(0xFF);oledWriteCmd(0xA1);oledWriteCmd(0xA6);oledWriteCmd(0xA8);oledWriteCmd(0x3F);oledWriteCmd(0xC8);oledWriteCmd(0xD3);oledWriteCmd(0x00);oledWriteCmd(0xD5);oledWriteCmd(0x80);oledWriteCmd(0xD8);oledWriteCmd(0x05);oledWriteCmd(0xD9);oledWriteCmd(0xF1);oledWriteCmd(0xDA);oledWriteCmd(0x12);oledWriteCmd(0xDB);oledWriteCmd(0x30);oledWriteCmd(0x8D);oledWriteCmd(0x14);oledWriteCmd(0xAF);
}//OLED清屏函数
void olceClean()
{int i,j;for(i=0;i<8;i++){oledWriteCmd(0xB0 + i); //选择PAGE//选择PAGE的第0列开始显示oledWriteCmd(0x00); oledWriteCmd(0x10);for(j = 0;j < 128; j++){oledWriteData(0); //写入字符0}}
}//OLED显示一个字符
void oledShowByte(char rows,char columns,char oledByte)
{ unsigned int i;//显示字符的上半部分oledWriteCmd(0xb0+(rows*2-2)); //选择行//选择列 oledWriteCmd(0x00+(columns&0x0f)); oledWriteCmd(0x10+(columns>>4)); //显示数据 for(i=((oledByte-32)*16);i<((oledByte-32)*16+8);i++){oledWriteData(oledFont[i]); }//显示字符的上半部分oledWriteCmd(0xb0+(rows*2-1)); //选择行 //选择列 oledWriteCmd(0x00+(columns&0x0f)); oledWriteCmd(0x10+(columns>>4)); //显示数据 for(i=((oledByte-32)*16+8);i<((oledByte-32)*16+8+8);i++){oledWriteData(oledFont[i]); }
}//OLED显示一个字符串
void oledShowString(char rows,char columns,char *str)
{while(*str != '\0'){oledShowByte(rows,columns,*str);str++;columns += 8; }
}//car
//两个电机反转,前进
void goForward()
{left_con1A = 1;left_con2A = 0;right_con1A = 1; right_con2A = 0;
}//两个电机正转,后退
void goBack()
{left_con1A = 0;left_con2A = 1;right_con1A = 0; right_con2A = 1;
}//两个电机不转,停止
void goStop()
{left_con1A = 0;left_con2A = 0;right_con1A = 0; right_con2A = 0;
}//左电机不转,右电机反转,左转
void goLeft()
{left_con1A = 0;left_con2A = 0;right_con1A = 1; right_con2A = 0;
}//左电机反转,右电机不转,右转
void goRight()
{left_con1A = 1;left_con2A = 0;right_con1A = 0; right_con2A = 0;
}//循迹模式
void tracingMode()
{ if(tracingLeft == 0 && tracingRight == 0){ goForward();}if(tracingLeft == 0 && tracingRight == 1){goRight();}if(tracingLeft == 1 && tracingRight == 0){goLeft();}if(tracingLeft == 1 && tracingRight == 1){goStop();}
}//跟随模式
void followMode()
{ if(followLeft == 0 && followRight == 0){ //goForward();}if(followLeft == 0 && followRight == 1){goRight();}if(followLeft == 1 && followRight == 0){goLeft();}if(followLeft == 1 && followRight == 1){goStop();}
}//避障模式
void avoidMode()
{sg90Middle();Delay300ms();middleDistance = getDistance();if(middleDistance > 35){goForward();}else{goStop();sg90Left();Delay300ms();leftDistance = getDistance();sg90Middle();Delay300ms();sg90Right();Delay300ms();rightDistance = getDistance();if(leftDistance < 15 && rightDistance < 15){goBack();Delay500ms();goStop();}else{if(leftDistance > rightDistance){goLeft();Delay500ms();goStop();}if(rightDistance > leftDistance){goRight();Delay500ms();goStop();}}}
}void main()
{int mark = 0;timer0Init();timer1Init();sg90Middle();Delay500ms();oledInit();olceClean();oledShowString(2,5,"haozige");while(1){if(A25 == 0 && A26 == 1 && A27 == 1){if(mark != GS){olceClean();oledShowString(2,5,"genshuai");}mark = GS;followMode(); }if(A25 == 1 && A26 == 0 && A27 == 1){if(mark != BZ){olceClean();oledShowString(2,5,"bizhang");}mark = BZ;avoidMode(); }if(A25 == 1 && A26 == 1 && A27 == 0){if(mark != XJ){olceClean();oledShowString(2,5,"xunji");}mark = XJ;tracingMode(); }}
}//定时器0的中断函数
void Time0Handler() interrupt 1
{TH0 = 0xFE;TL0 = 0x33;cnt++;//控制占空比if(cnt < angle){sg90 = 1;}else{sg90 = 0;}if(cnt == 40){ //每个周期为20mscnt = 0;sg90 = 1;}
}