目录
一、前言
先给大家看下效果吧
二、硬件
(一)、红外避障模块
(其他配件连接可以观看我的《蓝牙小车喔》)
(有一个接收端口我用黑胶带绑起来了,防止它被干扰)
先简单介绍些避障模块吧:
OUT口为信号输入输出口,当检测到前方有障碍物时,信号指示灯亮起并且返回低电平,若无障碍物时,信号指示灯不亮返回高电平。
由此我们可以根据返回值是高电平还是低电平来判断前方是否有障碍物。
同时我们可以通过调节电位器来调节红外模块的判断距离。
左边模块由P20控制,右边的模块由P21控制
三、软件
废话不多说直接上代码:
觉得文件多的可以在本末尾下载全部代码
main.c
#include <REGX52.H>
#include "UART.h"
#include "Timer0.h"
#include "Nixie.h"
#include "Delay.h"
sbit IN1 = P1^0; // 左上
sbit IN2 = P1^1; // 左下
sbit IN3 = P1^2; // 右上
sbit IN4 = P1^3; // 右上
sbit ENA = P2^6; //使能A
sbit ENB = P2^7; //使能B
sbit out0 = P2^0; // 右边避障,有障碍物就亮,输出0
sbit out1 = P2^1; // 左边避障,有障碍物就亮,输出0
unsigned char PWM; //PWM波
unsigned char date;//输入缓冲区
static unsigned char speed = 100; //设置速度初始值
void stop() // 停
{
IN1=0;
IN2=0;
IN3=0;
IN4=0;
}
void forward() // 向前
{
IN1=1;
IN2=0;
IN3=1;
IN4=0;
}
void back() // 向后
{
IN1=0;
IN2=1;
IN3=0;
IN4=1;
}
void left() // 向左,只有左轮动
{
IN1=1;
IN2=0;
IN3=1;
IN4=1;
}
void avoid_left()//向左,左右伦同时转动
{
IN1=1;
IN2=0;
IN3=0;
IN4=1;
}
void right() // 向右,只有右轮动
{
IN1=1;
IN2=1;
IN3=1;
IN4=0;
}
void avoid_right()//向左,左右伦同时转动
{
IN1=0;
IN2=1;
IN3=1;
IN4=0;
}
void increase(void)//加速
{
speed += 5; // 每次增加5
if(speed >= 100) // 上限是100
{
speed = 100;
}
}
void reduce(void)//减速
{
speed -= 5; // 每次减少5
if(speed <= 0) // 下限是0
{
speed = 0;
}
}
void avoid(void)//避障模式
{
if(out0 == 0) // 右边有障碍物,左转
{
avoid_left();
}
if(out1 == 0) // 左边有障碍物,右转
{
avoid_right();
}
if(out0 == 1 && out1 == 1) // 没有障碍物,前进
{
forward();
}
if(out0 == 0 && out1 == 0) // 有障碍物,停止
{
stop();
}
}
//串口中断
void Time_Int () interrupt 4
{
if(RI == 1) // RI为1时软件置0
{
RI = 0; // 清除接受标志
date = SBUF; // 接收数据缓存在date中
switch (date)
{
case ('1'):
{
forward();
break;
}
case ('2'):
{
back();
break;
}
case ('3'):
{
left();
break;
}
case ('4'):
{
right();
break;
}
case ('0'):
{
stop();
break;
}
case ('5'):
{
increase();
break;
}
case ('6'):
{
reduce();
break;
}
}
}
}
//定时器0
void time_control() interrupt 1
{
TL0 = 0x66; //设置定时初值
TH0 = 0xFC; //设置定时初值
PWM++;
if (PWM == 100)
{
PWM = 0;
}
if(PWM <= speed)//大于PWM波则打开使能
{
ENA = 1;
ENB = 1;
}
if(PWM > speed)//小于PWM波则关闭使能
{
ENA = 0;
ENB = 0;
}
}
void main ()
{
UsartConfiguration(); // 串口初始化
Timer0Init();//定时器0初始化
while(1)
{
//在数码管可以看到当前的速度是多少
Nixie(1, speed/100);
Delay(5);
Nixie(2, (speed/10)%10);
Delay(5);
Nixie(3, speed%10);
Delay(5);
//启动避障模式,将此模式存放在主函数当中
if(date == '7')
{
avoid();
}
}
}
UART.h(串口)
#ifndef __UART_H__
#define __UART_H__
void UsartConfiguration(void);
void UART_SendByte(unsigned char byte);
#endif
UART.c
#include <REGX52.H>
/**
* @brief 串口初始化,9600bps@11.0592MHz
* @param 无
* @retval 无
*/
void UsartConfiguration(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; //开启总中断
}
/**
* @brief 串口发送一个字节数据
* @param byte 是接收的数据
* @retval 无
*/
void UART_SendByte(unsigned char byte)
{
SBUF = byte;
while (TI == 0);
TI = 0;
}
Timer0.h(定时器0)
#ifndef __TIMER0_H__
#define __TIMER0_H__
void Timer0Init(void);
#endif
Timer0.c
#include <REGX52.H>
/**
* @brief 定时器0,1毫秒@11.0592MHz
* @param 无
* @retval 无
*/
void Timer0Init(void) //1毫秒@11.0592MHz
{
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0x66; //设置定时初值
TH0 = 0xFC; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //定时器开关
EA = 1; //总开关
}
/*模板
void time_control() interrupt 1
{
static unsigned int counst;//局部变量,静态变量,防止每次进入中断,都将counst置为0
TL0 = 0x66; //设置定时初值
TH0 = 0xFC; //设置定时初值
counst++;
if (counst == 1000)
{
counst = 0;
}
}
*/
Nixie.h(数码管)
#ifndef __NIXIE_H__
#define __NIXIE_H__
void Nixie(unsigned char Location,Number);
#endif
Nixie.c
#include <REGX52.H>
#include "Delay.h"
//数码管段码表
unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
/**
* @brief 数码管显示
* @param Location 要显示的位置,范围:1~8
* @param Number 要显示的数字,范围:段码表索引范围
* @retval 无
*/
void Nixie(unsigned char Location,Number)
{
switch(Location) //位码输出
{
case 1:P2_4=1;P2_3=1;P2_2=1;break;
case 2:P2_4=1;P2_3=1;P2_2=0;break;
case 3:P2_4=1;P2_3=0;P2_2=1;break;
case 4:P2_4=1;P2_3=0;P2_2=0;break;
case 5:P2_4=0;P2_3=1;P2_2=1;break;
case 6:P2_4=0;P2_3=1;P2_2=0;break;
case 7:P2_4=0;P2_3=0;P2_2=1;break;
case 8:P2_4=0;P2_3=0;P2_2=0;break;
}
P0=NixieTable[Number]; //段码输出
Delay(1); //显示一段时间
P0=0x00; //段码清0,消影
}
Delay.h(延时)
#ifndef __DELAY_H__
#define __DELAY_H__
void Delay(unsigned int xms);
#endif
Delay.c
/**
* @brief 毫秒延时
* @param xms输入的毫秒
* @retval 无
*/
void Delay(unsigned int xms) //@11.0592MHz
{
unsigned char i, j;
while(xms--)
{
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
}
四、手机端配置
蓝牙下载可以参照我的《蓝牙小车》文章
其中设置如下图(在开关中配置)
五、总结
有待改进的:
可以把可以把避障函数加入到中断中来,现在放在主函数
要调节好红外模块的角度,方便循迹,同时循迹的速度不可以太快,不然小车来不及反应
代码工程下载
链接:https://pan.baidu.com/s/1oyiUdTF0U3VoG3iPhp_8ZA
提取码:2233
--------------------------------------------------------------------------------------------------------------------------
欢迎大家观看我的文章,希望对你有帮助。
作者大一萌新,有什么写的不对的地方欢迎在评论区指正。
最后希望能和大家一起加油努力呀!~