标题:
51单片机追踪机器人(小车)程序
[打印本页]
作者:
lolita1888
时间:
2019-3-24 09:59
标题:
51单片机追踪机器人(小车)程序
之前做的时候苟了一周编出来的程序
QX-A51小车跟随前方障碍物运动
s2控制小车前进后退左转右转
s3跟踪
s4光敏
功能蛮全的,跟踪不是特别灵敏,跟小车硬件有关,可以再调整。
单片机源程序如下:
#include <reg52.h>
#include <intrins.h>
#include <C:\Users\Administrator\Desktop\QXA51.h>
unsigned char pwm_left_val =180;//左电机占空比值 取值范围0-170,0最快
unsigned char pwm_right_val = 175;//右电机占空比值取值范围0-170 ,0最快
unsigned char pwm_t;//周期
#define MAIN_Fosc 11059200UL //宏定义主时钟HZ
#define PCF8591_ADDR 0x90 //PCF8591地址
#define DACOUT_EN 0x40 //DAC输出使能
typedef unsigned char INT8U;
typedef unsigned char uchar;
typedef unsigned int INT16U;
typedef unsigned int uint;
sbit SDA = P2^0; //I2C串行数据
sbit SCL = P2^1; //I2C串行时钟
sbit we = P2^7; //位定义数码管位选锁存器接口
sbit du = P2^6; //位定义数码管位选锁存器接口
sbit LED0 = P1^0;
sbit LED1 = P1^1;
sbit LED2 = P1^2;
sbit LED3 = P1^3;
sbit LED4 = P1^4;
sbit LED5 = P1^5;
sbit LED6 = P1^6;
sbit LED7 = P1^7;//led流水灯
uchar code leddata[]={
0x3F, //"0"
0x06, //"1"
0x5B, //"2"
0x4F, //"3"
0x66, //"4"
0x6D, //"5"
0x7D, //"6"
0x07, //"7"
0x7F, //"8"
0x6F, //"9"
0x00, //熄灭
0x00 //自定义
}; //数码管段选表
uchar AD_Value; //存储AD转换回的数字量
uint i=0,a=0,b=0,c=0;
void Delay_Ms(INT16U ms)
{
INT16U i;
do{
i = MAIN_Fosc / 96000;
while(--i); //96T per loop
}while(--ms);
}
void Delay5us()
{
#if MAIN_Fosc == 11059200
_nop_();
#elif MAIN_Fosc == 12000000
_nop_();
#elif MAIN_Fosc == 22118400
_nop_(); _nop_(); _nop_();
#endif
}
/*====================================
函数:I2C_init()
描述:I2C总线初始化
====================================*/
void I2C_init()
{
SDA = 1; //数据总线高
_nop_();
SCL = 1; //时钟总线高
_nop_();
}
/*====================================
函数:I2C_Start()
描述:I2C起始信号
====================================*/
void I2C_Start()
{
SCL = 1;
_nop_();
SDA = 1;
Delay5us();
SDA = 0;
Delay5us();
}
/*====================================
函数:I2C_Stop()
描述:I2C停止信号
====================================*/
void I2C_Stop()
{
SDA = 0;
_nop_();
SCL = 1;
Delay5us();
SDA = 1;
Delay5us();
}
/*====================================
函数:Master_ACK(bit i)
参数:i 为0时发送非应答 为1时发送应答
描述:I2C主机发送应答
====================================*/
void Master_ACK(bit i)
{
SCL = 0; // 拉低时钟总线允许SDA数据总线上的数据变化
_nop_(); // 让总线稳定
if (i) //如果i = 1 那么拉低数据总线 表示主机应答
{
SDA = 0;
}
else
{
SDA = 1; //发送非应答
}
_nop_();//让总线稳定
SCL = 1;//拉高时钟总线 让从机从SDA线上读走 主机的应答信号
_nop_();
SCL = 0;//拉低时钟总线, 占用总线继续通信
_nop_();
SDA = 1;//释放SDA数据总线。
_nop_();
}
/*====================================
函数:Test_ACK()
返回:0为非应答 1为应答
描述:I2C检测从机应答
====================================*/
bit Test_ACK() // 检测从机应答
{
SCL = 1;//时钟总线为高电平期间可以读取从机应答信号
Delay5us();
if (SDA)
{
SCL = 0;
I2C_Stop();
return(0);
}
else
{
SCL = 0;
return(1);
}
}
/*====================================
函数:I2C_send_byte(uchar byte)
参数:byte 要发送的字节
描述:I2C发送一个字节
====================================*/
void I2C_send_byte(uchar byte)
{
uchar i;
for(i = 0 ; i < 8 ; i++)
{
SCL = 0;
_nop_();
if (byte & 0x80) //
{
SDA = 1;
_nop_();
}
else
{
SDA = 0;
_nop_();
}
SCL = 1;
_nop_();
byte <<= 1;
}
SCL = 0;
_nop_();
SDA = 1;
_nop_();
}
/*====================================
函数:I2C_read_byte()
返回:读取的字节
描述:I2C读一个字节
====================================*/
uchar I2C_read_byte()
{
uchar i, dat;
SCL = 0 ;
_nop_();
SDA = 1;
_nop_();
for(i = 0 ; i < 8 ; i++)
{
SCL = 1;
_nop_();
dat <<= 1;
if (SDA)
{
dat |= 0x01;
}
_nop_();
SCL = 0;
_nop_();
}
return(dat);
}
/*DAC输出*/
bit DAC_OUT(uchar DAT)
{
I2C_Start();
I2C_send_byte(PCF8591_ADDR+0);
if (!Test_ACK())
{
return(0);
}
I2C_send_byte(DACOUT_EN); //DA输出使能
if (!Test_ACK())
{
return(0);
}
I2C_send_byte(DAT);
if (!Test_ACK())
{
return(0);
}
I2C_Stop();
return(1);
}
/*读AD数据*/
bit ADC_Read(uchar CON)
{
I2C_Start();
I2C_send_byte(PCF8591_ADDR+0);
if (!Test_ACK())
{
return(0);
}
I2C_send_byte(CON);
Master_ACK(0);
I2C_Start();
I2C_send_byte(PCF8591_ADDR+1);
if (!Test_ACK())
{
return(0);
}
AD_Value = I2C_read_byte();
Master_ACK(0);
I2C_Stop();
return(1);
}
/*小车前进*/
void forward()
{
left_motor_en; //左电机使能
right_motor_en;//右电机使能
left_motor_go; //左电机前进
right_motor_go; //右电机前进
}
/*小车后退*/
void backward()
{
left_motor_en; //左电机使能
right_motor_en;//右电机使能
left_motor_back; //左电机后退
right_motor_back; //右电机后退
}
/*小车左转*/
void left()
{
left_motor_stops; //左电机停止
right_motor_en;//右电机使能
right_motor_go; //右电机前进
}
/*小车右转*/
void right()
{
right_motor_stops;//右电机停止
left_motor_en; //左电机使能
left_motor_go; //左电机前进
}
/*小车停止*/
void stop()
{
right_motor_stops;//右电机停止
left_motor_stops; //左电机停止
}
void timer0() interrupt 1
{
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;
}
void main()
{
unsigned char j;
for(;;)
{
while(1)
{
if(key_s2 == 0)//判断S2是否按下
{
Delay_Ms(5);//软件消抖
if(key_s2 == 0)
{
while(!key_s2);//松手检测
beep = 0;
Delay_Ms(1000);
beep = 1;
TMOD |= 0x02;//8位自动重装模块
TH0 = 220;
TL0 = 220;//11.0592M晶振下占空比最大比值是256,输出100HZ
TR0 = 1;//启动定时器0
ET0 = 1;//允许定时器0中断
EA = 1;
forward();//小车前进
Delay_Ms(1000);//毫秒级延时
stop();//小车停止
Delay_Ms(1000);//毫秒级延时
backward();//小车后退
beep = 0;//蜂鸣器鸣叫
Delay_Ms(1000);//毫秒级延时
stop();//小车停止
beep = 1;//蜂鸣器停止鸣叫
Delay_Ms(1000);//毫秒级延时
left(); // 小车左转
beep = 0;//蜂鸣器鸣叫
Delay_Ms(1000);//毫秒级延时
stop();//小车停止
beep = 1;//蜂鸣器停止鸣叫
Delay_Ms(1000);//毫秒级延时
right();// 小车右转延时
beep = 0;//蜂鸣器鸣叫
Delay_Ms(1000);//毫秒级延时
stop();//小车停止
beep=1;//蜂鸣器停止鸣叫
Delay_Ms(1000);//毫秒级延时
}
}
if(key_s3 == 0)//判断S3是否按下
{
Delay_Ms(5);//软件消抖
if(key_s3 == 0)
{
while(!key_s3);//松手检测
beep = 0;//蜂鸣器鸣叫
Delay_Ms(1000);//毫秒级延时
beep = 1;//蜂鸣器停止鸣叫
TMOD |= 0x02;//8位自动重装模块
TH0 = 220;
TL0 = 220;//11.0592M晶振下占空比最大比值是256,输出100HZ
TR0 = 1;//启动定时器0
ET0 = 1;//允许定时器0中断
EA = 1;
I2C_init();
while(1)
{
if (ADC_Read(0x00))
if (DAC_OUT(AD_Value))
if (AD_Value > 150) {stop(); }
else {forward(); }
Delay_Ms(5);
}
}
}
if(key_s4 == 0)// 实时检测S3按键是否被按下
{
Delay_Ms(5);//软件消抖
if(key_s4 == 0)//再检测S3是否被按下
{
while(!key_s4);//松手检测
beep = 0; //使能有源蜂鸣器
Delay_Ms(1000);//200毫秒延时
beep = 1; //关闭有源蜂鸣器
TMOD |= 0x02;//8位自动重装模块
TH0 = 220;
TL0 = 220;//11.0592M晶振下占空比最大比值是256,输出100HZ
TR0 = 1;//启动定时器0
ET0 = 1;//允许定时器0中断
EA = 1;//总中断允许
while(1)
{
we = 1;//打开位选
P0 = 0xfe;//,注意数码管的排序,P0.0对应连接的是左边第一位数码管
we = 0; //关闭位选
du = 1; //打开段选
P0 = leddata[b];
du = 0; //关闭段选
Delay_Ms(1);
we = 1;//打开位选
P0 = 0xfd;//,注意数码管的排序,P0.0对应连接的是左边第一位数码管
we = 0; //关闭位选
du = 1; //打开段选
P0 = leddata[i];
du = 0; //关闭段选
Delay_Ms(1);
if(left_led2 == 1 && right_led2 == 1)//为0 识别障碍物 为1没有识别到障碍物
{ stop();
}
if(left_led2 == 0 && right_led2 == 0)//左右识别到障碍物,前进跟随
{
forward();
for(c=0;c<=27000;c++)
{
if(c==27000)
{ j++;
a++;}
}
}
if(left_led2 == 1 && right_led2 == 0)//小车右侧识别到障碍物,右转跟随
{
right();
for(c=0;c<=27000;c++)
{
if(c==27000)
{ j++;
a++;}
}
}
if(left_led2 == 0 && right_led2 == 1)//小车左侧识别到障碍物,左转跟随
{
left();
for(c=0;c<=27000;c++)
{
if(c==27000)
{ j++;
a++;}
}
}
if(j==10) //当数值为10时,清零
{
j=0;
b++;
}
if(b==9)
{ b=0;}
if(a==90)
{
a=0;
j=0;
b=0;
}
}
}
}
}
break;
}
}
复制代码
所有资料51hei提供下载:
程序.rar
(35.83 KB, 下载次数: 16)
2019-3-24 09:58 上传
点击文件名下载附件
下载积分: 黑币 -5
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1