本帖最后由 zhangshiwei 于 2024-6-25 18:12 编辑
2024.06.19
第十集
学习心得:数码管的动态显示
(1)熟悉并掌握数码管动态刷新的原理,熟悉如何设计实现4位数码管分别点亮“1、2、3、4”的程序;
动态显示驱动
数码管动态显示接口是单片机中应用最为广泛的一种显示方式之一,动态驱动是将所有数码管的8个显示笔划"a,b,c,d,e,f,g,dp"的同名端连在一起,另外为每个数码管的公共极COM增加位选通控制电路,
位选通由各自独立的I/O线控制,当单片机输出字形码时,所有数码管都接收到相同的字形码,但究竟是哪个数码管会显示出字形,取决于单片机对位选通COM端电路的控制,
所以我们只要将需要显示的数码管的选通控制打开,该位就显示出字形,没有选通的数码管就不会亮。通过分时轮流控制各个数码管的的COM端,就使各个数码管轮流受控显示,这就是动态驱动。
在轮流显示过程中,每位数码管的点亮时间为1~2ms,由于人的视觉暂留现象及发光二极管的余辉效应,尽管实际上各位数码管并非同时点亮,但只要扫描的速度足够快,
给人的印象就是一组稳定的显示数据,不会有闪烁感,动态显示的效果和静态显示是一样的,能够节省大量的I/O端口,而且功耗更低。
[size=1.2em]
[size=1.2em]数码管驱动方式分类
动态数码管驱动方式:扫描方式 共阴数码管扫描:一个低电平其他全部为高电平,循环变换 共阳数码管扫描:一个高电平其他全部为低电平,循环变换
数码管代码示例头文件
- #ifndef __QYQ_MODULE_SMG_H_
- #define __QYQ_MODULE_SMG_H_
- #include "chip_include.h"
- #ifdef __QYQ_MODULE_SMG_C_
- #define QYQ_MODULE_SMG_EXT extern
- #else
- #define QYQ_MODULE_SMG_EXT
- #endif
-
- typedef struct
- {
- void (*qyq_module_smg_config_writedat)(uint8_t dat); // 写数据
- void (*qyq_module_smg_config_writeaddr)(uint8_t addr); // 写地址,从0编号开始写
- void (*qyq_module_smg_config_delay)(void); // 如果采用系统延迟,不需要适配延迟函数,否则需要延迟函数
- uint8_t qyq_module_smg_number; // 数码管数量
- uint8_t qyq_module_smg_off_value; // 数码管全部关闭值
- uint8_t qyq_module_smg_data_count; // 数码管计数器
- uint8_t *qyq_module_smg_data_value; // 数码管显示buf
- } qyq_module_smg_config_t;
-
- // 功能
- typedef struct qyq_module_smg_type
- {
- qyq_module_smg_config_t *qyq_module_smg_config;
-
- int8_t (*qyq_module_smg_write)(struct qyq_module_smg_type *this, uint8_t smg_id, uint8_t value);
- int8_t (*qyq_module_smg_scan)(struct qyq_module_smg_type *this);
- } qyq_module_smg_type_t;
-
- QYQ_MODULE_SMG_EXT int8_t qyq_module_smg_create(qyq_module_smg_type_t *this, qyq_module_smg_config_t *qyq_module_smg_config);
- #endif
复制代码
源文件
- #define __QYQ_MODULE_SMG_C_
- #include "qyq_module_smg.h"
-
- static uint8_t qyq_module_smg_font[][2] = {
- {0xFF, 0},
- {'0', 0x3F}, //"0"
- {'1', 0x06}, //"1"
- {'2', 0x5B}, //"2"
- {'3', 0x4F}, //"3"
- {'4', 0x66}, //"4"
- {'5', 0x6D}, //"5"
- {'6', 0x7D}, //"6"
- {'7', 0x07}, //"7"
- {'8', 0x7F}, //"8"
- {'9', 0x6F}, //"9"
- {'A', 0x77}, //"A"
- {'B', 0x7C}, //"B"
- {'C', 0x39}, //"C"
- {'D', 0x5E}, //"D"
- {'E', 0x79}, //"E"
- {'F', 0x71}, //"F"
- {'H', 0x76}, //"H"
- {'L', 0x38}, //"L"
- {'n', 0x37}, //"n"
- {'U', 0x3E}, //"u"
- {'P', 0x73}, //"P"
- {'O', 0x5C}, //"o"
- {'-', 0x40}, //"-"
- };
-
- static uint8_t qyq_module_smg_getfont(uint8_t value)
- {
- uint8_t i = 0;
- for (i = 0; i < sizeof(qyq_module_smg_font) / 2; i++)
- {
- if (value == qyq_module_smg_font[i][0])
- {
- return i;
- }
- }
- return 0;
- }
-
- static int8_t qyq_module_smg_scan(qyq_module_smg_type_t *this)
- {
- if (this == null)
- {
- return -1;
- }
-
- this->qyq_module_smg_config->qyq_module_smg_config_writedat(this->qyq_module_smg_config->qyq_module_smg_off_value);
- this->qyq_module_smg_config->qyq_module_smg_config_writeaddr(this->qyq_module_smg_config->qyq_module_smg_data_count);
- this->qyq_module_smg_config->qyq_module_smg_config_writedat(qyq_module_smg_font[qyq_module_smg_getfont(this->qyq_module_smg_config->qyq_module_smg_data_value[this->qyq_module_smg_config->qyq_module_smg_data_count])][1]);
- if (this->qyq_module_smg_config->qyq_module_smg_config_delay != null)
- {
- this->qyq_module_smg_config->qyq_module_smg_config_delay();
- }
- this->qyq_module_smg_config->qyq_module_smg_data_count++;
- if (this->qyq_module_smg_config->qyq_module_smg_data_count >= this->qyq_module_smg_config->qyq_module_smg_number)
- {
- this->qyq_module_smg_config->qyq_module_smg_data_count = 0;
- }
-
- return 0;
- }
-
- static int8_t qyq_module_smg_write(qyq_module_smg_type_t *this, uint8_t smg_id, uint8_t value)
- {
- if (this == null)
- {
- return -1;
- }
-
- this->qyq_module_smg_config->qyq_module_smg_data_value[smg_id] = value;
-
- return 0;
- }
-
- int8_t qyq_module_smg_create(qyq_module_smg_type_t *this, qyq_module_smg_config_t *qyq_module_smg_config)
- {
- if (this == null)
- {
- return -1;
- }
- if (qyq_module_smg_config == null)
- {
- return -1;
- }
-
- this->qyq_module_smg_config = qyq_module_smg_config;
- this->qyq_module_smg_config->qyq_module_smg_data_count = 0;
- qyq_module_smg_font[0][1] = this->qyq_module_smg_config->qyq_module_smg_off_value;
-
- this->qyq_module_smg_scan = qyq_module_smg_scan;
- this->qyq_module_smg_write = qyq_module_smg_write;
-
- return 0;
- }
复制代码
(2)数码管驱动的控制原理
需要注意数码管驱动的方式,并且注意延时的设计,一般是给定1ms的延时,并且需要保证结束一个循环不能大于20ms,根据人的视觉暂留效应(也就是说人的视觉不容易分辨出50Hz以上的动态刷新);
(3)如何同时点亮8位数码管
针对数码管显示的对应数值确定,即段码
程序设计思路
什么是段选、什么是位选?段选 就是 数码管各个发光二极管显示的段 组成的字 位选 就是 公共端引出的引脚,选择哪个数码管来显示 共阴、共阳 0~F 的段选显示 共阴数码管亮 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0 1 2 3 4 5 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 6 7 8 9 A B 0x39, 0x5e, 0x79, 0x71, 0x00, C D E F 无显示 共阳数码管亮 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0 1 2 3 4 5 0x82, 0xF8, 0x80, 0x90, 0x88, 0x83, 6 7 8 9 A B 0xC6, 0xA1, 0x86, 0x8E, 0xFF, C D E F 无显示 消影用人眼余晖,延时来 让人感觉数码管动态显示。 总结:了解了数码管如何实现动态的显示,学会每一位的数码管的任意内容的显示;如何实现数码管的动态显示,程序上去设计如何驱动数码管。
|