历史上的今天
今天是:2025年04月03日(星期四)
2020年04月03日 | 静态和动态控制数码管
2020-04-03 来源:eefocus
1 什么是数码管
1.1 几方面看数码管
(1)外观。
(2)作用:数码管是显示器件,用来显示数字的。
(3)分类:单个(1位)、联排(2位、4位、8位)。
1.2 工作原理
(1)亮灭原理(其实就是内部的照明LED)。
(2)显示数字(甚至文字)原理:利用内部的LED的亮和灭让外部的组成数字的笔画显示或者不显示,人看到的就是不同的数字。
1.3 共阳极和共阴极数码管
(1)驱动方法的差异。必须清楚一个数码管内部的8颗LED是独立驱动的。如果8颗LED的正极接在一起接到VCC上(负极分别接到单片机的不同引脚),这种接法就叫共阳极。反之如果8颗LED负极接在一起然后接到GND(正极就分别接到单片机的不同引脚)就叫共阴极。两种接法都可以驱动数码管显示,但是用来显示的单片机程序不同(共阳极时单片机0是亮,共阴极时单片机的1是亮)。
(2)驱动电流需求差异。数码管(其实就是LED)如果按照共阳极接法则单片机可以直接驱动显示,如果按照共阴极接法则单片机不能直接驱动,因为单片机的IO口提供的电流大小不够驱动数码管内部的LED显示,需要外部电路来提供一个大电流驱动的芯片来解决(上个课程中的74HC573就是起的这个作用)。
1.4 静态和动态数码管
(1)用途差异:静态方式用于驱动单独的数码管,动态方式用于驱动联排数码管。
(2)电路接法差异。
2 静态数码管的初步驱动
2.1 原理图分析

