完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
期待
|
|
|
|
|
|
亮剑
|
|
|
|
|
|
第二十一节:纯IO口动态扫描数码管的驱动方式
(1) 开场白: 利用单片机IO口来动态扫描数码管这种驱动方式,仅仅适合应用在实时性要求不高,简单的系统中,比如鸿哥当年应用在养猪温控器这样的系统中就绰绰有余,想看养猪温控器的朋友请看我另外一个经验分享帖《血与泪的发明创造之路-吴坚鸿的亲身经历与反思》。用这种驱动方式时,为了让数码管显示正常,必须每隔一次定时中断就去扫描一次,慢了或者快了都会引起数码管显示的不均匀,在这样的系统中,动态扫描数码管这件事是最高优先级的。 (2) 功能需求: 要求左边的数码管显示一个“1”数字,右边的数码管显示一个“2”数字。 (3)硬件原理: 用任意7个IO口经过中间串接470欧电阻连接到数码管的seg引脚,用2个IO口经过中间串接470欧电阻连接到数码管的com引脚。本程序是驱动两位的共阴数码管。 (4)源码适合的单片机: PIC16F73,晶振为3.579545MHz。 (5)源代码讲解如下: #include #define seg_0_dr RB6 //任意7个IO口接数码管的seg引脚 #define seg_1_dr RB5 #define seg_2_dr RB4 #define seg_3_dr RB3 #define seg_4_dr RC7 #define seg_5_dr RB0 #define seg_6_dr RB1 #define com_left_dr RB2 //任意2个IO口接数码管的com引脚 #define com_right_dr RB7 void initial();//初始化 void delay1(unsigned int de) ;//小延时程序,时间不宜太长,因为内部没有喂看门狗 void display_drive(); //数码管驱动程序,放在定时中断里 void display_seg(unsigned char seg); //编码转换程序,放在display_drive里 unsigned char number_left=0; //左边数码管显示的内容 unsigned char number_right=0; //右边数码管显示的内容 unsigned char dis_step=1; //扫描的步骤 main() //主程序 { initial(); //初始化 while(1) { number_left=1; //左边数码管显示的内容,显示"1" number_right=2; //右边数码管显示的内容,显示"2" CLRWDT(); } } void interrupt timer1rbint(void) //中断程序入口 { if(TMR1IE==1&&TMR1IF==1) //定时中断程序 { TMR1IF=0; TMR1ON=0; display_drive(); //数码管驱动程序,放在定时中断里 TMR1H=0xFF; TMR1L=0xC8; TMR1ON=1; } } void initial()//初始化 { ADCON0=0x41; //设置AD模式 ADCON1=0x04; //RA0作为AD输入通道 TRISB=0x00; //数码管IO口设置成输出 TRISC7=0; T1CON=0x24; //定时中断配置 TMR1H=0xFE; TMR1L=0xEF; INTCON=0xC0; TMR1IF=0; TMR1IE=1; PEIE=1; //外围中断允许 GIE=1; TMR1ON=1; } void display_drive() //数码管驱动程序,放在定时中断里 { seg_0_dr=0; seg_1_dr=0; seg_2_dr=0; seg_3_dr=0; seg_4_dr=0; seg_5_dr=0; seg_6_dr=0; com_left_dr=1; com_right_dr=1; //在即将更换下一位数码管时,先把让它两个什么都不显示,让显示过度更加平稳 asm("nop"); //空指令延时 asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); switch(dis_step) { case 1: //扫描左边的数码管 display_seg(number_left); //如果不是任意IO口,可以直接用查表的方式取代此子程序 com_left_dr=0; //选中左数码管 com_right_dr=1; break; case 2: //扫描右边的数码管 display_seg(number_right); //如果不是任意IO口,可以直接用查表的方式取代此子程序 com_left_dr=1; com_right_dr=0; //选中右数码管 break; } delay1(50); //每一位数码管显示的停留延时时间,有疑问的朋友请自己尝试改成计数延时的方式, //鸿哥认为在此种环境下,在定时中断里用死延时delay1(50)是最佳的方式 ++dis_step; //下一次中断扫描另外一位的数码管,轮流扫描 if(dis_step>2) { dis_step=1; } } //不是鸿哥不懂爱,如果不是用任意IO口,而是直接用一个并口(比如51单片机中的P1口),那么就不用那么费力, //直接用查数组(俗称查表)的方式就可以替代display_seg这个编码转换程序, void display_seg(unsigned char seg) //编码转换程序,,放在display_drive里 { switch(seg) //switch指令,单片机中的战斗机,鸿哥的最爱! { case 0: //显示"0" seg_0_dr=1; seg_1_dr=1; seg_2_dr=1; seg_3_dr=1; seg_4_dr=0; seg_5_dr=1; seg_6_dr=1; break; case 1: //显示"1" seg_0_dr=1; seg_1_dr=1; seg_2_dr=0; seg_3_dr=0; seg_4_dr=0; seg_5_dr=0; seg_6_dr=0; break; case 2: //显示"2" seg_0_dr=1; seg_1_dr=0; seg_2_dr=1; seg_3_dr=1; seg_4_dr=1; seg_5_dr=1; seg_6_dr=0; break; case 3: //显示"3" seg_0_dr=1; seg_1_dr=1; seg_2_dr=0; seg_3_dr=1; seg_4_dr=1; seg_5_dr=1; seg_6_dr=0; break; case 4: //显示"4" seg_0_dr=1; seg_1_dr=1; seg_2_dr=0; seg_3_dr=0; seg_4_dr=1; seg_5_dr=0; seg_6_dr=1; break; case 5: //显示"5" seg_0_dr=0; seg_1_dr=1; seg_2_dr=0; seg_3_dr=1; seg_4_dr=1; seg_5_dr=1; seg_6_dr=1; break; case 6: //显示"6" seg_0_dr=0; seg_1_dr=1; seg_2_dr=1; seg_3_dr=1; seg_4_dr=1; seg_5_dr=1; seg_6_dr=1; break; case 7: //显示"7" seg_0_dr=1; seg_1_dr=1; seg_2_dr=0; seg_3_dr=0; seg_4_dr=0; seg_5_dr=1; seg_6_dr=0; break; case 8: //显示"8" seg_0_dr=1; seg_1_dr=1; seg_2_dr=1; seg_3_dr=1; seg_4_dr=1; seg_5_dr=1; seg_6_dr=1; break; case 9: //显示"9" seg_0_dr=1; seg_1_dr=1; seg_2_dr=0; seg_3_dr=1; seg_4_dr=1; seg_5_dr=1; seg_6_dr=1; break; case 10: //什么也不显示,空 seg_0_dr=0; seg_1_dr=0; seg_2_dr=0; seg_3_dr=0; seg_4_dr=0; seg_5_dr=0; seg_6_dr=0; break; } } void delay1(unsigned int de) { unsigned int t; for(t=0;t (6)小结: 有的朋友一旦发现我在定时中断里用了delay1(50)这个死延时,肯定会有疑问。其实delay1(50)这个只是一个小延时,对于大部分简单的系统是没有任何影响。有兴趣的朋友可以尝试把delay(50)这个延时改成计数延时方式,但是我觉得这个涉及到显示的效果,估计改起来没有那么容易。真正要开发复杂的,实时性要求非常高的系统,建议不要用这种动态扫描的方式。大家不要急,我后续的章节中还会提供很多种数码管驱动方式给大家参考。 (7)下集预告: 利用74HC595辅助来动态扫描数码管。 (未完待续,下节更精彩,不要走开哦) |
|
|
|
向鸿哥学习!!!!!!!!
|
|
|
|
|
|
牛人呀!!!!!!!!!!
|
|
|
|
|
|
一代天骄-------------------吴哥!!!!!!!!
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
期待
|
|
|
|
|
|
一晚上时间,仔细品读了吴工的程序,钦佩他不辞辛苦的一点点的写了那么多,这种无私的精神更值得我们去学习,同时从吴工的程序风格里看到了他工程师之路走来不易,我是很理解他说的“别人皆睡我独醒”的这种状况,对于电子工程师来说,每接一个新的方案,有很大的压力(不仅有客户给的时间上的还有新技术上的),每一个新的方案都是一个新的挑战,挑战完了,有重生的感觉,技术上也会上一个台阶。虽然,然而我认为只有面对新方案有心跳有欲望的工程师,才能最终成为大师。这些不是感觉不是玩玩开发板的人可以体会到的。我会一直关注这个帖子的,吴工我想和你说,在这里,你不是一个人在努力,我们都会陪伴在你身边。再次说声,您辛苦了.....
|
|
|
|
|
|
鸿哥V5
|
|
|
|
|
|
只有小组成员才能发言,加入小组>>
求解外围电路实现的是4脚给持续低电平复位并正常工作,高电平不工作的原因
2076 浏览 1 评论
3489 浏览 3 评论
PIC1946程序有一个变量在运行过程中恢复初始值其他变量保持不变
2329 浏览 2 评论
2754 浏览 0 评论
PIC16F1825的RC5引脚,在主程序中操作无效,在中断中可以改变是为什么?
4012 浏览 5 评论
960浏览 0评论
用XC8编译PIC18F25K80时提示下面Error,求怎么解决这个问题
6345浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-24 06:04 , Processed in 1.210094 second(s), Total 103, Slave 88 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号