目录
基本概述
硬件组成
功能
关键字
模块介绍
电机模块L9110S
循迹模块(TCRT5000传感器)
红外避障模块
测速模块
小车
移动小车(控制电机转动,使小车前进、后退、左转、右转 )
遥控小车( 使用蓝牙模块,通过串口发送信息控制小车移动)
调速小车(利用PWM波对电机进行调速)
循迹小车 (利用循迹模块进行黑白色的检测)
跟随小车(利用红外避障模块完成跟随行为)
避障小车(利用超声波测距完成避障行为)
语音控制小车,循迹、跟随、避障三种功能切换
基本概述
硬件组成
电机模块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; //开启定时器1
EA = 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++;
//forward
if(mybuf[0] == 'f' && mybuf[1] == 'o'){
goForward();
memset(mybuf,'\0',24);
}
//forward
if(mybuf[0] == 'b' && mybuf[1] == 'a'){
goBack();
memset(mybuf,'\0',24);
}
//left
if(mybuf[0] == 'l' && mybuf[1] == 'e'){
goLeft();
memset(mybuf,'\0',24);
}
//right
if(mybuf[0] == 'r' && mybuf[1] == 'i'){
goRight();
memset(mybuf,'\0',24);
}
//stop
if(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; //设置定时器模式
//定时器初值为1ms
TL0 = 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; //设置定时器模式
//定时器初值为1ms
TL1 = 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; //设置定时器模式
//定时器初值为1ms
TL0 = 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; //设置定时器模式
//定时器初值为1ms
TL1 = 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; //设置定时器模式
//定时器初值为1ms
TL0 = 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; //设置定时器模式
//定时器初值为1ms
TL1 = 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.5ms
TH0 = 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清0
TH1 = 0x00;
TL1 = 0x00;
ultrasonicStart();
while(Echo == 0); //当Echo引脚从低电平跳到高电平时开启定时器1
TR1 = 1;
while(Echo == 1); //当Echo引脚从高电平跳到低电平时关闭定时器1
TR1 = 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){ //每个周期为20ms
cnt = 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; //开启定时器1
EA = 1; //开启总中断
ES = 1; //开启串口中断
}
//定时器0初始化,初值为1ms
void Time0Init()
{
TMOD &=0xF0;
TMOD |=0x01;
//1ms
TL0 = 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还是1
scl = 0;
sda = myData & 0x80; //获取需要发送字节的最高位到SDA
Delay5us(); //数据建立时间
//开始发送数据
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位为0
IIC_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位为0
IIC_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,// 0
0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x30,0x00,0x00,0x00,//! 1
0x00,0x10,0x0C,0x06,0x10,0x0C,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//" 2
0x40,0xC0,0x78,0x40,0xC0,0x78,0x40,0x00,0x04,0x3F,0x04,0x04,0x3F,0x04,0x04,0x00,//# 3
0x00,0x70,0x88,0xFC,0x08,0x30,0x00,0x00,0x00,0x18,0x20,0xFF,0x21,0x1E,0x00,0x00,//$ 4
0xF0,0x08,0xF0,0x00,0xE0,0x18,0x00,0x00,0x00,0x21,0x1C,0x03,0x1E,0x21,0x1E,0x00,//% 5
0x00,0xF0,0x08,0x88,0x70,0x00,0x00,0x00,0x1E,0x21,0x23,0x24,0x19,0x27,0x21,0x10,//& 6
0x10,0x16,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//' 7
0x00,0x00,0x00,0xE0,0x18,0x04,0x02,0x00,0x00,0x00,0x00,0x07,0x18,0x20,0x40,0x00,//( 8
0x00,0x02,0x04,0x18,0xE0,0x00,0x00,0x00,0x00,0x40,0x20,0x18,0x07,0x00,0x00,0x00,//) 9
0x40,0x40,0x80,0xF0,0x80,0x40,0x40,0x00,0x02,0x02,0x01,0x0F,0x01,0x02,0x02,0x00,//* 10
0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x1F,0x01,0x01,0x01,0x00,//+ 11
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xB0,0x70,0x00,0x00,0x00,0x00,0x00,//, 12
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,//- 13
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00,//. 14
0x00,0x00,0x00,0x00,0x80,0x60,0x18,0x04,0x00,0x60,0x18,0x06,0x01,0x00,0x00,0x00,/// 15
0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,//0 16
0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//1 17
0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,//2 18
0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,//3 19
0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00,//4 20
0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00,//5 21
0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00,//6 22
0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,//7 23
0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00,//8 24
0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00,//9 25
0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,//: 26
0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x60,0x00,0x00,0x00,0x00,//; 27
0x00,0x00,0x80,0x40,0x20,0x10,0x08,0x00,0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x00,//< 28
0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00,//= 29
0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00,0x00,0x20,0x10,0x08,0x04,0x02,0x01,0x00,//> 30
0x00,0x70,0x48,0x08,0x08,0x08,0xF0,0x00,0x00,0x00,0x00,0x30,0x36,0x01,0x00,0x00,//? 31
0xC0,0x30,0xC8,0x28,0xE8,0x10,0xE0,0x00,0x07,0x18,0x27,0x24,0x23,0x14,0x0B,0x00,//@ 32
0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00,0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20,//A 33
0x08,0xF8,0x88,0x88,0x88,0x70,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x11,0x0E,0x00,//B 34
0xC0,0x30,0x08,0x08,0x08,0x08,0x38,0x00,0x07,0x18,0x20,0x20,0x20,0x10,0x08,0x00,//C 35
0x08,0xF8,0x08,0x08,0x08,0x10,0xE0,0x00,0x20,0x3F,0x20,0x20,0x20,0x10,0x0F,0x00,//D 36
0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x20,0x23,0x20,0x18,0x00,//E 37
0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x00,0x03,0x00,0x00,0x00,//F 38
0xC0,0x30,0x08,0x08,0x08,0x38,0x00,0x00,0x07,0x18,0x20,0x20,0x22,0x1E,0x02,0x00,//G 39
0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20,//H 40
0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//I 41
0x00,0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,0x00,//J 42
0x08,0xF8,0x88,0xC0,0x28,0x18,0x08,0x00,0x20,0x3F,0x20,0x01,0x26,0x38,0x20,0x00,//K 43
0x08,0xF8,0x08,0x00,0x00,0x00,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x20,0x30,0x00,//L 44
0x08,0xF8,0xF8,0x00,0xF8,0xF8,0x08,0x00,0x20,0x3F,0x00,0x3F,0x00,0x3F,0x20,0x00,//M 45
0x08,0xF8,0x30,0xC0,0x00,0x08,0xF8,0x08,0x20,0x3F,0x20,0x00,0x07,0x18,0x3F,0x00,//N 46
0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x10,0x20,0x20,0x20,0x10,0x0F,0x00,//O 47
0x08,0xF8,0x08,0x08,0x08,0x08,0xF0,0x00,0x20,0x3F,0x21,0x01,0x01,0x01,0x00,0x00,//P 48
0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x18,0x24,0x24,0x38,0x50,0x4F,0x00,//Q 49
0x08,0xF8,0x88,0x88,0x88,0x88,0x70,0x00,0x20,0x3F,0x20,0x00,0x03,0x0C,0x30,0x20,//R 50
0x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00,0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00,//S 51
0x18,0x08,0x08,0xF8,0x08,0x08,0x18,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//T 52
0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//U 53
0x08,0x78,0x88,0x00,0x00,0xC8,0x38,0x08,0x00,0x00,0x07,0x38,0x0E,0x01,0x00,0x00,//V 54
0xF8,0x08,0x00,0xF8,0x00,0x08,0xF8,0x00,0x03,0x3C,0x07,0x00,0x07,0x3C,0x03,0x00,//W 55
0x08,0x18,0x68,0x80,0x80,0x68,0x18,0x08,0x20,0x30,0x2C,0x03,0x03,0x2C,0x30,0x20,//X 56
0x08,0x38,0xC8,0x00,0xC8,0x38,0x08,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//Y 57
0x10,0x08,0x08,0x08,0xC8,0x38,0x08,0x00,0x20,0x38,0x26,0x21,0x20,0x20,0x18,0x00,//Z 58
0x00,0x00,0x00,0xFE,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x7F,0x40,0x40,0x40,0x00,//[ 59
0x00,0x0C,0x30,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x06,0x38,0xC0,0x00,//\ 60
0x00,0x02,0x02,0x02,0xFE,0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x7F,0x00,0x00,0x00,//] 61
0x00,0x00,0x04,0x02,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//^ 62
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,//_ 63
0x00,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//` 64
0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x19,0x24,0x22,0x22,0x22,0x3F,0x20,//a 65
0x08,0xF8,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x3F,0x11,0x20,0x20,0x11,0x0E,0x00,//b 66
0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x00,0x0E,0x11,0x20,0x20,0x20,0x11,0x00,//c 67
0x00,0x00,0x00,0x80,0x80,0x88,0xF8,0x00,0x00,0x0E,0x11,0x20,0x20,0x10,0x3F,0x20,//d 68
0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x22,0x22,0x22,0x22,0x13,0x00,//e 69
0x00,0x80,0x80,0xF0,0x88,0x88,0x88,0x18,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//f 70
0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x6B,0x94,0x94,0x94,0x93,0x60,0x00,//g 71
0x08,0xF8,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//h 72
0x00,0x80,0x98,0x98,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//i 73
0x00,0x00,0x00,0x80,0x98,0x98,0x00,0x00,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,//j 74
0x08,0xF8,0x00,0x00,0x80,0x80,0x80,0x00,0x20,0x3F,0x24,0x02,0x2D,0x30,0x20,0x00,//k 75
0x00,0x08,0x08,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//l 76
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F,//m 77
0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//n 78
0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//o 79
0x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00,0x80,0xFF,0xA1,0x20,0x20,0x11,0x0E,0x00,//p 80
0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0E,0x11,0x20,0x20,0xA0,0xFF,0x80,//q 81
0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x20,0x20,0x3F,0x21,0x20,0x00,0x01,0x00,//r 82
0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x33,0x24,0x24,0x24,0x24,0x19,0x00,//s 83
0x00,0x80,0x80,0xE0,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x1F,0x20,0x20,0x00,0x00,//t 84
0x80,0x80,0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20,//u 85
0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x00,0x01,0x0E,0x30,0x08,0x06,0x01,0x00,//v 86
0x80,0x80,0x00,0x80,0x00,0x80,0x80,0x80,0x0F,0x30,0x0C,0x03,0x0C,0x30,0x0F,0x00,//w 87
0x00,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x31,0x2E,0x0E,0x31,0x20,0x00,//x 88
0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x80,0x81,0x8E,0x70,0x18,0x06,0x01,0x00,//y 89
0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x21,0x30,0x2C,0x22,0x21,0x30,0x00,//z 90
0x00,0x00,0x00,0x00,0x80,0x7C,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x3F,0x40,0x40,//{ 91
0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,//| 92
0x00,0x02,0x02,0x7C,0x80,0x00,0x00,0x00,0x00,0x40,0x40,0x3F,0x00,0x00,0x00,0x00,//} 93
0x00,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++;
//forward
if(mybuf[0] == 'f' && mybuf[1] == 'o'){
goForward();
memset(mybuf,'\0',24);
}
//forward
if(mybuf[0] == 'b' && mybuf[1] == 'a'){
goBack();
memset(mybuf,'\0',24);
}
//left
if(mybuf[0] == 'l' && mybuf[1] == 'e'){
goLeft();
memset(mybuf,'\0',24);
}
//right
if(mybuf[0] == 'r' && mybuf[1] == 'i'){
goRight();
memset(mybuf,'\0',24);
}
//stop
if(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 3
sfr 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,// 0
0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x30,0x00,0x00,0x00,//! 1
0x00,0x10,0x0C,0x06,0x10,0x0C,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//" 2
0x40,0xC0,0x78,0x40,0xC0,0x78,0x40,0x00,0x04,0x3F,0x04,0x04,0x3F,0x04,0x04,0x00,//# 3
0x00,0x70,0x88,0xFC,0x08,0x30,0x00,0x00,0x00,0x18,0x20,0xFF,0x21,0x1E,0x00,0x00,//$ 4
0xF0,0x08,0xF0,0x00,0xE0,0x18,0x00,0x00,0x00,0x21,0x1C,0x03,0x1E,0x21,0x1E,0x00,//% 5
0x00,0xF0,0x08,0x88,0x70,0x00,0x00,0x00,0x1E,0x21,0x23,0x24,0x19,0x27,0x21,0x10,//& 6
0x10,0x16,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//' 7
0x00,0x00,0x00,0xE0,0x18,0x04,0x02,0x00,0x00,0x00,0x00,0x07,0x18,0x20,0x40,0x00,//( 8
0x00,0x02,0x04,0x18,0xE0,0x00,0x00,0x00,0x00,0x40,0x20,0x18,0x07,0x00,0x00,0x00,//) 9
0x40,0x40,0x80,0xF0,0x80,0x40,0x40,0x00,0x02,0x02,0x01,0x0F,0x01,0x02,0x02,0x00,//* 10
0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x1F,0x01,0x01,0x01,0x00,//+ 11
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xB0,0x70,0x00,0x00,0x00,0x00,0x00,//, 12
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,//- 13
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00,//. 14
0x00,0x00,0x00,0x00,0x80,0x60,0x18,0x04,0x00,0x60,0x18,0x06,0x01,0x00,0x00,0x00,/// 15
0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,//0 16
0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//1 17
0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,//2 18
0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,//3 19
0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00,//4 20
0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00,//5 21
0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00,//6 22
0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,//7 23
0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00,//8 24
0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00,//9 25
0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,//: 26
0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x60,0x00,0x00,0x00,0x00,//; 27
0x00,0x00,0x80,0x40,0x20,0x10,0x08,0x00,0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x00,//< 28
0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00,//= 29
0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00,0x00,0x20,0x10,0x08,0x04,0x02,0x01,0x00,//> 30
0x00,0x70,0x48,0x08,0x08,0x08,0xF0,0x00,0x00,0x00,0x00,0x30,0x36,0x01,0x00,0x00,//? 31
0xC0,0x30,0xC8,0x28,0xE8,0x10,0xE0,0x00,0x07,0x18,0x27,0x24,0x23,0x14,0x0B,0x00,//@ 32
0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00,0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20,//A 33
0x08,0xF8,0x88,0x88,0x88,0x70,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x11,0x0E,0x00,//B 34
0xC0,0x30,0x08,0x08,0x08,0x08,0x38,0x00,0x07,0x18,0x20,0x20,0x20,0x10,0x08,0x00,//C 35
0x08,0xF8,0x08,0x08,0x08,0x10,0xE0,0x00,0x20,0x3F,0x20,0x20,0x20,0x10,0x0F,0x00,//D 36
0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x20,0x23,0x20,0x18,0x00,//E 37
0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x00,0x03,0x00,0x00,0x00,//F 38
0xC0,0x30,0x08,0x08,0x08,0x38,0x00,0x00,0x07,0x18,0x20,0x20,0x22,0x1E,0x02,0x00,//G 39
0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20,//H 40
0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//I 41
0x00,0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,0x00,//J 42
0x08,0xF8,0x88,0xC0,0x28,0x18,0x08,0x00,0x20,0x3F,0x20,0x01,0x26,0x38,0x20,0x00,//K 43
0x08,0xF8,0x08,0x00,0x00,0x00,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x20,0x30,0x00,//L 44
0x08,0xF8,0xF8,0x00,0xF8,0xF8,0x08,0x00,0x20,0x3F,0x00,0x3F,0x00,0x3F,0x20,0x00,//M 45
0x08,0xF8,0x30,0xC0,0x00,0x08,0xF8,0x08,0x20,0x3F,0x20,0x00,0x07,0x18,0x3F,0x00,//N 46
0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x10,0x20,0x20,0x20,0x10,0x0F,0x00,//O 47
0x08,0xF8,0x08,0x08,0x08,0x08,0xF0,0x00,0x20,0x3F,0x21,0x01,0x01,0x01,0x00,0x00,//P 48
0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x18,0x24,0x24,0x38,0x50,0x4F,0x00,//Q 49
0x08,0xF8,0x88,0x88,0x88,0x88,0x70,0x00,0x20,0x3F,0x20,0x00,0x03,0x0C,0x30,0x20,//R 50
0x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00,0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00,//S 51
0x18,0x08,0x08,0xF8,0x08,0x08,0x18,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//T 52
0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//U 53
0x08,0x78,0x88,0x00,0x00,0xC8,0x38,0x08,0x00,0x00,0x07,0x38,0x0E,0x01,0x00,0x00,//V 54
0xF8,0x08,0x00,0xF8,0x00,0x08,0xF8,0x00,0x03,0x3C,0x07,0x00,0x07,0x3C,0x03,0x00,//W 55
0x08,0x18,0x68,0x80,0x80,0x68,0x18,0x08,0x20,0x30,0x2C,0x03,0x03,0x2C,0x30,0x20,//X 56
0x08,0x38,0xC8,0x00,0xC8,0x38,0x08,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//Y 57
0x10,0x08,0x08,0x08,0xC8,0x38,0x08,0x00,0x20,0x38,0x26,0x21,0x20,0x20,0x18,0x00,//Z 58
0x00,0x00,0x00,0xFE,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x7F,0x40,0x40,0x40,0x00,//[ 59
0x00,0x0C,0x30,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x06,0x38,0xC0,0x00,//\ 60
0x00,0x02,0x02,0x02,0xFE,0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x7F,0x00,0x00,0x00,//] 61
0x00,0x00,0x04,0x02,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//^ 62
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,//_ 63
0x00,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//` 64
0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x19,0x24,0x22,0x22,0x22,0x3F,0x20,//a 65
0x08,0xF8,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x3F,0x11,0x20,0x20,0x11,0x0E,0x00,//b 66
0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x00,0x0E,0x11,0x20,0x20,0x20,0x11,0x00,//c 67
0x00,0x00,0x00,0x80,0x80,0x88,0xF8,0x00,0x00,0x0E,0x11,0x20,0x20,0x10,0x3F,0x20,//d 68
0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x22,0x22,0x22,0x22,0x13,0x00,//e 69
0x00,0x80,0x80,0xF0,0x88,0x88,0x88,0x18,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//f 70
0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x6B,0x94,0x94,0x94,0x93,0x60,0x00,//g 71
0x08,0xF8,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//h 72
0x00,0x80,0x98,0x98,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//i 73
0x00,0x00,0x00,0x80,0x98,0x98,0x00,0x00,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,//j 74
0x08,0xF8,0x00,0x00,0x80,0x80,0x80,0x00,0x20,0x3F,0x24,0x02,0x2D,0x30,0x20,0x00,//k 75
0x00,0x08,0x08,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//l 76
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F,//m 77
0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//n 78
0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//o 79
0x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00,0x80,0xFF,0xA1,0x20,0x20,0x11,0x0E,0x00,//p 80
0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0E,0x11,0x20,0x20,0xA0,0xFF,0x80,//q 81
0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x20,0x20,0x3F,0x21,0x20,0x00,0x01,0x00,//r 82
0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x33,0x24,0x24,0x24,0x24,0x19,0x00,//s 83
0x00,0x80,0x80,0xE0,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x1F,0x20,0x20,0x00,0x00,//t 84
0x80,0x80,0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20,//u 85
0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x00,0x01,0x0E,0x30,0x08,0x06,0x01,0x00,//v 86
0x80,0x80,0x00,0x80,0x00,0x80,0x80,0x80,0x0F,0x30,0x0C,0x03,0x0C,0x30,0x0F,0x00,//w 87
0x00,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x31,0x2E,0x0E,0x31,0x20,0x00,//x 88
0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x80,0x81,0x8E,0x70,0x18,0x06,0x01,0x00,//y 89
0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x21,0x30,0x2C,0x22,0x21,0x30,0x00,//z 90
0x00,0x00,0x00,0x00,0x80,0x7C,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x3F,0x40,0x40,//{ 91
0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,//| 92
0x00,0x02,0x02,0x7C,0x80,0x00,0x00,0x00,0x00,0x40,0x40,0x3F,0x00,0x00,0x00,0x00,//} 93
0x00,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.5ms
TH0 = 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清0
TH1 = 0x00;
TL1 = 0x00;
ultrasonicStart();
while(Echo == 0); //当Echo引脚从低电平跳到高电平时开启定时器1
TR1 = 1;
while(Echo == 1); //当Echo引脚从高电平跳到低电平时关闭定时器1
TR1 = 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还是1
scl = 0;
sda = myData & 0x80; //获取需要发送字节的最高位到SDA
Delay5us(); //数据建立时间
//开始发送数据
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位为0
IIC_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位为0
IIC_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){ //每个周期为20ms
cnt = 0;
sg90 = 1;
}
}