/*
* 【编写时间】: 2018
* 【外部晶振】: 11.0592mhz
* 【主控芯片】: STC89C52
* 【编译环境】: Keil μVisio4
* ********************************【接线说明】********************************
以下"A_"表示智能小车底板~~~"B_"表示开发板
*开发板供电线 :A_J5-VCC~~~B_VCC或5V0 A_J6-GND~~~B_GND (一共使用2根杜邦线)
*电机控制线 :A_J10-P1.2至P1.7 对应接到B_P1.2至P1.7 (一共使用6根杜邦线)
*超声波模块反馈线:A_J2-P20~~~B_P20 A_J2-P21~~~B_P21 (一共使用2根杜邦线)
*避障寻迹反馈线:A_J11-P3.2至P3.5 对应接到B_P3.2至P3.5 (一共使用4根杜邦线)
******************************************************************************
* 【程序功能】:QX-A51智能小车寻迹避障二合一(在黑线寻迹的过程中如遇障碍物则自动掉头)
* 【使用说明】:接线无误后,烧写程序打开电源开、按下S2按键后蜂鸣器发出提示音1秒后启动小车
* 【注意事项】:避免小车撞向障碍物或小车轮子堵转。
小车电压不能低于6V.
此程序只做参考,实际运行效果需根据不同实验场地进行不同调试
S2 按下功能:开始程序 就是第一个开关 程序里定义成了s2
s3 按下功能:按下一次,开启循迹 再按一次 关闭循迹
s4 按下功能:让电机速度变慢
s5 按下功能:让电机速度加快
**********************************************************************************/
#include <reg52.h>//51头文件
#include <intrins.h> //包含nop等系统函数
#include <QXA51.h>//QX-A51智能小车配置文件
#include "stdlib.h"
#include "stdio.h"
#include "String.h"
typedef unsigned char uchar;
typedef unsigned int uint;
unsigned char pwm_left_val = 100;//左电机占空比值 取值范围0-170,0最快
unsigned char pwm_right_val = 100;//右电机占空比值取值范围0-170 ,0最快
unsigned char pwm_t;//周期
unsigned char s3=0;//定义一个s3 开关的计数 s3 是功能按键
//按下s3开关 变量就会加1 s3=1时 开启循迹模式
/*=================================================
*函数名称:Read_Busy
*函数功能:判断1602液晶忙,并等待
=================================================*/
void Read_Busy()
{
uchar busy;
LCD1602_DB = 0xff;//复位数据总线
LCD1602_RS = 0; //拉低RS
LCD1602_RW = 1; //拉高RW读
do
{
LCD1602_EN = 1;//使能EN
busy = LCD1602_DB;//读回数据
LCD1602_EN = 0; //拉低使能以便于下一次产生上升沿
}while(busy & 0x80); //判断状态字BIT7位是否为1,为1则表示忙,程序等待
}
/*=================================================
*函数名称:LCD1602_Write_Cmd
*函数功能:写LCD1602命令
*调用:Read_Busy();
*输入:cmd:要写的命令
=================================================*/
void LCD1602_Write_Cmd(uchar cmd)
{
Read_Busy(); //判断忙,忙则等待
LCD1602_RS = 0;
LCD1602_RW = 0; //拉低RS、RW操作时序情况1602课件下中文使用说明基本操作时序章节
LCD1602_DB = cmd;//写入命令
LCD1602_EN = 1; //拉高使能端 数据被传输到LCD1602内
LCD1602_EN = 0; //拉低使能以便于下一次产生上升沿
}
/*=================================================
*函数名称:LCD1602_Write_Dat
*函数功能:写LCD1602数据
*调用:Read_Busy();
*输入:dat:需要写入的数据
=================================================*/
void LCD1602_Write_Dat(uchar dat)
{
Read_Busy();
LCD1602_RS = 1;
LCD1602_RW = 0;
LCD1602_DB = dat;
LCD1602_EN = 1;
LCD1602_EN = 0;
}
/*=================================================
*函数名称:LCD1602_Dis_OneChar
*函数功能:在指定位置显示一个字符
*调用:LCD1602_Write_Cmd(); LCD1602_Write_Dat();
*输入:x:要显示的横坐标取值0-40,y:要显示的行坐标取值0-1(0为第一行,1为第二行)
dat:需要显示的数据以ASCLL形式显示
=================================================*/
//void LCD1602_Dis_OneChar(uchar x, uchar y,uchar dat)
//{
// if(y) x |= 0x40;
// x |= 0x80;
// LCD1602_Write_Cmd(x);
// LCD1602_Write_Dat(dat);
//}
/*=================================================
*函数名称:LCD1602_Dis_Str
*函数功能:在指定位置显示字符串
*调用:LCD1602_Write_Cmd(); LCD1602_Write_Dat();
*输入:x:要显示的横坐标取值0-40,y:要显示的行坐标取值0-1(0为第一行,1为第二行)
*str:需要显示的字符串
=================================================*/
void LCD1602_Dis_Str(uchar x, uchar y, uchar *str)
{
if(y) x |= 0x40;
x |= 0x80;
LCD1602_Write_Cmd(x);
while(*str != '\0')
{
LCD1602_Write_Dat(*str++);
}
}
/*=================================================
*函数名称:Init_LCD1602
*函数功能:1602初始化
*调用: LCD1602_Write_Cmd();
=================================================*/
void Init_LCD1602()
{
LCD1602_Write_Cmd(0x38); // 设置16*2显示,5*7点阵,8位数据接口
LCD1602_Write_Cmd(0x0c); //开显示
LCD1602_Write_Cmd(0x06); //读写一字节后地址指针加1
LCD1602_Write_Cmd(0x01); //清除显示
}
void delay(unsigned int z)//毫秒级延时
{
unsigned int x,y;
for(x = z; x > 0; x--)
for(y = 114; y > 0 ; y--);
}
/*
void Delay10us(unsigned char i) //10us延时函数 启动超声波模块时使用
{
unsigned char j;
do{
j = 10;
do{
_nop_();
}while(--j);
}while(--i);
}
*/
/*小车前进*/
void forward()
{
left_motor_go; //左电机前进
right_motor_go; //右电机前进
}
/*小车左转*/
void left_run()
{
left_motor_stops; //左电机停止
right_motor_go; //右电机前进
}
/*小车右转*/
void right_run()
{
right_motor_stops;//右电机停止
left_motor_go; //左电机前进
}
/*PWM控制使能 小车原地左转*/
//void left_rapidly()
//{
// left_motor_back;
// right_motor_go;
//}
/*小车后退*/
void backward()
{
left_motor_back; //左电机后退
right_motor_back; //右电机后退
}
/*小车停止*/
//void stop()
//{
// right_motor_stops;//右电机停止
// left_motor_stops; //左电机停止
//}
/*PWM控制使能 小车高速右转*/
void right_rapidly()
{
left_motor_go;
right_motor_back;
}
/*定时器1中断输出PWM信号*/
//void timer1() interrupt 3
//{
// pwm_t++;//周期计时加
// if(pwm_t == 255)
// pwm_t = EN1 = EN2 = 0;
// if(pwm_left_val == pwm_t)//左电机占空比
// EN1 = 1;
// if(pwm_right_val == pwm_t)//右电机占空比
// EN2 = 1;
//}
/*判断S2是否被按下*/
void keyscan(void)
{
for(;;) //死循环
{
if(key_s2 == 0)// 实时检测S2按键是否被按下
{
delay(5); //软件消抖
if(key_s2 == 0)//再检测S2是否被按下
{
while(!key_s2);//松手检测
beep = 0; //使能有源蜂鸣器
delay(200);//200毫秒延时
beep = 1; //关闭有源蜂鸣器
break; //退出FOR死循环
}
}
}
}
/*判断按键s3 s4 s5是否被按下*/
void keyscan_345(void)
{
if(key_s3 == 0)// 实时检测S3按键是否被按下
{
delay(5); //软件消抖
if(key_s3 == 0)//再检测S2是否被按下
{
while(!key_s3);//松手检测
beep = 0; //使能有源蜂鸣器
delay(200);//200毫秒延时
beep = 1; //关闭有源蜂鸣器
s3++;
if(s3==4)
{
s3=0;
}
}
}
if(key_s4 == 0)// 实时检测S3按键是否被按下
{
delay(5); //软件消抖
if(key_s4 == 0)//再检测S2是否被按下
{
while(!key_s4);//松手检测
beep = 0; //使能有源蜂鸣器
delay(200);//200毫秒延时
beep = 1; //关闭有源蜂鸣器
if(pwm_left_val<170)
{
pwm_left_val=pwm_left_val+10;//这是减 电机速度 变量增大 速度变慢
}
if(pwm_right_val<170)
{
pwm_right_val=pwm_right_val+10;
}
}
}
if(key_s5 == 0)// 实时检测S3按键是否被按下
{
delay(5); //软件消抖
if(key_s5 == 0)//再检测S2是否被按下
{
while(!key_s5);//松手检测
beep = 0; //使能有源蜂鸣器
delay(200);//200毫秒延时
beep = 1; //关闭有源蜂鸣器
if(pwm_left_val>11)
{
pwm_left_val=pwm_left_val-10;//这是减 电机速度 变量增大 速度变慢
}
if(pwm_right_val>11)
{
pwm_right_val=pwm_right_val-10;
}
}
}
}
//寻迹
void tracking()
{
//为0 没有识别到黑线 为1识别到黑线
if(left_led1 == 1 && right_led1 == 1)//左右寻迹探头识别到黑线
{
forward();//前进
}
else
{
if(left_led1 == 1 && right_led1 == 0)//小车右边出线,左转修正
{
left_run();//左转
}
if(left_led1 == 0 && right_led1 == 1)//小车左边出线,右转修正
{
right_run();//右转
}
if(left_led1 == 0 && right_led1 == 0)//左右寻迹探头都没识别到黑线
{
forward();//前进
}
}
}
//避障
void aviod(void)
{
//为0 识别障碍物 为1没有识别到障碍物