学 科: 单片机原理及应用
项 目: 里程记录仪
学 院:
专业、年级:
指导老师:
摘要
设计首先实现对小车行驶时的平均速度、即时速度以及里程等行驶参量的实时测量和显示功能,扩展了对小车的行驶时间的显示功能。
设计硬件部分设计采用了STC公司的STC89C52系列单片机为微控制器,根据车辆里程记录仪的要求对系统的主控模块、液晶显示模块、行车数据采集测量模块、蓝牙通信模块以及电机驱动等模块进行了设计。软件设计以Proteus为开发平台,结合C51系列单片机强大的在线调试能力,以C语言为编程语言编写出实用程序。并将之运用到了实物测试之中。
关键词:c51单片机、 OLED显示 、蓝牙控制、 L298n、 霍尔电机
Abstract
Firstly, the design realizes the real-time measurement and display function of the average speed, real-time speed and mileage of the car, and expands the display function of the car's travel time.
The hardware part of the design adopts STC89C52 series single chip microcomputer of STC company as the microcontroller. According to the requirements of vehicle mileage recorder, the main control module, LCD module, driving data acquisition and measurement module, Bluetooth communication module and motor drive module of the system are designed. The software design takes Proteus as the development platform, combined with the powerful online debugging ability of C51 series MCU, and uses C language as the programming language to write the utility program. And it is applied to the physical test.
Key words: C51 single chip microcomputer, OLED display, Bluetooth control, L298N, Hall motor
目录
课程设计报告 1
1、小组成员 3
2、成员分工 3
3、 系统总体设计 4
3.1设计要求 4
3.2系统理想功能描述 4
3.3主控模块方案的比较与选择 4
3.4速度测量原理 6
4、电路与程序设计 6
4.1元件选型 6
4.2工作原理 7
4.3电路设计 7
4.4程序设计 8
4.5实际效果 14
4.6实物图以及操作展示 14
5、设计过程 17
5.1遇到的问题 17
5.2解决方法 17
6、报告总结 17
1、小组成员
2、成员分工
设计构思与资料查询:
3.1设计要求
出租车或自行车里程记录仪的设计,能实时测量里程,即时速度,平均速度,三个参数的显示可以用按键切换。设计硬件电路并编写程序。
3.2系统理想功能描述
3.3主控模块方案的比较与选择
(1)方案一:采用MCS51系列单片机作为微控制器
采用STC89C52作为微控制器,STC89C52是STC公司早年生产的一种拓展型的8位微控制器。其主要优点是价格低廉且MCS-51系列是最早引入国内的单片机系列,在国内有着极其广泛的应用,设计范例经典,设计方案成熟,国内市场上的低端行车记录仪产品大多采用这一微控制器。
(2)方案二:采用TI公司的MSP430系列单片机作为处理器
采用MSP430F149单片机为微处理器,msp430 系列单片机是由是美国德州义器(TI)九十年代推出的主打超低功耗的十六位单片机,具有丰富的片内片外接口。其主要特点是处理能力强、运算速度快及超低功耗等特点。内部的看门狗定时器可以保证在程序跑飞时自动的复位使程序重新开始执行,确保系统的稳定性;硬件USART串行总线接口可以进行UART异步串行通信方式和I2C同步串行通信方式;另外,MSP430系列单片机有较多的中断,有不同的优先级,利用这些中断源可以在软件上采用中断触发机制,这样可以实现超低功耗的特点。
采用AT89C52单片机为微处理器,AT89C52是美国ATMEL公司生产的低电压.高性能CMOS 8位单片机.内合8K bytes的可反复擦写的只读程序存储器(PEROM和256 bytes的随机存取数据存储器(RAM),器件采用ATMEI公司的高密度,非易失性存储技术生产,与标准MCS-51指令系统及8052产品引脚兼容,片内置通用8位中央必理器(CPU)和Flash存储单元,功能强大AT89C5单片机适合于许多较为复杂控制应用场合。允许RAM定时/计数器,串行通信口及中断系统继续工作.掉电方式保存RAM中的内容,但振荡器停止工作并禁止其它所有部件工作直到下一个硬件复位。
综上考虑了设计的硬件要求和STC89C52使用广泛、价格低廉和设计方案成熟等特点以及组员更加熟悉基于STC89C52的编程方法,最终设计选用STC89C52系列的STC89C52RC单片机作为系统的微控制器。
3.3.1 方案确定与设计
设计采用STC89C52RC单片机为微处理器,通过外接电路包括霍尔测速模块、OLED显示模块和无线通讯通讯模块组成具有实用价值的低功耗的行车记录仪系统,实现对小车运行过程中行驶里程、及时速度、平均速度的测量和显示。
图1:设计思路
3.3.2 工作流程图
图2:工作流程图
3.4速度测量原理
经过小组讨论本设计是根据第一个原理计算速度的。
4、电路与程序设计
4.1元件选型
主控芯片:STC89C52RC
STC89C52是一种带8K字节闪烁可编程可檫除只读存储器(FPEROM-Flash Programable and Erasable Read Only Memory )的低电压,高性能COMOS8的微处理器。该器件采用ATMEL高密度非易失存储器制造技术制造,与工业标准的MCS-51指令集和输出管脚相兼容。
主要功能特性:
兼容MCS51指令系统 |
8k可反复擦写Flash POM |
32个双向I/O口 |
256*8bit内部RAM |
3个16位可编程定时/计数器中断 |
时钟频率0-24MHZ |
2个串行中断 |
可编程UART串行通道 |
2个外部中断源 |
共6个中断源 |
2个读写中断口线 |
3级加密位 |
低功耗空闲和掉电模式 |
软件设置睡眠和唤醒功能 |
表1 STC89C52系列主要功能特性
电机驱动模块:L298N
L298N是ST公司生产的一种高电压、大电流电机驱动芯片。该芯片采用15脚封装。主要特点是:工作电压高,最高工作电压可达46V;输出电流大,瞬间峰值电流可达3A,持续工作电流为2A;额定功率25W。内含两个H桥的高电压大电流全桥式驱动器,可以用来驱动直流电动机和步进电动机、继电器线圈等感性负载;采用标准逻辑电平信号控制;具有两个使能控制端,在不受输入信号影响的情况下允许或禁止器件工作有一个逻辑电源输入端,使内部逻辑电路部分在低电压下工作;可以外接检测电阻,将变化量反馈给控制电路。该芯片可以驱动一台两相步进电机或四相步进电机,也可以驱动两台直流电机。
显示:OLED显示屏
OLED显示屏与LCD显示屏相比结构简单、更加轻薄、原生色域广、对比度和亮度高、响应时间快、省电、可视角度广但是寿命没有LCD屏高。
测速模块:霍尔电机
霍尔元件是磁敏元件,要想用来测转速,就必须在被测的旋转体上装一个磁体,旋转时,每当磁体经过霍尔元件,霍尔元件就发出一个信号,经放大整形得到脉冲信号,也有的霍尔元件可以直接输出脉冲信号,送运算,两个脉冲的间隔时间就是周期,由周期可以换算出转速,也可计数单位时间内的脉冲数,再换算出转速。
车轮驱动:减速电机
4.2工作原理
里程、速度等由霍尔元器件测量。已知小车轮胎的周长为0.215m,轮子每转动一圈,安装在车轮辐条上的磁钢接近霍尔传感器一次,传感器送13个脉冲信号给单片机的外部中断0,每送13个脉冲信号,圈数加一。圈数*0.215即为车前进距离。而通过单片机T0定时器记录时间,间隔1秒,1秒内的前进距离除以时间1秒,得到1秒内的当前速度作为即时速度。而总里程L除以总时间t得到平均速度。
系统处理速度数据时同时刷新平均速度、即时速度及运行里程。
单片机定时器0定时时间为50ms,每20次刷新系统时钟及计算累计行驶时间。
4.3电路设计
图3:电路原理图
4.4程序设计
主要程序:
#include
#include
#include
#include"oled.h"
#define uchar unsigned char
#define uint unsigned int
//#define zhijing 6.5 //直径6.5cm 周长3.14*6.5=20.41cm
//#define licheng zhijing*quanshu
//函数声明
void v_u();
void v_d();
void v_init();
void gc();
void qh();
void zpy();
void cs();
void ypy();
void mb_init();
void jishuqi();
//PWM输出(控制舵机)
sbit V =P2^0;
sbit SEH_PWM =P3^3;
uint PWM_T=0,t=0;
uchar temp; //temp储存蓝牙串口收到的信息
uchar count=0; //0.1ms次数标识
uchar SEV_count=1; //舵机角度标识
uchar SEH_count=1;
bit flag;
uchar p=0;
uchar ms=0;
uchar fen=0;
uchar mc=0;
long int quanshu=0;
uint pjsd=0;
uint jssd=0;
long int lc=0;
uint su=0;
uint sd=0;
uint d=0;
void delay_1ms(uint t)
{
uint x,y;
for(x=t;x>0;x--)
for(y=120;y>0;y--);
}
void PWM1(uchar x)
{
SEV_count=x;
}
void main()
{
flag=0;
EA = 1;
Car_Init(); //初始化轮子配制
Com_Init();
V=0;
TR0=0; //关闭定时器0
OLED_Init(); //初始化OLED
OLED_Clear() ;
OLED_ShowCHinese(0,0,12);//蓝牙测速里程小车
OLED_ShowCHinese(16,0,13);//
OLED_ShowCHinese(32,0,14);//
OLED_ShowCHinese(48,0,15);//
OLED_ShowCHinese(64,0,16);//
OLED_ShowCHinese(80,0,17);//
OLED_ShowCHinese(96,0,18);//
OLED_ShowCHinese(112,0,19);//
//
OLED_ShowString(32,2,"Author:TJX",16); //:
OLED_ShowString(32,4,"QJ JSC CC",16); //:
V=1;
while(1)
{
switch(temp)
{
case 0x00: stop(); break;
case 0x01: go(); break;
case 0x02: back(); break;
case 0x03: left(); break;
case 0x04: right(); break;
case 0x05: v_u(); break;
case 0x06: v_d(); break;
case 0x07: qh(); break;
case 0x08: gc(); break;
case 0x09: zpy(); break;
case 0x0A: ypy(); break;
case 0x0b:cs();break;
}
}
}
void uart_ser() interrupt 4 //串口中断函数
{
RI = 0;
temp = SBUF; //将接收到的数据传给temp
}
timer0() interrupt 1 //计时器
{
p++;
if(p==20)
{
d++;
if(d==1)
{
su=quanshu*6.5*3.14/13;
}
if(d==2)
{
sd=quanshu*6.5*3.14/13;
d=0;
jssd=sd-su;//及时速度的计算每秒刷新,(现里程-上一秒里程)/1s
}
p=0;
ms++;
if(ms==60)
{
ms=0;
fen++;
if(fen==60)
{
fen=0;
}
}
}
TH0=0x4b; //
TL0=0xfd; //
}
ZD() interrupt 0
{
quanshu++;
}
void v_d()
{
if(PWM_T<250)
{
PWM_T=PWM_T+25; //越大正电压占空比越小,占空比越小速度越慢
}
delay_1ms(10);
temp=0xff;
}
void v_u()
{
if(PWM_T>24)
{
PWM_T=PWM_T-25;
if(PWM_T<25)
PWM_T=0;
}
delay_1ms(10);
temp=0xff;
}
void v_init() //pwm初始化
{
TMOD = 0x22; //定时器0,工作模式2,8位定时模式
TH0=210; //写入预置初值(取值1-255,数越大PWM频率越高)
TL0=210; //写入预置值 (取值1-255,数越大PWM频率越高)
TR0=1; //启动定时器
ET0=1; //允许定时器0中断
EA=1; //允许总中断
V=1; //初始化P2.0,输出端口作为pwm输出控制车速
PWM_T=30;
}
void qh()
{
while(1)
{
go();
delay_1ms(100);
back();
delay_1ms(100);
if(temp!=0x07)
break;
}
}
void gc()
{
while(1)
{
left();
delay_1ms(100);
right();
delay_1ms(100);
if(temp!=0x08)
break;
}
}
void zpy()
{
PWM_T=0;
go();
delay_1ms(500);
left_go=0;//前轮左转
left_back=1;
right_go=1;
right_back=0;
left_go2=0;//后轮抱死
left_back2=0;
right_go2=0;
right_back2=0;
delay_1ms(250);
go();
delay_1ms(250);
temp=0;//执行完停止
}
void ypy()
{
PWM_T=0;
go();
delay_1ms(500);
left_go=1;//前轮右转
left_back=0;
right_go=0;
right_back=1;
left_go2=0;//后轮抱死
left_back2=0;
right_go2=0;
right_back2=0;
delay_1ms(250);
go();
delay_1ms(250);
temp=0;
}
void cs()
{
temp=0xff;
flag=1;
V=1; //速度初始化
TR0=0; //关闭定时器0
mb_init(); //秒表初始化
OLED_Clear() ; //清屏
jishuqi();//计数器初始化
//oled界面初始化
OLED_ShowCHinese(0,0,0);//里
OLED_ShowCHinese(16,0,1);//程
OLED_ShowString(32,0,":",16); //:
OLED_ShowCHinese(0,2,2);//及
OLED_ShowCHinese(16,2,3);//时
OLED_ShowCHinese(32,2,4);//速
OLED_ShowCHinese(48,2,5);//度
OLED_ShowString(64,2,":",16);//:
OLED_ShowCHinese(0,4,6);//平均速度
OLED_ShowCHinese(16,4,7);//时
OLED_ShowCHinese(32,4,8);//速
OLED_ShowCHinese(48,4,9);//度
OLED_ShowString(64,4,":",16);//:
OLED_ShowCHinese(0,6,10);//单
OLED_ShowCHinese(16,6,11);//位
OLED_ShowString(36,6,"m",16); //:
OLED_ShowString(56,6,"m/s",16); //:
while(1)
{
lc=quanshu*6.5*3.14/13;//精确到20.41/13,单位为厘米
pjsd=lc/(fen*60+ms); //cm/s
//蓝牙控制
switch(temp)
{
case 0x00: stop(); break;
case 0x01: go(); break;
case 0x02: back(); break;
case 0x03: left(); break;
case 0x04: right(); break;
case 0x05: v_u(); break;
case 0x06: v_d(); break;
case 0x07: qh(); break;
case 0x08: gc(); break;
case 0x09: zpy(); break;
case 0x0A: ypy(); break;
case 0x0b:cs();break;///测速里程模块
}
//更新里程,平均速度,瞬时速度以及秒表
OLED_ShowNum(40,0,lc/10000,1,16);
OLED_ShowNum(40 + 8,0,lc/1000%10 ,1,16);
OLED_ShowNum(40 + 8+8,0,lc/100%10 ,1,16);
OLED_ShowChar(40 + 16+8,0,'.',16);
OLED_ShowNum(40 + 24+8,0,lc/10%10,1,16);
OLED_ShowNum(40 + 24+8+8,0,lc%10,1,16);
OLED_ShowNum(70,2,jssd/1000,1,16);
OLED_ShowNum(70 + 8,2,jssd/100%10 ,1,16);
OLED_ShowChar(70 + 16,2,'.',16);
OLED_ShowNum(70 + 24,2,jssd/10%10,1,16);
OLED_ShowNum(70 + 24+8,2,jssd%10,1,16);
OLED_ShowNum(70,4,pjsd/1000,1,16);
OLED_ShowNum(70 + 8,4,pjsd/100%10 ,1,16);
OLED_ShowChar(70 + 16,4,'.',16);
OLED_ShowNum(70 + 24,4,pjsd/10%10,1,16);
OLED_ShowNum(70 + 24+8,4,pjsd%10,1,16);
OLED_ShowNum(88 ,6,fen/10,1,16);
OLED_ShowNum(96 ,6,fen%10,1,16);
OLED_ShowString(104,6,":",16);//:
OLED_ShowNum(112 ,6,ms/10,1,16);
OLED_ShowNum(120 ,6,ms%10,1,16);
}
}
void mb_init() //计时器初始化
{
TMOD = 0x21; //定时器0,工作模式1,16位定时模式
TH0=0x4b; //
TL0=0xfd; //
TR0=1; //启动定时器
ET0=1; //允许定时器0中断
EA=1;
}
void jishuqi() //p3.5 用中断0来采集1圈数
{
IT0=1;
EX0=1;
EA=1;
}
4.5实际效果
4.6实物图以及操作展示
图4:实物图(侧)
图5:实物图(俯)
图6:显示界面展示
图7:操控界面展示
5、设计过程
5.1遇到的问题
5.2解决方法
6、报告总结
经过几个星期的讨论与研究,我们小组成功的做出了基于51单片机的汽车里程记录仪,本设计采用STC89C52单片机为微控制器,实现了对行驶车辆的平均速度、即时速度、里程等参数进行测量,并且具有人机交互的功能,可以通过手机蓝牙控制执行的功能,实现了设计要求。
在设计之初,通过小组成员交换意见之后,发现在仿真效果这一方面存在着较大的问题。由于不能顺利的做出仿真效果,我们打算根据身边有限的硬件资源试着将设计用实物展现出来,规避自身的短板。经过讨论,小组全体成员认为此方案可行并迅速分配好了任务。
在设计过程期间,小组内成员都各司其职,较为出色的完成了小组长分配给自己的任务,虽然在设计过程中我们遇到了很多困难,也有过分歧,但最终在老师的帮助以及小组成员的不懈努力下,克服了硬件和软件上的困难,成功的将实物做了出来,并在此基础上完成了设计报告。实物与思考题要求有些差别,它能够实时的测量里程、及时速度、平均速度但是应用OLED屏能将三个参数同时显示在屏幕上,不需要用按键来切换显示。除此之外,本设计还新增了能够显示小车运行时间的功能。
此次设计经历对我们小组内每个人来说都是宝贵的财富,在设计过程中大家互帮互助,在遇到问题时,大家一起想办法解决,每个人都可以将自己内心的想法表达出来。在设计的过程中大家学到了每个成员各自擅长的许多知识与技能,对书本上单片机中断和定时部分也有了更深的掌握,为我们未来的工作积累了宝贵的经验,也让我们收获了许多。但是也有一些不足之处:遇到问题时,我们首先想着逃避,实在是逃不开才会想着办法将问题解决;对proteus仿真软件还不是很熟练,在探索涉及到的新的仿真步骤时花费了大量的时间,导致有一段时间进度停滞;在程序编写方面,对单片机程序编写方法掌握的还不够,但是我们又盲目的认为自己可以,导致软件设计部分走了不少弯路;对硬件制版的技能掌握的不够,在用盐酸和双氧水腐刻铜板时剂量掌握的不好导致转印后的铜板腐刻不成功,浪费了很多材料。
这次课程设计对我们来说是一次检测自身能力,认清自我能力定位的机会。我们在一次次碰壁中成长,对自己能力的了解也越来越深刻。我们认识到了自己的不足,也知道了自己在某些方面的掌握只是稍稍比其他同学好一点点。在以后的学习中,我们一定会对自己还欠缺的地方格外的注意,努力补齐短板,争取对单片机方面的知识掌握的更加熟练。
说明
百度网盘链接:https://pan.baidu.com/s/1P_iFhUeozLOXqt8Q6wKUQg
csdn资源链接:https://download.csdn.net/download/ryncgh/85422995
蓝牙软件:蓝牙调试器。使用方法可以参考以下内容:
https://blog.csdn.net/qq_53022278/article/details/120579388?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165293619316782425130950%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=165293619316782425130950&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_click~default-2-120579388-null-null.142^v10^pc_search_result_control_group,157^v4^control&utm_term=%E8%93%9D%E7%89%99%E8%B0%83%E8%AF%95%E5%99%A8&spm=1018.2226.3001.4187https://blog.csdn.net/qq_53022278/article/details/120579388?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165293619316782425130950%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=165293619316782425130950&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_click~default-2-120579388-null-null.142%5Ev10%5Epc_search_result_control_group,157%5Ev4%5Econtrol&utm_term=%E8%93%9D%E7%89%99%E8%B0%83%E8%AF%95%E5%99%A8&spm=1018.2226.3001.4187
测速:测速是依靠底部的霍尔传感器电机实现的,我这里只需要三根线,给霍尔传感器供电以及A项数据输出(输出波形我用示波器看了挺工整的不需要额外的滤波电路),用51自带的计数器中断实现的计数,详情见代码,记不清了。