164串行芯片驱动程序设计鉴赏
适用范围
在家用电器微电脑控制器的设计中,基于成本的考虑,对主控芯片MCU的选择上要求引脚越少越好,因此就要求按键输入和数码管(LED)显示上能够使用尽可能少的IO口或者使用低成本扩展芯片达到相应显示和按键检测功能。本设计指引针对此类设计思想,采用一块低成本扩展芯片74HC164,占用芯片7个IO口,采用分时复用的程序实现办法,就可以显示两位数码管,十二盏LED灯,检测到八个按键。《按键和LED复用程序设计鉴赏》主要对此方法进行了分析,说明了软件编制的方法和注意事项,并提供了程序范例,为以后的程序设计者提供类似的开发参考。
引用资料
范例程序采用日本NEC公司的RA78K0S系列汇编语言编写,具体技术资料参照78K0S系列八位单片机UPD78F9177芯片的相关资料。
定义
汇编语言:是用于编写微处理器软件的最基本编程语言。
汇编程序包:是一组程序的总称,用于把汇编语言的源程序文件转换成机器代码的程序,通常包括汇编程序﹑连接程序﹑目标码转换程序和其它库管理程序﹑表转换程序等。
按键和LED复用程序设计说明
硬件资源的介绍
采用一片74HC164,四个IO口作为显示公共端分时驱动四路显示,需要两IO口模拟74HC164的时钟口和数据口,另外需要一路IO检测按键输入。共占用了7路IO口。电路原理图如下:
功能
该子程序模块需在定时中断中调用实现显示驱动和按键检测功能。
性能
低成本的代价实现丰富的输入输出功能,性价比极高。
算法
74HC164的驱动原理:74HC164是一个8位的串进并出的移位寄存器芯片。通过串口输入一个字节数据到芯片内部,数据内容则通过74HC164的Q7~Q0口体现出来,如输入数据0xAB,则Q7~Q0为10101011。因此我们可以利用74HC164这一特性,输入不同的数据到芯片内部,则可以显示不同的内容,或者在检测按键输入时,在一段时间令Q7~Q0单独一个口为低电平,然后检测单片机按键输入口是否为低电平来检测相应的按键是否有按下。如果我们需要点亮某一盏LED灯,比如需要LED灯“FAN”点亮,根据原理图,需要LED_COM4为低电平,令三极管9012导通,LED正极有+5V供电,同时LED负极为低电平,则要令到Q0为零,那就需要输入0x0FE到74HC164中,当输入数据完成后Q7~Q0=11111110。
按键扫描原理:根据原理图可以知道,应用系统具有8个按键,4路显示,程序处理过程为,每个显示和按键检测处理周期分为5个时间段,前4个时间段用来显示4路显示,第五个时间段首先关闭所有显示,然后循环8次依次输出数据0x0FEH、0x0FDH、0x0FBH、0x0F7H、0x0EFH、0x0DFH、0x0BFH、0x7FH到74HC164中,输入完成一个数据后,比如输入0x0FEH,则检测KEY1口是否为零,如果为零,则表示ON/OFF键有按下,如果不为零,则表示ON/OFF键没有按下。这样通过依次送数到74HC164中使得74HC164的Q0到Q7依次为零,就可以依次检测8个按键是否有按下,来达到按键检测和分辨键值的目的。按键防抖通过重复检测一定的按键次数实现,重复检测次数决定了按键按下的持续时间,建议时间为40-80ms。
为达到4路LED显示人眼看着不闪烁,每路显示的间隔时间建议在20毫秒以内。程序中每3毫秒驱动路显示,加上按键检测需要3毫秒,即更新一帧显示需要15毫秒,满足功能要求。具体的算法步骤参考程序流程图。
流程逻辑
参考164驱动程序中的程序流程图。
接口参数
参考164驱动程序通用标准模块中的驱动程序接口变量参数。
164驱动程序通用标准模块 (基于UPD78F9177芯片的RA78K0S汇编语言编写) | ||||
子程序名 | Key_LEDmodu.ASM | 日期 | 2004/4/21 | |
子程序功能说明: 驱动四路显示及检测8个按键。
| ||||
驱动程序接口变量参数 | ||||
变量名称 | 内容定义 | |||
Key_LEDmodu | 显示驱动和按键检测子程序入口 | |||
keymodu | 按键检测子程序入口 | |||
dbyteout | 驱动74HC164送数子程序入口 | |||
keyn | 存储扫描到的轻触按键值 | |||
busyff | 扫描到有效轻触按键的功能标志 | |||
variab0 | 多路显示驱动的计数器 | |||
kdebounce | 按键消抖计数 | |||
Disp1~disp4 | 显示内容暂存器 | |||
compo1~compo4 | 显示驱动公共IO口 | |||
Dsdapo、dsclpo | 74HC164数据口和时钟口 | |||
keytemp | 按键检测暂存器 | |||
prekeyn0 | 键值暂存器 | |||
keylist | 键值代码对应表 | |||
IO端口说明 | ||||
compo1 | 第1组LED公用端,输出 | |||
compo2 | 第2组LED公用端,输出 | |||
compo3 | 第1组LED公用端,输出 | |||
compo4 | 第2组LED公用端,输出 | |||
dsclpo | 164时钟口,输出 | |||
dsdapo | 164数据口,输出 |
;------------------------------------------------
中断处理中每4MS调用一次,判断variab0的值(0~4)来驱动4路显示或者去处理按键检测。
;------------------------------------------------
Key_LEDmodu: ;程序入口
set1 compo1
set1 compo2
set1 compo3
set1 compo4 ;关所有显示端口
cmp variab0,#4
bnz $slab023
br keymodu ;如果variab0值等于4,
; 则跳转到keymodu处理按键检测
slab023:
movw ax,#disp
xch a,x
add a,variab0
xch a,x
addc a,#0
movw hl,ax
mov a,[hl] ;以variab0为索引,访问disp1-disp4
call dbyteout ;驱动74HC164送数
cmp variab0,#3 ;根据variab0的值,开某一路显示
bnz $slab020
clr1 compo4
br slab022
slab020:
cmp variab0,#2
bnz $slab021
clr1 compo3
br slab022
slab021:
cmp variab0,#1
bnz $slab024
clr1 compo2
br slab022
slab024:
clr1 compo1
mov variab0,#5
slab022:
dec variab0 ;variab0 ranges 0-4
ret
;------------------------------------------------
驱动74HC164送数子程序
;------------------------------------------------
dbyteout:
mov x,#8 ;循环8次
slab012:
clr1 dsclpo
nop
rolc a,1 ;左移一位,寄存器A的最高位送到C
bc $slab010
clr1 dsdapo
br $slab011
slab010:
set1 dsdapo
slab011:
nop
nop
set1 dsclpo
dec x ;寄存器X减一
bnz $slab012 ;不为零则跳,为零则退出子程序
ret
;------------------------------------------------
按键检测
;------------------------------------------------
keymodu:
mov b,#8 ;循环8次,共有八个按键
mov c,#11111110b
call dbyteout ;驱动74HC164送数
nop
nop
klab15:
set1 wdtm.7 ;update WDT
clr1 keytemp.0
bt keyin,$klab14 ;判断是否有按键按下
nop
nop
set1 keytemp.0 ;有按键按下
klab14:
mov a,keytemp
rol a,1
mov keytemp,a ;暂存键值
set1 dsdapo
nop
nop
clr1 dsclpo
nop
nop
nop
nop ;此处处理等同于将164送数值左移一位
set1 dsclpo ;省去164送数子程序
dbnz b,$klab15 ;没检测完,循环检测
mov a,keytemp
mov b,a
mov c,#10
klab11:
mov a,c
dec a
getlit keylist ;查表按键代码值
cmp a,b
bz $klab16 ;valid key
dbnz c,$klab11
mov a,#0 ;there is no key pressed
br klab10
klab16:
mov a,c
klab10: ;get key number detected
cmp a,#0
bnz $ klab110
cmp keytemp,#0
bz $ klab110
set1 busyff ;检测到无用的多个键按下时
mov a,#44 ;不与处理,直到按键完全抬起
mov keydata,a
klab110:
cmp a,prekeyn0
bnz $klab05
dbnz kdebounce,$klab06 ;按键消抖处理
cmp a,#0
bz $klab04
klab03:
set1 busyff
klab04:
mov keyn,a
klab05:
mov prekeyn0,a
mov kdebounce,#3 ;按键消抖
klab06:
dec variab0
;==================
klabend: nop
ret
keylist: 按键代码表
db 00000001b ;onoffkeynequ
db 10000000b ;modekeynequ
db 01000000b ;speedkeynequ
db 00100000b ;timeonkeynequ
db 00010000b ;timeoffkeynequ
db 00000100b ;upkeynequ
db 00001000b ;downkeynequ
db 00000010b ;swingkeynequ
db 081h ;testkeynequ
db 0ch ;OC_OFkeynequ
end
164驱动程序流程图:
下一篇 : 没有了