雾山大叔 发表于 2025-2-22 11:04:12

Ai8051U学习之旅(3)- 数码管显示

一、前言数码管显示是常见的显示器件,最常用的是家电、消费电子上,学会数码管驱动,对于理解数字显示、定时器运用、IO操作都有帮助,今天就先整理一下数码管学习笔记。二、硬件电路2.1 数码管2.1.1 数码管的基本结构1) 七段数码管:ü最常见的类型,包含7个LED段(a-g),排列成“日”字形。ü额外的小数点(DP)段,共8个控制引脚。ü每个段对应一个LED,通过通电点亮。2) 共阳(Common Anode)与共阴(Common Cathode):ü共阳:所有LED的阳极连接在一起,接高电平(VCC),阴极分别控制。ü共阴:所有LED的阴极连接在一起,接地(GND),阳极分别控制。2.1.2 工作原理1)显示原理:ü通过给不同段通电组合显示数字(如数字“0”需要a、b、c、d、e、f段亮)。ü需配合限流电阻(通常100-500Ω)保护LED。2)编码方式:ü每个数字对应一个二进制或十六进制编码(段码表)。ü例如,共阴数码管显示“0”的段码为 0x3F(二进制 00111111)。2.1.3 驱动方式1、静态驱动:n每个数码管独立连接控制引脚,适合少量显示。n优点:亮度稳定;缺点:占用引脚多。2、动态扫描(多路复用):n多个数码管共用段引脚,通过快速切换公共端分时显示。n优点:节省引脚;缺点:需较高刷新频率(>60Hz)避免闪烁。2.2 数码管驱动电路正常情况下,MCU的驱动电路没有那么大或IO不够多时,就需要外围驱动IC来做数码管的驱动电路,最常用的是串转并芯片,AI8051U开发板上用的是经典的74HC595,如下图:图1 数码管电路图   74HC595是一个8位串行输入、平行输出的位移缓存器:平行输出为三态输出。在SCK的上升沿,单行数据由SDL输人到内部的8位位移缓存器,并由Q7‘输出,而平行输出则是在LCK的上升沿将在8位位移缓存器的数据存人到8位平行输出缓存器。当串行数据输人端OE的控制信号为低使能时,平行输出端的输出值等于平行输出缓存器所存储的值。而当OE为高电位,也就是输出关闭时,平行输出端会维持在高阻抗状态。串行输入,并行输出。表1 74HC595引脚定义三、软件设计       知道了驱动原理,接下来就是根据原理写程序,也就是如果让HC595发数据,如果让数据管显示。先简单的显示12345678   3.1 数码管驱动   Dev_Segled.c/*----------------------------------------------------------------------------------------------------------------------
* Copyright(c) 2024, Mark Xu Work Studio R&D Department. All rights reserved.
* 文件名称 : Dev_Segled.c
* 文件版本 : V1.0.0
* 功能描述 : 数码管应用模块
* 创建人员 : Mark Xu
* 创建日期 : 2025/02/17
----------------------------------------------------------------------------------------------------------------------*/

#include "Dev_Segled.h"                        

//----------------------------------------------------------------------------------------------------------------------
// 配置文件                                       
//----------------------------------------------------------------------------------------------------------------------
#define SEG_COM_MAX                              (8)                //8位数码管

//----------------------------------------------------------------------------------------------------------------------
// 类型重定义                                       
//----------------------------------------------------------------------------------------------------------------------

//----------------------------------------------------------------------------------------------------------------------
// 常量、宏   
//----------------------------------------------------------------------------------------------------------------------
U8C segCode[] = {                     //标准字库
//   0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
    0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
//black-   H    J    K    L    N    o   P    U   t    G    Q    r   M    y
    0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
    0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46};    //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1

U8C segCom = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};      //位码

//----------------------------------------------------------------------------------------------------------------------
// 局部变量
//----------------------------------------------------------------------------------------------------------------------
static U8s_u8DisBuff = {1, 2, 3, 4, 5, 6, 7, 8};                //显示缓存
static U8s_u8ComLoopCnt = 0;                                        //轮询值
//----------------------------------------------------------------------------------------------------------------------
// 全局变量
//----------------------------------------------------------------------------------------------------------------------

