【技术分享】【原创】基于AT89C52的一个速度计数器的设计过程
0赞前面说到要写一下嵌入式HCS12的调试的文章,最近实验室关门了,进不去,不好调试,等段时间吧,写一个简单的基于AT89C52的一个速度计数器的设计过程。
设计要求:利用单片机实现的自行车里程/速度计能自动显示自行车行驶的总里程数及自行车行驶速度,具有超速信号提醒功能,里程数据自动记忆。也可应用于电动自行车、摩托车、汽车等机动车仪表上。
1. 总体设计
控制器采用AT89C52单片机,速度及里程传感器采用霍尔元件,显示器通过AT89C52的P0口和P2口扩展。外部存储器采用E2PROM存储器AT24C01,用于存储里程和速度等数据。并用控制器来控制里程/速度指示灯,里程指示灯亮时,显示里程;速度指示灯亮时,显示速度。超速报警采用扬声器,用一个发光二极管来配合扬声器,扬声器响时,二极管亮,表明超速。
2. 硬件电路设计
电路原理图如下页图所示。P0口和P2口用于七段LED显示器的段码及扫描输出。在显示里程时,第三位小数点用P3.7口()控制点亮。P1.0口和P1.1口分别用于显示里程状态和速度状态。P1.2,P1.3,P1.6和P1.7口分别用于设置轮圈的大小。P3.0口的开关用于确定显示的方式。当开关闭合时,显示速度;断开时,显示里程。外中断用于对轮子圈数的计数输入,轮子每转一圈,霍尔传感器输出一个低电平脉冲。外中断用于控制定时器T1的启停,当输入为0时关闭定时器。此控制信号是将轮子圈数的计数脉冲经二分频后形成,这样,每次定时器T1的开启时间正好为轮子转一圈的时间,根据轮子的周长就可以计算出自动车的速度。P1.4口和P1.5口用于E2PROM存储器24C01的存取控制。11脚(TXD)输出用于速度超速时的报警。
3. 软件设计
软件主要包括:主程序、初始化程序、里程计数子程序、数据处理子程序、计数器中断服务程序、E2PROM存取程序、显示子程序。
(1)主程序
根据P0口的开关状态切换显示状态,即选择里程显示和速度显示。其流程图如右图所示。
程序如下:
ORG 0000H
LJMP START ; 跳至主程序
ORG 0003H ; 外中断0中断程序入口
LJMP INTEX0 ; 跳至INTEX0中断服务程序
ORG 000BH ; 定时器T0中断程序入口
RETT1 ; 中断返回
ORG 0013H ; 外中断1中断入口
LJMP INTEX1 ; 跳至INTEX1中断服务程序
ORG 001BH ; 定时器T1中断程序入口
LJMP INTT1 ; 跳至INTT1中断服务程序
ORG 0023H ; 串口中断入口地址
RET1 ; 中断返回
ORG 002BH ; 定时器T2中断入口地址
RET1 ; 中断返回
ORG 0050H
START: LCALL CLEARMEN ; 上电初始化
START1: JB P0.4, DISPLAYS ; P0.4=1,则显示里程
LCALL DISPLAYV ; P0.4=0,显示速度
START2: SJMP START ; 转START循环
(2)初始化程序
初始化程序主要功能是将T1设为外部控制定时器方式,外中断 及 设为边沿触发方式,将部分内存单元清0,设置车轮周长值,开中断、启动定时器,将AT24C01中的数据调入内存中,设置车轮圈出错处理程序。
程序如下:
CLEARMEN: MOV TMOD, #90 ; T1为16位外部控制定时器
MOV SP, #75H ; 堆栈在75H开始
SETB PX0 ; 外中断0优先级为1
SETB IT0 ; 外中断0用边沿触发
SETB IT1 ; 外中断1用边沿触发
MOV A, #00H ; 清A
MOV 20H, A ; 清内存中特定单元
MOV 6CH, A
MOV 6DH, A
MOV 70H, A
MOV 71H, A
MOV 72H, A
MOV 73H, A
MOV 60H, A
MOV 61H, A
MOV 62H, A
MOV 63H, A ; 清内存中特定单元
DEC A ; A为#0FFH
MOV 68H,A ; 内存置数据#0FFH
MOV 69H,A ; 内存置数据#0FFH
MOV 6AH,A ; 内存置数据#0FFH
MOV 6BH,A ; 内存置数据#0FFH
MOV P1, A ; P1口置1
CLEAR1: JB P1.2, KEY1 ; 根据P1.2, P1.3, P1.6, P1.7设置状态
在21H地址单元设置自行车周长值
MOV 21H,#0FH ; 22英寸自行车周长系数
LJMP CLEAR2 ; 转CLEAR2
KEY1: JB P1.3, KEY2
MOV 21H, #12H ; 24英寸自行车周长系数
LJMP CLEAR2 ; 转CLEAR2
KEY2: JB P1.6,KEY3
MOV 21H,#14H ; 26英寸自行车周长系数
LJMP CLEAR2 ; 转CLEAR2
KEY3: JB P1.7,ERR
MOV 21H,#19H ; 28英寸自行车周长系数
CLEAR2: SETB TR1 ; 开定时器开关T1
SETB EA ; 开中断允许
SETB EX0 ; 开外中断
SETB ET1 ; 开定时中断T1
SETB P3.1 ; 关报警器
LCALL VIICREAD ; 将E2PROM中原里程数据调入内存
RET ; 子程序返回
ERR: CLP P3.1 ; 轮周长设置出错,LED灯闪烁提醒
LCALL DLSS5 ; 延时
LJMP CLEAR1 ; 重新初始化,等待轮周长设置开关合上
(3)里程计数子程序
外中断 服务程序用于对输入的车轮圈数脉冲进行计数,为十六进制计数,用片内RAM的60H单元存储计数值的低位,62H存储高位,计数一次后,对里程数据进行一次存储。
程序如下:
INTEX0: PUSH ACC ; 累加器堆栈保护
PUSH PSW ; 状态字堆栈保护
INC 60H ; 圈加1
MOV A, #00H ; 清A
CJNE A, 60H,INTEX0OUT ; 计数没溢出转IN0OUT
INC 61H ; 溢出进位(61H加1)
CJNE A, 61H, INTEX0OUT ; 计数没溢出转IN0OUT
INC 62H ; 溢出进位(62H加1)
IN0OUT: LCALL VIICWRITE ; 里程数据存入E2PROM
SETB EX1 ; 开外中断1
POP PSW ; 状态字恢复
POP ACC ; 累加器恢复
RET1 ;
(4)数据处理子程序
外中断服务程序用于处理轮子转动一圈后的计时数据,当标志位(00H)为1时,说明计数器溢出,放入最大值0FFH;当标志位为0时,将计数单元(TL1,TH1,6CH, 60H)的值放入68H~6BH单元。
程序如下:
INTEX1: PUSH ACC ; 累加器堆栈保护
PUSH PSW ; 状态字堆栈保护
CLR EX1 ; 关外中断1
JNB 00H, INTEX11 ; 溢出标志为0转INTEX11
MOV TL1, #0FFH ; 溢出时,计时单元赋#FFH(显示速度为0)
MOV TH1, #0FFH
MOV 6CH, #0FFH
MOV 6DH, #0FFH
INTEX11: MOV 68H, TL1 ; 将时间计数值存入暂存单元68H~6BH
MOV 69H, TH1
MOV 6AH, 6CH
MOV 6BH, 6DH
MOV A, #00H ; 清A
MOV TL1, A ; 计时单元置0
MOV TH1, A
MOV 6CH, A
MOV 6DH, A
CLR 00H ; 清溢出标志
POP PSW ; 状态字恢复
POP ACC ; 累加器恢复
RET1 ; 中断返回