snifer

【技术分享】【原创】基于AT89C52的一个速度计数器的设计过程

0
阅读(15109)

前面说到要写一下嵌入式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 ; 中断返回


呵呵,就是这样,感觉这个系统做的比较不错,适合初学者,谢谢大家投票啊


Baidu
map