//----------------------------------------------------------------------------------------------------------------------
// 本地函数声明
//----------------------------------------------------------------------------------------------------------------------


/*----------------------------------------------------------------------------------------------------------------------
* 函数名称 :void Segled_Init(void)
* 功能描述 :数码管程序初始化
* 入口参数 :无
* 出口参数 :无
* 备注说明 :无
----------------------------------------------------------------------------------------------------------------------*/
void Segled_Init(void)
{

}


/*----------------------------------------------------------------------------------------------------------------------
* 函数名称 :void HC595_SendDat(U8 i_Dat)
* 功能描述 :传输数据
* 入口参数 :i_Dat - 要传输的8位数据
* 出口参数 :无
* 备注说明 :无
----------------------------------------------------------------------------------------------------------------------*/
void HC595_SendDat(U8 i_Dat)
{
      U8 i;
      for (i=0; i<8; i++)
      {
                if (i_Dat & 0x80)      //先传输高位      
                {
                        HC595_DAT_HI();
                }
                else
                {
                        HC595_DAT_LO();
                }

                i_Dat <<= 1;

                HC595_SRCLK_HI();
                HC595_SRCLK_LO();
      }
}

/*----------------------------------------------------------------------------------------------------------------------
* 函数名称 :void Segled_AllOff(void)
* 功能描述 :关闭数码管
* 入口参数 :无
* 出口参数 :无
* 备注说明 :无
----------------------------------------------------------------------------------------------------------------------*/
void Segled_AllOff(void)
{
      U8 i = 0;
      for (i=0; i<SEG_COM_MAX; i++)
      {
                s_u8DisBuff = 0x00;
      }
}      Dev_Segled.h/*----------------------------------------------------------------------------------------------------------------------
* Copyright(c) 2025, Mark Xu Work Studio R&D Department. All rights reserved.
* 文件名称 : Dev_Segled.h
* 文件版本 : V1.0.0
* 功能描述 : 数码管功能头文件
* 创建人员 : Mark Xu
* 创建日期 : 2025/02/17
----------------------------------------------------------------------------------------------------------------------*/
#ifndef      __DEV_SEGLED_H__
#define      __DEV_SEGLED_H__

#include "includes.h"

//----------------------------------------------------------------------------------------------------------------------
// 常量、宏
//----------------------------------------------------------------------------------------------------------------------

//----------------------------------------------------------------------------------------------------------------------
// 类型重定义                                    
//----------------------------------------------------------------------------------------------------------------------

//----------------------------------------------------------------------------------------------------------------------
// 全局变量
//----------------------------------------------------------------------------------------------------------------------

//----------------------------------------------------------------------------------------------------------------------
// 全局函数
//----------------------------------------------------------------------------------------------------------------------
#if (DEV_SEGLED_EN)
      extern void Segled_Init(void);
      extern void Segled_DeInit(void);
      extern void Segled_PollProc(void);
#else
      #define Segled_Init()
      #define Segled_DeInit()
      #define Segled_PollProc()
#endif

#endif //#ifndef      __DEV_SEGLED_H__

在主程序中调用void Segled_PollProc(void);这个函数即可,如下所示:






雾山大叔 发表于 2025-2-22 11:06:55

1、为了简单期间,直接在main函数中轮询调用,当然设计了标志,每1ms调用一次
2、存在缺点:如果大循环中存在的事件比较大,浪费的时间比较久,则可能影响数码管的显示效果,这时可能需要抢占式任务或直接在定时器中调用
3、下步计划:试一下RTC,作一个小闹钟,配合按键等,可以直接用

雾山大叔 发表于 2025-2-22 11:14:30

今天实验的工程,所有源文件均在工程中,
注意:工程名没有更改,当然这个不影响实验的结果{:4_167:}
页: [1]
查看完整版本: Ai8051U学习之旅(3)- 数码管显示