2.2 接线
(1)结论:单片机的P0端口直接接到共阳极数码管的阴极。因此单片机输出0则数码管亮,输出1数码管灭。实验验证结果ok。
2.3 编程点亮
(1)P0 = 0x0; 8段全亮
(2)P0 = 0xff; 8段全灭
(3)P0 = 0x0f; 4段亮4段灭
2.4 验证原理图中数码管段号是否正确
(1)数码管的8段实际是8个LED,分别对应IO端口P0的8个引脚(P0.0、P0.1····P0.7),那么谁对应谁呢?
(2)理论上可以分析原理图和接线方法去推测这个对应关系(数码管的段码),但是实际上理论分析的经常不对。
(3)实战中一般都是自己写代码去测试的。
P0 = 0xfe; // 11111110 P0.0输出0 实测对应a
P0 = 0xfd; // 11111101 P0.1输出0 实测对应b
P0 = 0xfb; // 11111011 P0.2输出0 实测对应c
P0 = 0xf7; // 11110111 P0.3输出0 实测对应d
P0 = 0xef; // 11101111 P0.4输出0 实测对应e
P0 = 0xdf; // 11011111 P0.5输出0 实测对应f
P0 = 0xbf; // 10111111 P0.6输出0 实测对应g
P0 = 0x7f; // 01111111 P0.7输出0 实测对应dp
注意:P0端口的8个二进制位中,高位对应P0.7,而低位对应P0.0
2.5 思考:数码管如何显示数字?
(1)数码管显示数字,其实就是让数码管亮相应的几个段。其实就是让IO端口的相应引脚输出0(其余引脚输出1),其实就对应一个8位的二进制数。
(2)结论就是:P0端口输出一个合适的字节数,数码管就会显示相应的数字。每个数字都会有一个对应的8位二进制数,关键就是要得到这8位二进制数。
#include void main(void) { // 测试数码管是否能点亮 //P0 = 0x00; // P0输出全0,数码管应该8段全亮。 /* // 测试数码管的段码 P0 = 0xfe; // 11111110 P0.0输出0 实测对应a P0 = 0xfd; // 11111101 P0.1输出0 实测对应b P0 = 0xfb; // 11111011 P0.2输出0 实测对应c P0 = 0xf7; // 11110111 P0.3输出0 实测对应d P0 = 0xef; // 11101111 P0.4输出0 实测对应e P0 = 0xdf; // 11011111 P0.5输出0 实测对应f P0 = 0xbf; // 10111111 P0.6输出0 实测对应g P0 = 0x7f; // 01111111 P0.7输出0 实测对应dp */ } 3 静态数码管显示数字 3.1 数字编码(段码)的获取 要显示的数字 数码管亮的LED 段码二进制 十六进制 0 abcdef 11000000 0xC0 1 bc 11111001 0xf9 2 abdeg 10100100 0xA4 3 abcdgh 10110000 0xb0 4 bcfg 10011001 0x99 5 acdfg 10010010 0x92 6 acdefg 10000010 0x82 7 abc 11111000 0xf8 8 abcdefg 10000000 0x80 9 abcdfg 10010000 0x90 A abcefg 10001000 0x88 b cdefg 10000011 0x83 C adef 11000110 0xc6 d bcdeg 10100001 0xA1 E adefg 10000110 0x86 F aefg 10001110 0x8e 3.2 编程验证 P0 = 0xC0; 3.3 结论 (1)不同的数码管数字编码(段码)表完全可能不同。 (2)同一个数码管接线方式不同编码表可能完全不同。 (3)硬件确定后可通过调试的方法来实验确定编码表。 4 让数码管依次显示0到f (1)笨办法:分状态。 (2)升级方法:使用数组。 (3)总结 C语言的不同特性用在不同地方,可以简化编程; C语言数组从0开始,注意不能越界,这个很重要。 #include void delay(void) { unsigned char i, j, k; for (i=0; i<100; i++) for (j=0; j<100; j++) for (k=0; k<20; k++); } void main(void) { unsigned char val[16] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e}; unsigned char i = 0; while (1) { for (i=0; i<16; i++) { P0 = val[i]; delay(); } } } /* void main(void) { while (1) { P0 = 0xc0; // 0 delay(); P0 = 0xf9; // 1 delay(); P0 = 0xa4; // 2 delay(); P0 = 0xb0; // 3 delay(); P0 = 0x99; // 4 delay(); P0 = 0x92; // 5 delay(); P0 = 0x82; // 6 delay(); P0 = 0xf8; // 7 delay(); P0 = 0x80; // 8 delay(); P0 = 0x90; // 9 delay(); P0 = 0x88; // A delay(); P0 = 0x83; // b delay(); P0 = 0xc6; // C delay(); P0 = 0xa1; // d delay(); P0 = 0x86; // E delay(); P0 = 0x8e; // F delay(); } } */ 5 动态数码管 5.1 静态数码管驱动方式的缺陷 (1)优势是驱动简单直接,好编程。 (2)缺陷是每个数码管需要1个端口,单片机的端口不够用。 解决办法:使用动态方式驱动多个数码管 5.2 什么是动态数码管 (1)数码管还是原来的数码管(共阳极或共阴极均可)记住:数码管有2端:COM端和段码端。 (2)段码一侧还是接一个单片机端口。 (3)COM(共极)接单片机一个IO口,多个联排数码管的COM共同接一个IO端口。 分析对比静态和动态数码管,发现本质区别是:静态数码管中只要给了段码数码管就一定工作(显示只取决于段码端),动态数码管中段码端给了段码值后还需要COM端配合才能点亮数码管。 5.3 动态数码管如何工作 (1)在某一特定时间段中,联排数码管中只有一个数码管在工作,其他均在休息(不工作)。 (2)COM端选择哪个数码管工作,段码端输出这个数码管要显式的数字的段码;延时;COM端选择下一个数码管工作,同时段码端改输出这个数码管要显示的数字的段码;延时;COM端选择下一个数码管工作······ (3)快速切换工作的数码管,则人看到的是所有的数码管都在亮(其实亮度是比静态驱动低的)。 (4)动态数码管利用了人眼的视觉暂留。 搞清楚2点: 第一,宏观上所有的数码管都是同时亮的,所以人以为所有数码管同时工作,所以多个数码管可以合在一起来显示(譬如显示12345678) 第二,微观上数码管是依次亮的,我们可以给不同的数码管送不同的段码,所以不同的数码管可以显示不同的数字。所以相当于8个数码管的显示是独立的。 6 动态数码管显示编程实战 6.1 先实验得出数码管的段码表 (1)接线确定:段码端接P0,COM端接P2端口。 (2)COM端选择一个数码管亮:P2.0-P2.7随便选1个输出0,其余输出1。 (3)段码端给不同的值来测试得到段码表 第一步:先测试P0.0-P0.7和abcdefg.怎么对应的? 实验测试结论:P2.0对应最左边一个数码管(P2.7对应最右边一个数码管)、P0.0对应a(P0.1对应b·····P0.7对应dp) 0 0x3f 1 0x06 2 0x5b 3 0x4f 4 0x66 5 0x6d 6 0x7d 7 0x07 8 0x7f 9 0x6f A 0x77 b 0x7c C 0x39 d 0x5e E 0x79 F 0x71 段码表:0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71。 6.2 目标:8个联排数码管一起显示12345678 (1)编程思路:先选中第1数码管,然后段码端送1的段码,然后延时一会儿;然后切换选中第2数码管,然后段码端送2的段码,然后延时一会儿;····直到第8个数码管显示完为一个周期;死循环这个周期。 (2)实验结论: 1、延时时间太长,数字会闪动。 2、把时间改短后发现有3个问题:第一个是亮的不够亮,第二个是暗的不够暗,第三个是其中一个数字(1)显示明显有问题。 解决方案就是在每个数码管亮完要切换下一个数码管时消隐。
上一篇:51单片机之动态数码管显示
下一篇:51单片机的静态数码管
史海拾趣
|
我用的是TINNY 2313,它的定时器0溢出中断向量是7,我用轮循环的方式是正常的,用中断方式不行.下面是代码,帮忙看下,解决了分全给. #include #include //volatile unsigned int cnt=0; //int ss _at_ 0x00; int main() { & ...… 查看全部问答> |
|
wince 5.0 下取 SD 卡的路径 FindFirstFlashCard 这个函数 在 不支持CE 还有一个 FindFirstStore 说是支持但,需要Storeapi.lib 而我这竟然没有。也不知道咋回事 我只需要得到SD 卡的根目录。就成。。 怎么做。。大家帮忙啊。。 … 查看全部问答> |
|
在Cadence下做spectreVerilog混合仿真,但出现Error:problem encountered while executing verilog,但我查了一下,我的版本的verilog已经装好了的,$verilog a.v也是正常的,怎么解决啊?… 查看全部问答> |
|
MCU是STM32,用FSMC连接TFT LCD(LGDP4551),LCD接口模式采用MCU模式。现在背光已经点亮了,但显示其他颜色、画线、显示字符……都不行,可能会是什么原因呢?… 查看全部问答> |
|
前段日子甲骨文公司宣布了Java SE 7的首个正式版,这也是自2006年12月Sun发布Java SE 6以来的首个重要版本更新。那么经过一段时间的使用,java 7是否能带给java程序员意想不到的使用效果呢。下面就跟随福州卓跃教育就java培训分析java 7的临世。 ...… 查看全部问答> |




