资源描述
安阳工学院
《单片机基础》课程大作业
《简易红外遥控小车设计》
院系:计算机科学与信息工程学院
专业班级:
姓名:
学号:
成绩(教师填写)___________
20 年 月 日
一、课题名称:
《简易红外遥控小车设计》
二、方法步骤:
1.总体设计
主要设计思想:
本设计利用通用红外遥控器控制小车后轮两个电机的动作来实现小车走、停、转弯等功能。并通过软件控制小车方向和PWM调速小车的转速。具体思想如下:通过外部中断1接收红外信息,并通过软件解码,根据接收信息的不同通过PWM和控制函数做出响应,并且在二极管上面反映出来,所以说二极管充当车灯和档位指示灯的作用,且每次接收信号,蜂鸣器鸣叫用来显示有信号的传入。
主要设计任务:
红外遥控小车的设计主要分两大步,第一是硬件实现的设计,第二是单片机软件实现的设计。
(1)其中硬件又分几块:51单片机最小系统板,小型直流电机(3~9V)驱动电路模块,红外接收模块(已集成在最小系统板),蜂鸣器和二极管显示模块,车体。
(2)软件比较简单,但也分了几块:外部中断红外接收解码模块,PWM电机调速模块,主程序。
2.设计任务与要求
(1)主要完成的性能指标
本小车设计完成后能够实现如下功能:前进、后退、左前传(以做轮胎为轴转弯)、右前转、左圆转(以车体为轴进行转弯)、右圆转、左倒转、右倒转、紧急暂停、123级加减速。
(2)器件选择
本设计主要用到以下材料:51单片机一个、通用遥控器一个、红外接收头一个、5号电池7节、车体(双电机+万向轮)一套、蜂鸣器一个、杜邦线若干、二极管9个、L9110S电机驱动芯片2个、其他电阻电容若干
(3)单片机选择
本设计用到宏晶公司的STC——125A32Ad单片机
(4)说明总体框图(可选)
51最小系统
电机驱动
二极管显示
5V直流电机
(5)画出总线路图 (硬件)
51单片机最小系统如右:
红外电路图如下:
L9110S电机驱动电路如下:
L9110S电气特性如下:
完成后的驱动:
实现后的实物图如下:
(6)流程图及程序清单
//*******************************************************************************
//***************简易红外小车 完全调试程序
//***************版本V0.2
//***************2012年5月13日10:49:26
//***************修改优化时间2012年5月14日0:02:21
//***************再次修改时间2012年5月18日20:49:28
//***************Made by **************
#include<reg52.h>
#include"intrins.h"
#define uint unsigned int
#define uchar unsigned char
sbit M11=P1^0; // 电机1接口
sbit M12=P1^1;
sbit M21=P1^2; // 电机2接口
sbit M22=P1^3;
sbit LED0=P0^0; // 左前灯
sbit LED1=P0^1; // 档1灯
sbit LED2=P0^2; // 档2灯
sbit LED3=P0^3; // 档3灯
sbit LED4=P0^4; //紧急灯
sbit LED5=P0^5; //右前灯
sbit LED6=P0^6; //左后灯
sbit LED7=P0^7; //右后灯
sbit F=P1^4;//蜂鸣器接口
uchar TEMP1=0;//全局变量,用于存放红外返回值 -用于PWM占空比的控制
uchar TEMP2=10; // 用于方向的控制
sbit Int0 = P3^3; // 红外接收采用外部中断1
uchar databus[7];//用于红外接收存放数据
//************************************************************
//延时函数
void delay1(uint xms)//delay 0.1ms
{
uint i,j;
for(i=xms;i>0;i--)
for(j=13;j>0;j--);
}
//************************************************************
//********************接受解码函数
uchar Rec()
{
uchar temp=0; //函数内部临时变量,用于返回函数值
uint i=0; // 用于存放数据的临时变量
uint j=0;
uint m=0; // 局部计数临时变量
uint n=0; // 局部计数临时变量
uint k=0; // 局部计数临时变量
EX1=0; // 关外部中断1 ,以防再次外部1中断的介入
while(!Int0) //用于计时前9Ms低电平的引导码
{
delay1(1);
m++; // 计数引导码的长度
}
if(m<=60) //50,可变,大概数,m应该在90左右,如果引导码时间太小(如<50),就表示
//此次接收有误,返回0
return 0; //
while(Int0) //用于计时4.5ms高电平的引导码
{
delay1(1);
n++; //计时高电平
}
if(n<=30) // 20大概值,应该在45左右,如果太小或太大,都有问题
return 0;
//当上面的两步都完成时,表示9ms低电平,4.5ms高电平的引导码验证完毕
//可进行下步接收数据工作。后面有32位高低电平组成的编码分为:系统码1,系统码2,数据码和数据反码
//其中前16位,为用户识别码(系统码1和2)用于区别不同的电器,因为使用的通用遥控器和接收器所以
//不用关心前16位。
M11=M12=M21=M22=0; //进入中断,停止电机,防止电机颤抖
for(i=0;i<4;i++) // 4组接收
for(j=0;j<8;j++) // 每组8个高低信号
{
//数据0由0.56ms低+0.56ms高组成 即 1:1
//数据1由0.56ms低+1.655ms高组成 1:3
while(!Int0) //过滤数据的低位 0.56ms低电平
{
delay1(1);
}
while(Int0) // 进入高电平计时
{
delay1(1);
k++; // k计时每次的高电平
}
databus[i]=databus[i]>>1; // 数据接收数组首先默认接收为0信号,即databus【i】第7位移入0
if(k>=10) // 而后,判断刚才接收到的数据是否为1,因为1的高点平持续1.655ms
//低电平持续0.56ms,所以只要k大于10,就能确定为1
{
databus[i]=databus[i]|0x80; // 若为1,把第8位置1
}
k=0;//把k的值重新置零
};
if(databus[2]!=~databus[3]) // 2和3组数据为反码关系。所以判断它们是否相反,来确定接收数据
//是否正确
return 0;
temp=databus[2]; // 返回赋值
return temp; //
}
//****************************************************
//**********红外接受中断服务函数,+接受编码TEMP1,TEMP2
void int0() interrupt 2
{
uchar temp; // 临时存放红外接收函数返回值
uint i=0; // 计数临时变量
LED4=1; //(因紧急灯是闪烁的每次中断时结果不一样,为保证效果)先灭紧急指示灯
temp=Rec(); // 红外函数返回赋值
switch (temp) // 对返回的数据进行编码,方便后面的操作
{
case 0x0d:
{
TEMP1=0; //TEMP1,编码用作,PWM参数,全局变量,
LED1=LED2=LED3=1; //对应的指示灯状态
break;
}
case 0x0c:
{
TEMP1=1;
LED1=0;
LED2=LED3=1;
break;
}
case 0x18:
{
TEMP1=2;
LED1=LED3=1; //2档
LED2=0;
break;
}
case 0x5e:
{
TEMP1=3;//TEMP1用于控制PWM占空比
LED3=0;
LED1=LED2=1;
break;
}
case 0x40:
{
TEMP2=0;//紧急状态(暂停)。TEMP2用于控制电机,暂停,前进,左右转,
break;
}
case 0x46:
{
TEMP2=1;//前进
LED0=LED5=0; //指示灯设置
LED6=LED7=1;
break;
}
case 0x44:
{
TEMP2=2;//左前转
LED0=0;
LED5=1;
LED6=LED7=1;
break;
}
case 0x43 :
{
TEMP2=3;//右前转
LED5=0;
LED0=1;
LED6=LED7=1;
break;
}
case 0x15:
{
TEMP2=4; //倒车状态
LED6=LED7=0;//67为倒车指示灯
LED0=LED5=1;
break;
}
case 0x07:
{
TEMP2=5;//左后转
LED6=0;
LED7=LED0=LED5=1;
break;
}
case 0x09:
{
TEMP2=6;//右后转
LED7=0;
LED6=LED0=LED5=1;
break;
}
case 0x45:
{
TEMP2=7; //左园转
LED0=LED7=0;
LED5=LED6=1;
break;
}
case 0x47:
{
TEMP2=8;//右园转
LED5=LED6=0;
LED0=LED7=1;
break;
}
}
//每次接受红外,蜂鸣器蜂鸣一次
F=1;
delay1(300);
F=0;
EA=1; // 开总中断
EX1=1; // 开外1中断
IT1=1; // 下降沿触发
}
//*****************************************
//**********电机驱动函数
void PWM_RUN()
{
uint m=0; // 临时计数变量
uchar n=0; //
uint i=0; //
m=TEMP1*100; //m有0,1,2,3状态,PWM每小时间片为3*100,所以m*100
n=TEMP2; //TEMP1用于控制转速,TEMP2用于控制前后左右
//对n(TEMP2)进行解码,设置不同的电机工作方式
//注:暂定M*1=1,M*2=0正传,M*1=0,M*2=1倒转,M*1=M*2=0,停止
if(n==0) //紧急状态,
{
M11=M12=M21=M22=0;
LED4=~LED4; //设置紧急灯动作
delay1(1000);
}
if(n==1) //m1和m2都前转,前进
{
M11=1;
M12=0;
M21=1;
M22=0;
}
if(n==2) //m1停止,m2前转,实现左前转弯
{
M11=0;
M12=0;
M21=1;
M22=0;
}
if(n==3) // m1前转,m2停止 ,实现右前转
{
M11=1;
M12=0;
M21=0;
M22=0;
}
if(n==4)//m1m2倒转,实现倒车
{
M11=0;
M12=1;
M21=0;
M22=1;
}
if(n==5) //m1停止,m2倒转,实现左后转
{
M11=0;
M12=0;
M21=0;
M22=1;
}
if(n==6)// m1倒转,m2停止,实现右后转
{
M11=0;
M12=1;
M21=0;
M22=0;
}
if(n==7)//m1倒传 ,m2前转,实现左方向,原地打转
{
M11=0;
M12=1;
M21=1;
M22=0;
}
if(n==8)//m1前转,m2倒转,实现右方向,原地打转
{
M11=1;
M12=0;
M21=0;
M22=1;
}
/* //PWM实现部分
while(m--)
_nop_(); // 电机动作
while(i<300-m) // 电机歇菜
{
M11=M12=0;
M21=M22=0;
_nop_();
i++;
}
while(1);
*/
}
//***************************THE main()
//*******
void main()
{ EA=1; // 开总中断
EX1=1; // 开外1中断
IT1=1; // 下降沿触发
P1=0; // P1口为电机控制口,初始化为0,即,开机时电机是停止的
while(1)
PWM_RUN();
}
三、分析讨论
本设计的设计过程遇到很多问题,例如电机驱动模块的设计,红外接收硬件模块,红外接收软件解码模块,电机调速模块,不过最终这些问题都经过查阅资料,询问老师一一解决。小车虽已实现基本功能,但仍有很多地方存在缺陷,有待改进。例如,红外接收易受影响,可以考虑改进成无线收发模块,电机驱动提供动力较小,可以改进成L298N大功率驱动模块,车体改成四驱这样更稳定,增加循迹,避障,超声波测距模块,还可以与上位机结实现上微机控制小车,小车反馈信息到上位机、、、、、等功能有待改进
通过本次设计,收获良多,首先书本和实际是差的很远的,其次是想法和成品距离也不近,还有一般和完美是要付出汗水。呵呵,来电实际的,这次设计我学到了主要是硬件部分,比如上拉电阻增强驱动能力的应用,电容滤波的应用,51最小系统的连接,红外接收电路的连接,电驱动芯片L9110S的应用连接。软件部分有:红外解码子程序的实现,PWM调速程序的实现,外部中断的应用等。
四、参考资料
1————L9110sDataSheet
2————华强公司红外接收头DataSheet
QQ交流:1044675456
展开阅读全文