安徽财贸职业学院电子信息系
《电子产品装配与调试》项目封面
项目题目 自动往返电动小汽车
班级 电子1001 指导教师 ##
日期 20##-6-13
目录
1、 系统设计... - 1 -
1.1 基本要求... - 1 -
1.2 程序框图... - 2 -
2、单元电路设计... - 3 -
2.1光电检测部分... - 3 -
2.2 STC89C52单片机基本系统... - 3 -
2.3 L298N电动机驱动模块部分... - 5 -
2.4 系统总原理图... - 6 -
2.5 系统PCB板布局... - 7 -
2.6 电源部分... - 7 -
3、软件设计... - 8 -
3.1外部中断0. - 8 -
3.2 外中断1. - 9 -
3.3 定时器中断0. - 10 -
3.4 定时器中断1. - 11 -
3.5 显示电路... - 11 -
3.6 主程序... - 11 -
4、系统测试... - 20 -
5、结论... - 21 -
6、附录... - 22 -
7、参考文献... - 23 -
1、 系统设计
设计并制作了一个自动往返电动小汽车,跑道宽度0.5m,表面贴有白纸,两侧有挡板 ,挡板与地面垂直,其高度不低于20cm。在跑道的B、C、D、E、F、G各点处画有2cm宽的黑线,各段的长度如图1所示。
图1-1 跑道顶视图
1.1 基本要求
(1)车辆从起跑线出发(出发前,车体不得超出起跑线)。在第一个路程C~D区(3~6米)以低速行驶,通过时间不低于10s;第二个路程D~E区(2米)以高速行驶,通过时间不得多于4秒;第三个路程E~F区(3~6米)以低速行驶,通过时间不低于10s。
(2)小车能自动记录、显示行驶时间、行驶距离以及行驶速度,还能记录每段所走的时间,从而判断是否符合课程设计要求。(记录显示装置要求安装在车上)。
(3)说明
a.不允许在跑道内外区域另外设置任何标志或检测装置。
b.车辆(含在车体上附加的任何装置)外围尺寸的限制:长度[35cm,宽度[15cm。
1.2 程序框图
图1-2 程序框图
2、单元电路设计
2.1光电检测部分
我们采用反射式光电检测电路对跑道上的黑线进行检测,并用两个遮光套管套住发光管和接收管以一定的角度紧贴跑道,这样可以消除外界光线的干扰。为了加强可靠性采用槽型光耦检测轮子转动的行程。用LM358电压比较器输出高低电平检测信号。
图2-1 光电检测电路图
2.2 STC89C52单片机基本系统
以89C52为核心,每检测到一个黑带由光电检测部分产生一个的脉冲,使单片机产生一个外部中断1,定义检测黑带数的变量加1,同时车轮每转一圈,霍尔元件输出一个脉冲,是安单片机产生一个外部中断0,定义圈数的变量加1.通过P3.0和P3.1控制L298来控制电机的正转与反转及刹车。当P3.0输出低电平,P3.1输出高电平时,电机正转,相反则电机反转,当P3.0和P3.1都是低电平时,使电动机被短路,提高了刹车效率,基本杜绝了由于制动惯性造成的小车的前冲现象。通过P0口进行两个数码管的位选,P2口进行段码输出,其中一个数码管显示行驶时间,另外一个数码管显示行驶路程。
如图所示:
图2-2 单片机最小系统电路图
2.3 L298N电动机驱动模块部分
该电路采用电动机驱动芯片L298来控制电动机的正转与反转,加以第二路电机电
源保证了电动机启动时有足够的电流。在试验中控制电压为单片机输出的高低电
平直接控制。
具体电路图连接如下:
图2-3 电机驱动电路图
2.4 系统总原理图
图2-4 小车总原理图
2.5 系统PCB板布局
图2-5 PCB板布局
2.6 电源部分
由于小车底板承受重量有限就直接使用4节1.5v的干电池即可。
3、软件设计
单片机控制电路主要由一片STC89C52组成,通过P3口控制小车正转与反转,刹车,加速减速,通过两个四联数码管控制显示时间和里程以及小车行驶的时间。其中P0口进行位选,P2口进行显示段码输出。
该系统采用上电复位加上手动复位联合复位系统进行初始化,单片机通过P3.0,P3.1输出脉冲控制电机正转反转以及刹车,当P3.0,P3.1分别输出01是电动机正转,输出10时电动机反转,输出00时电动机两边短路,小车立即刹车。
3.1外部中断0
车轮美转一次,霍尔元件产生一个脉冲P3.14,通过下降沿触发外部中断0,并且在每进行一次外部中断记录圈数的变量加1.
3.2 外中断1
光电检测每检测到一条黑带就产生一个脉冲输入P3.2口,通过下降沿的方式触发外中断1,每中断一次记录黑带的变量加1,当检测到第五条黑带时,p1.0=1,p1.1=1,小车的电动机由于短路刹车,当检测到第九条黑带时,小车再次刹车同时关掉所有中断 。
3.3 定时器中断0
使用定时器T0产生5ms定时中断,每次执行该中断前要先给定时器0赋初值,定时器中断每执行一次,变量加1。当i=200时,即每当计时1秒时,时间变量t加1,速度等于一秒转的圈数和小车车轮的周长相乘。
3.4 定时器中断1
主要用来产生不同的占空比的波型进行高低速控制,每次执行时,定时器1要赋初值
3.5 显示电路
采用传统的数码管显示。本系统采用7位数码管动态扫描的方式进行显示。前三位数码管显示的数值表示里程,显示的范围为1~999米;后四位数码管的数值表示一次往返过程中所需的总时间,其中前两位表示分,后两位表示秒。往返到起点时显示的数值是一次往返的总时间。P0口作段码数据输出,P2口为扫描输出口。
3.6 主程序
主程序主要用来控制两个四联数码管的显示,通过循环语句不断的调用显示程序,使两个四联数码管按位不断循环亮点,当小车行驶时动态显示时间和路程,小车停止时显示小车行驶过程中的时间和路程。
#include //包含头文件
#define uint unsigned int //宏常量定义
#define uchar unsigned char //宏常量定义
sbit dianji1=P1^0; //P1_0设置为电机控制一
sbit dianji2=P1^1; //P1_1设置为电机控制二
sbit hdjc=P3^2; //P3_2设置为黑带检测位
uchar code duma[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff}; //段编码
uchar code dianduma[]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10}; //带小数点段编码
uchar code wema[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x00,0xff}; //位编码
uchar num,ge,shi,bai,qian; //定义几个字符型变量
uint miao,lc,heidai=0; //定义几个整形变量
long int qs; //定义一个长整形变量用来记录小车所转的圈数
void fenwei(uint); //声明一个分位函数用来把要显示的数分位
void shuma(uchar,uchar) ; //声明一个数码上显示函数用来在数码管上显示数据
void shumadian(uchar,uchar); //声明另一个数码显示函数用来显示带小数点的数据
void miaoxianshi(uint); //声明一个显示时间的函数
void lcxs(uint); //声明一个显示路程的函数
void djkz(); //声明一个电机控制函数
void delay(uchar); //声明一个延时函数
void delay10s(); //声明另一个延时函数用来延时十秒钟
/*————————————————主函数———————————————————*/
void main()
{
EA=1; //打开总中断
ET0=1; //打开定时器中断0
EX0=1; //打开外部中断1
IT0=1; //外部中断0设置为跳变沿触发方式
EX1=1; //打开外部中断1
IT1=1; //外部中断1设置为跳变沿触发方式
TMOD=0x01; //设置定时器0为方式1
TH0=(65536-500)/256; //定时器0高八位装初值
TL0=(65536-500)%256; //定时器0低八位装初值
TR0=1; //打开定时器0
while(1) //进入主循环
{
djkz(); //进入电机控制函数
}
}/*————————————————显示分位———————————————————*/
//函数功能: 把需要在数码管上显示的数据分位,
// 即把数据的个、十、百、千位分别分
// 离出来
//函数入口参数:整形x,储存需要分位的数据
//函数返回值: 无
void fenwei(uint x)
{
ge=x%10;
shi=(x%100)/10;
bai=(x%1000)/100;
qian=x/1000;
}
/*————————————————数码显示———————————————————*/
//函数功能: 将需要显示的数据显示在数码管上
//函数入口参数:字符型x,储存显示数据
// 字符型y,储存要显示的位置
//函数返回值: 无
void shuma(uchar x,uchar y)
{
P2=wema[8];
P0=duma[x];
P2=wema[y];
delay(5);
}
/*————————————————带小数点数码显示———————————————————*/
//函数功能: 将需要显示的数据显示在数码管上
//函数入口参数:字符型x,储存显示数据
// 字符型y,储存要显示的位置
//函数返回值: 无
void shumadian(uchar x,uchar y)
{
P2=wema[8];
P0=dianduma[x];
P2=wema[y];
delay(5);
}
/*————————————————时间显示———————————————————*/
//函数功能: 将定时器0输出的时间显示在数码管上
//函数入口参数:整型x,要显示的时间
//函数返回值: 无
void miaoxianshi(uint x)
{
fenwei(x);
shuma(ge,3);
shuma(shi,2);
shumadian(bai,1);
shuma(qian,0);
}
/*————————————————路程显示———————————————————*/
//函数功能: 将外部中断1输出的路程显示在数码
// 管上
//函数入口参数:整形z:要显示的路程
//函数返回值: 无
void lcxs(uint z)
{
fenwei(z);
shuma(ge,7);
shuma(shi,6);
shumadian(bai,5);
shuma(qian,4);
}
/*————————————————电机控制———————————————————*/
//函数功能: 控制电机运转
//函数入口参数:无
//函数返回值: 无
void djkz()
{
uchar n=20,m=60;
switch(heidai)
{
case 0:
case 1:
case 2:
dianji1=1;
dianji2=0;
miaoxianshi(miao);
lcxs(lc);
break;
case 3:
while(m--) {
dianji1=0;
dianji2=1;
delay(70);
dianji1=0;
dianji2=0;
delay(30);
miaoxianshi(miao);
lcxs(lc);
}
while(heidai==3)
{
dianji1=1;
dianji2=0;
delay(13);
dianji1=0;
dianji2=0;
delay(1);
miaoxianshi(miao);
lcxs(lc);
}
break;
case 4:
while(heidai==4)
{
dianji1=1;
dianji2=0;
delay(25);
dianji1=0;
dianji2=0;
delay(1);
miaoxianshi(miao);
lcxs(lc);
}
break;
case 5:
while(n--)
{
dianji1=0;
dianji2=1;
delay(50);
dianji1=0;
dianji2=0;
delay(50);
miaoxianshi(miao);
lcxs(lc);
}
dianji1=1;
dianji2=1;
delay10s();
while(heidai==5)
{
dianji1=0;
dianji2=1;
}
break;
case 6:
dianji1=0;
dianji2=1;
miaoxianshi(miao);
lcxs(lc);
break;
case 7:
while(n--)
{
dianji1=1;
dianji2=0;
delay(50);
dianji1=0;
dianji2=0;
delay(50);
miaoxianshi(miao);
lcxs(lc);
}
while(heidai==7)
{
dianji1=0;
dianji2=1;
delay(90);
dianji1=0;
dianji2=0;
delay(1);
miaoxianshi(miao);
lcxs(lc);
}
break;
case 8:
dianji1=0;
dianji2=1;
miaoxianshi(miao);
lcxs(lc);
break;
case 9:
while(n--)
{
dianji1=1;
dianji2=0;
delay(50);
dianji1=0;
dianji2=0;
delay(50);
miaoxianshi(miao);
lcxs(lc);
}
dianji1=1;
dianji2=1;
TR0=0;
while(1)
{
miaoxianshi(miao);
lcxs(lc);
}
break;
default:
break;
}
}
/*————————————————延时函数———————————————————*/
//函数功能: 延时
//函数入口参数:字符型x,储存延时时间的长短
//函数返回值: 无
void delay(uchar x)
{
uchar a,b;
for(a=x;a>0;a--)
for(b=50;b>0;b--);
}
/*————————————————延时函数(延时十秒)———————————————————*/
//函数功能: 延时十秒钟
//函数入口参数:无
//函数返回值: 无
void delay10s()
{
uint a,b;
for(a=15;a>0;a--)
for(b=123;b>0;b--)
{
miaoxianshi(miao);
lcxs(lc);
}
}
/*————————————————外部中断0———————————————————*/
//函数功能: 外部中断0,用来检测黑带
//函数入口参数:无
//函数返回值: 无
void ext0() interrupt 0
{
delay(50);
if(hdjc==0)
heidai++;
}
/*————————————————定时器中断0———————————————————*/
//函数功能: 定时器中断0,用来记录时间
//函数入口参数:无
//函数返回值: 无
void time0() interrupt 1
{
TH0=(65536-500)/256;
TL0=(65536-500)%256;
num++;
if(num==20)
{
num=0;
miao++;
}
}
/*————————————————外部中断1———————————————————*/
//函数功能: 外部中断1,记录车轮转过的圈数
//函数入口参数:无
//函数返回值: 无
void ext1() interrupt 2
{
qs++;
lc=(int)(qs*21.6);
4、系统测试
自动小车为玩具遥控小汽车的改装品,在改装的过程中最重要的是考虑设计光电检测管的位置,检测黑带的光电管放在车体的中央,用遮光管将其以一定反射角度压到跑道上。路程检测用槽型光耦,放在小车的从动轮上。轮子的周长约为21.6厘米,在轮子上用了一个霍尔元件,每转一圈一个脉冲。在组装前对每一个单元电路进行测试,以保证外部硬件电路的无误,有利于最后的统调。调整是以点到线,最后到整体调试的方法。在调整的过程中我们发现了许多问题,如响应中断的次数的调整等。并且为了小车碰到墙壁不至于停车,我们在小车的四角上都加上了导向轮,导向轮用随身听的压带轮制作即可。
5、结论
本次实训系统以单片机AT89C52芯片为核心部件,利用光电检测、传感器检测技术并配合软件实现了小车的黑线检测、里程检测、时间显示等功能,最终使小车完成设计题目要求时的各项任务。在设计系统中我们三人共同讨论商量,分工协作完成这个实训任务。经过一学期的努力工作我们的实训也将成功。在这期间我们也曾放弃过对于我们这样的基础要完成这样的实训是在是一项很大的挑战,我们不知如何进行下去,我们三人很苦恼也很颓废真的想要放弃的但是在老师的鼓励下我们继续坚持下定决心要好好努力尽我们最大的能力去完成实训。不管结果如何至少我们努力过不会后悔的。其实这也是我们生活的态度,使我们在面对困难时不会临阵脱逃。而且增进我们三人之间的友谊懂得更加去共同面对问题一起商量团结之心更加紧密。体会到所学理论知识的重要性,知识掌握的越全面实训起来更轻松、更得心应手、更好。熟悉了对一项实训的设计实验的过程,这对我们以后的工作有很大的帮助。培养了我们严肃认真、积极进取、团结共进的态度。提高了我们解决问题的能力。总之,这一学期的实训让我们学会了不少、感悟颇深。
6、附录
元件清单如下:
一个STC89C52单片机
2个四位共阳数码管
一个L298 N芯片
一个LM358
一个霍尔元件和小磁钢片
光点接收管一对
晶振(12M)及30pf电容
开关
电阻 10k 100欧姆 1k 20k可调
7、参考文献
[1] 张培仁. MCS-51单片机原理及应用. 北京: 清华大学出版社, 1998:15-36
[2] 张洪润. 传感技术与应用. 北京: 清华大学出版社, 2000:111-135
[3] 阎石. 数字电子技术基础. 北京: 高等教育出版社, 1997:124-139
[4] 童诗白,华成英. 模拟电子技术基础. 北京: 高等教育出版社, 2000:163-177
[5] 常健生. 检测与转换技术. 北京: 机械工业出版社, 2004:34-43 73-97
[6] 何立民. 单片机应用技术选编. 北京: 北京航空航天大学出版社, 2001
[7] 张伟,王力. Protel DXP入门与提高. 北京: 人民邮电出版社, 2004
[8] 宋家友. 集成电子电路设计手册. 福建:福建科学技术出版社,2002
[9] 何希才. 新型电子电路应用实例. 北京:科学出版社,2005
[10]《电子产品装配与调试》、《Protel 99 se 》、《protues》、《multisim》