可用串口控制小车前进后退左转右转,开启或关闭避障模式,将蓝牙模块接到串口上,就可用手机HC蓝牙助手控制小车启动或切换到避障模式
拿前面舵机摇头+超声波测距避障的代码来进行修改,新增串口控制的功能即可
1.main.c:定时器0、定时器2、串口的初始化函数调用,while循环内进行避障函数的调用
2.Motor.c:小车前进、后退、左转、右转和停止的函数,左右转函数是一个轮前进,另一个轮后退
3.Delay.c:延时函数
4.Sg90.c:定时器0初始化函数,中断PWM,舵机摇头的角度(封装成函数)
5.HC-SR04.c:定时器2初始化函数,不开启中断,因为这次用到串口控制,要用定时器1作波特率发生器,所以超声波改为用定时器2,超声波测距的函数
6.Avoid.c:将上次超声波避障的逻辑代码进行函数封装,单独写成一个源文件,供主函数调用
7.Uart.c:串口初始化函数,中断处理也是使用之前的判断逻辑
Avoid.c:
把前面测距避障的代码进行封装整合,写成一个源文件
#include
#include "Delay.h"
#include "Motor.h"
#include "HC-SR04.h"
#include "Sg90.h"
unsigned char MiddleFlag; //超声波方向朝前标志位
double MiddleDis,LeftDis,RightDis;
/**
* @brief 舵机初始化时90度,让超声波模块向前
* @param 无
* @retval无
*/
void HC_Init()
{
SgMiddle(); //一开始为90度,往前
Delay1ms(300);
MiddleFlag = 1; //标志位置1
}
/**
* @brief 开启避障模式
* @param 无
* @retval无
*/
void Start_Avoid()
{
if(MiddleFlag != 1) //避免舵机抽搐
{
SgMiddle();
Delay1ms(180);
MiddleFlag = 1;
}
MiddleDis = ultrasonic(); //检测前方距离
if(MiddleDis > 30) //前方没有障碍
{
GoForward(); //前进
}
else if(MiddleDis < 10) //如果距离过小
{
GoBack(); //后退
}
else //前方有障碍
{
//停止
Stop();
SgLeft(); //180度,左扭头
Delay1ms(180);
LeftDis = ultrasonic(); //测左边距离
SgMiddle(); //回到中间
Delay1ms(180);
SgRight(); //0度,右扭头
Delay1ms(180);
RightDis = ultrasonic(); //测右边距离
//若左边距离大于右边距离,说明左边宽敞,向左转
if(LeftDis > RightDis)
{
GoLeft();
Delay1ms(170);
Stop();
}
//若右边距离大于左边距离,说明右边宽敞,向右转
if(RightDis > LeftDis)
{
GoRight();
Delay1ms(170);
Stop();
}
MiddleFlag = 0;
}
}
Uart.c:
串口中断函数中加入新指令,串口收到的指令如果是“Avoid”,则将避障模式的标志位置1,其他判断不变
#include
#include "Motor.h"
#include "Delay.h"
#include "string.h"
#define SIZE 10
unsigned char rec[SIZE];
extern unsigned char Avoid_Flag;
/**
* @brief 串口初始化
* @param 无
* @retval无
*/
void UartInit(void) //9600bps@11.0592MHz
{
PCON &= 0x7F; //波特率不倍速
SCON = 0x50; //8位数据,可变波特率
TMOD &= 0x0F; //清除定时器1模式位
TMOD |= 0x20; //设定定时器1为8位自动重装方式
TL1 = 0xFD; //设定定时初值
TH1 = 0xFD; //设定定时器重装值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
ES = 1; //开启串口中断
EA = 1; //开启总中断
}
//串口中断处理
void Uart_Rountine() interrupt 4
{
static unsigned int i = 0;
unsigned char temp;
if(RI)
{
RI = 0;
temp = SBUF;
if(temp == 'F' || temp == 'B' || temp == 'L' || temp == 'R' || temp == 'S' || temp == 'A')
{
i = 0;
}
rec[i++] = temp;
//前进
if(rec[0] == 'F' && rec[1] == 'o')
{
GoForward();
Delay1ms(200);
i = 0;
memset(rec,'\0',SIZE);
}
//后退
if(rec[0] == 'B' && rec[1] == 'a')
{
GoBack();
Delay1ms(200);
i = 0;
memset(rec,'\0',SIZE);
}
//左转
if(rec[0] == 'L' && rec[1] == 'e')
{
GoLeft();
Delay1ms(100);
i = 0;
memset(rec,'\0',SIZE);
}
//右转
if(rec[0] == 'R' && rec[1] == 'i')
{
GoRight();
Delay1ms(100);
i = 0;
memset(rec,'\0',SIZE);
}
//停止
if(rec[0] == 'S' && rec[1] == 't')
{
Stop();
Avoid_Flag = 0;
i = 0;
memset(rec,'\0',SIZE);
}
//避障模式
if(rec[0] == 'A' && rec[1] == 'v')
{
Avoid_Flag = 1;
i = 0;
memset(rec,'\0',SIZE);
}
//松手停止
if(rec[0] == '\0' && rec[1] == '\0')
{
Stop();
}
if(i == SIZE){i = 0;}
}
}
main.c:
主函数中要先调用定时器0、定时器2、串口的初始化函数,调用函数让舵机旋转,让超声波模块往前,然后while循环内就不断判断标志位是否是1,是1则说明串口那边下指令了,就调用函数让小车进入避障模式
#include
#include "Motor.h"
#include "Delay.h"
#include "Sg90.h"
#include "Avoid.h"
#include "HC-SR04.h"
#include "Uart.h"
/*1.先将避障的方法模块化
2.将超声波改用定时器2,定时器1留给串口
3.增加串口源文件和头文件
*/
unsigned char Avoid_Flag;
unsigned char temp;
void main()
{
Timer0Init();
Timer2Init();
UartInit();
HC_Init(); //超声波模块往前
while(1)
{
//开始避障
if(Avoid_Flag == 1)
{
Start_Avoid();
}
}
}