计数器
(此计数器创意源自别的课题,C语言代码由本人自行查询资料完成,proteus仿真查询普中系列单片机电路设计)
一.功能设计说明
本次实验拟用proteus和keil5仿真实现一个计数器
计数器有复位功能,按下该按键,计数器清零
暂停和继续计数功能,按下按键实现计数停止和开始计数的功能
正反计数功能,按下按键后,计数器在当前数字开始反计数,再次按下回到正计数
长短按功能,长按按键3秒后(近似),计数器计数在快计数和慢计数挡切换
计数保护功能,正计数达到上限200或者反计数达到0后,计数停止,保留当前值
二.代码功能实现
2.1变量和函数说明:
sec是当前计数值
Flag:加减计数转换标志位
Buttongflag:快计数和慢计数的标识
CF:P0端口
K1:K1复位 就是将运行的程序结束 然后重新开始运行
K2:暂停和开始 ,长按进入快慢计数模式切换
K3:正反计数切换
K4:模式切换
Triggercount:长短按的触发条件
数码管的位选由P2引脚控制,命名为LED1~4,方便表示位选数组为disbuff[],数字0到9段选控制由num[]数组给定控制计数
计数每次步进一,采用除以10的方法来确定计数值的百位,十位和个位
简单的延时函数:ms为1代表延时1ms,用于按键消抖
显示函数:为了显示舒适不闪动,令CF=0x00消隐
2.2辅助计数软件
计数采用定时器1,设定50ms进入一次中断,每进入10次中断sec加一(慢计数,正计数模式下)
初始值高位和低位计算用辅助软件,
2.3主函数和中断说明
设定工作模式TM0D=0x11,初始值设定,开启中断,启动定时器。
每次进入中断,重新赋值,启动定时器10次中断后,sec值加一。
至此简单的计数功能已经实现。
2.4其余功能设计
按键K1控制复位,只需要在K1按下的松开后,sec=0,TR0=1;重新开始计数。当然按键的消抖也是必不可少的。这里按键触发采用上升沿触发,按键松开后才会计数
K2按键按下,消抖后就只需要对TR0取反,就能停止计数和开始计数。
对快慢计数切换也在K2进行操作,当K2按下不松开,一直进入到while(!K2)循环中,循环每1ms延时给triggercount加一,直到松开,松开后判断triggercount的值,如果大于2200则认为是长按了,先triggercount置零,然后切换buttonflag的值在5和10变化,调整要进入多少次中断才给sec值加一。然后开始计数,TR0=1
如果triggercount的值小于2200,认为短按,给triggercount置零,依旧维持开始和暂停功能。
对正计数和反计数设计,按下K3,消抖处理后让flag取反。
Flag是进入buttonflag次中断后,判断flag是否为True,让sec加一或者减一。
计数保护设计,只需要在中断判断sec的值是否为200或者0,这里注意判断顺序应该为sec加减后判断,否则开机或者复位会触发保护。然后TR0=0关闭定时器。
三.仿真设计
采用AT89C51的MCU,独立按键K1~K4连接P3.0~P3.3,
8位共阴极数码管,数码管的位选由74LS138译码器实现,段选用74HC573
独立按键K1~K4接引脚P3.0-P3.3
总体仿真电路设计如下:
实物验证:使用stc89c52rc,验证与仿真一致
四.心得体会:
在此之前我没有使用过proteus进行单片机的仿真验证,所以这次使用proteus还是很吃力的,尤其是对51MCU的外围电路配置,比如说晶振的配置,使能的配置此次仿真实验,让我体会到了嵌入式系统的学习不仅仅是代码语言的编写,首先得在实际电路中还搭建好,
此次proteus的仿真电路我参考了经典普中51单片机的原理。
此次我最印象深刻的地方就是长按功能的实现,因为我无论是单片机上和仿真上都不能实现长按,我反复检查代码逻辑,始终发现不了问题。最后终于是明白,问题出在triggercount的定义,我需要让triggercount大于2200才能进入长按功能,所以我对triggercount的类型不能是char,无符号的字符类型只能0~255,就是这个问题让我至少花费了2个小时。最后改为无符号int类型,长按终于实现,功能圆满。
此次作业仍有许多不足的地方,例如对代码结构还是比较混乱的,不易读,执行效率不高。代码没有分块编写,不方便移植。希望能够继续改进