单片机:实现数码管动态显示(0~99999999)74hc138驱动(附带源码)

单片机实现数码管动态显示(0~99999999)并使用74HC138驱动

在本项目中,我们将介绍如何在单片机上实现一个八位数码管(显示0到99999999)的动态显示,并使用74HC138解码器来控制数码管的选择。74HC138是一种常见的3线至8线解码器,可以通过它来控制8个数码管的显示位置,使得我们能够动态地切换每个数码管并显示相应的数字。

1. 项目需求分析

目标:
  1. 八位数码管显示:在8个数码管上动态显示一个8位数字,支持0到99999999的数字显示。
  2. 使用74HC138解码器驱动:通过74HC138解码器控制8个数码管的位置,实现动态显示。
  3. 数码管显示内容:每个位数显示0-9的数字,通过动态扫描显示多个数字。
功能需求:
  1. 动态扫描显示:使用定时器中断周期性地切换数码管显示的位置。
  2. 数字显示:控制数码管显示对应的数字。
  3. 使用74HC138控制显示:通过74HC138的选择端(A、B、C)控制数码管的显示位置。
  4. 简易数字递增:为了方便观察效果,模拟数字从0到99999999递增并在数码管上显示。

2. 硬件设计

2.1 单片机选择

选择51系列单片机(如AT89C51)作为开发平台,原因是该单片机具有足够的I/O端口,适合控制多个数码管,并且资源较为丰富,便于开发。

2.2 数码管与74HC138解码器连接
  • 74HC138解码器:它有3个输入端(A、B、C)用于选择8个输出端(Y0至Y7)。每个输出端对应一个数码管,输入端控制哪个数码管被选中。
  • 数码管:使用8个共阴或共阳的七段数码管,通过单片机的端口控制每个数码管的段选。
  • 连接设计
    • 74HC138的输出端连接到每个数码管的位选端。
    • 每个数码管的段选端连接到单片机的GPIO口。
2.3 数码管段选数据表

每个数字(0-9)对应的七段数码管的显示,可以使用一个数组来表示每个数字的段选状态(即每个数字的显示对应于7个段的开关状态)。

cpp 复制代码
// 数码管段选数据(共阴,0表示亮,1表示灭)
unsigned char code digit[] = {
    0x3F,  // 0
    0x06,  // 1
    0x5B,  // 2
    0x4F,  // 3
    0x66,  // 4
    0x6D,  // 5
    0x7D,  // 6
    0x07,  // 7
    0x7F,  // 8
    0x6F   // 9
};

3. 软件设计

3.1 定时器中断

使用定时器中断来实现数码管的动态扫描。定时器定时触发中断,每次中断发生时,我们依次切换不同的数码管进行显示。

3.2 代码实现
cpp 复制代码
#include <reg51.h>  // 包含51系列单片机的寄存器定义文件

// 数码管段选数据(共阴,0表示亮,1表示灭)
unsigned char code digit[] = {
    0x3F,  // 0
    0x06,  // 1
    0x5B,  // 2
    0x4F,  // 3
    0x66,  // 4
    0x6D,  // 5
    0x7D,  // 6
    0x07,  // 7
    0x7F,  // 8
    0x6F   // 9
};

// 定义74HC138的输入端口(A, B, C)
sbit A = P3^0;  // 74HC138的A端连接到P3.0
sbit B = P3^1;  // 74HC138的B端连接到P3.1
sbit C = P3^2;  // 74HC138的C端连接到P3.2

// 数码管的段选端口(假设连接在P2端口)
sbit SEG_A = P2^0;
sbit SEG_B = P2^1;
sbit SEG_C = P2^2;
sbit SEG_D = P2^3;
sbit SEG_E = P2^4;
sbit SEG_F = P2^5;
sbit SEG_G = P2^6;

// 定义一个8位数字
unsigned long display_number = 0;  // 当前显示的数字,最大可显示到99999999

// 数码管显示函数
void display_digit(unsigned char position, unsigned char number) {
    // 根据数字选择相应的段选数据
    unsigned char seg = digit[number];  // 获取数字对应的段选数据
    
    SEG_A = (seg >> 0) & 0x01;
    SEG_B = (seg >> 1) & 0x01;
    SEG_C = (seg >> 2) & 0x01;
    SEG_D = (seg >> 3) & 0x01;
    SEG_E = (seg >> 4) & 0x01;
    SEG_F = (seg >> 5) & 0x01;
    SEG_G = (seg >> 6) & 0x01;
}

// 选择要显示的数码管位置(通过74HC138)
void select_digit(unsigned char position) {
    // 根据位置选择对应的数码管
    switch (position) {
        case 0: A = 0; B = 0; C = 0; break;
        case 1: A = 0; B = 0; C = 1; break;
        case 2: A = 0; B = 1; C = 0; break;
        case 3: A = 0; B = 1; C = 1; break;
        case 4: A = 1; B = 0; C = 0; break;
        case 5: A = 1; B = 0; C = 1; break;
        case 6: A = 1; B = 1; C = 0; break;
        case 7: A = 1; B = 1; C = 1; break;
    }
}

// 定时器中断服务函数
void Timer0_ISR(void) interrupt 1 {
    static unsigned char pos = 0;  // 当前显示的数码管位置
    static unsigned char digits[8];  // 存储显示的每一位数字

    // 将当前数字转换为8位数字数组
    digits[0] = display_number % 10;
    digits[1] = (display_number / 10) % 10;
    digits[2] = (display_number / 100) % 10;
    digits[3] = (display_number / 1000) % 10;
    digits[4] = (display_number / 10000) % 10;
    digits[5] = (display_number / 100000) % 10;
    digits[6] = (display_number / 1000000) % 10;
    digits[7] = (display_number / 10000000) % 10;

    // 选择并显示当前数码管
    select_digit(pos);  // 选择当前数码管
    display_digit(pos, digits[pos]);  // 显示对应的数字

    // 更新显示的数码管位置
    pos++;
    if (pos == 8) pos = 0;  // 8个数码管显示完后重新从第一个开始
}

// 定时器初始化
void Timer0_Init() {
    TMOD = 0x01;  // 定时器0模式1,16位定时器
    TH0 = 0xFC;   // 设置定时器初值
    TL0 = 0x66;
    ET0 = 1;      // 使能定时器0中断
    EA = 1;       // 开启总中断
    TR0 = 1;      // 启动定时器0
}

void main() {
    // 初始化定时器0
    Timer0_Init();

    // 主循环,模拟数字递增
    while (1) {
        display_number++;  // 模拟数字递增
        if (display_number > 99999999) {
            display_number = 0;  // 数字达到最大值后重置
        }
    }
}

4. 代码解释

  1. 数码管段选数据digit数组包含0到9对应的七段数码管显示数据,每个数字对应一个字节,每个字节的7个位表示一个七段数码管的段(a-g)的开关状态。0表示该段亮,1表示该段灭。

  2. display_digit函数:此函数负责根据给定的位置(0-7)和数字,控制相应的段选端口(a-g)显示对应的数字。

  3. select_digit函数:此函数控制74HC138解码器的选择端A、B、C的状态,从而选择哪个数码管进行显示。

  4. Timer0_ISR函数 :定时器中断服务函数,每次定时器中断时,它都会更新当前显示的数码管,并通过select_digitdisplay_digit函数来显示数字。

  5. Timer0_Init函数:初始化定时器,设置为16位定时器模式,定时器溢出时会产生中断,从而周期性地更新数码管的显示。

  6. 主程序 :在主程序中,我们通过递增display_number来模拟数字从0到99999999的递增,并在数码管上动态显示。

5. 总结

通过定时器中断与74HC138解码器,我们实现了8个数码管的动态显示,显示范围为0到99999999的数字。每次定时器中断触发时,我们通过select_digit选择显示的数码管,并通过display_digit显示数字。这个方法有效地实现了多个数码管的动态显示,同时利用74HC138简化了数码管的控制。

相关推荐
m0_7482409126 分钟前
OpenMV与STM32通信全面指南
stm32·单片机·嵌入式硬件
Cchengzu3 小时前
阿里巴巴2017实习生笔试题(二)
stm32·单片机·嵌入式硬件
重生之我是数学王子6 小时前
单片机 STM32入门
stm32·单片机·嵌入式硬件
qq_4597300310 小时前
4-3 MCU中ARM存储器的作用
arm开发·单片机·嵌入式硬件
重生之我是数学王子13 小时前
点亮核心板小灯 STM32U575
stm32·单片机·嵌入式硬件
end_SJ13 小时前
初学stm32 --- 定时器中断
stm32·单片机·嵌入式硬件
南城花随雪。15 小时前
单片机:实现信号发生器(附带源码)
单片机·嵌入式硬件
灵槐梦17 小时前
【速成51单片机】2.点亮LED
c语言·开发语言·经验分享·笔记·单片机·51单片机
三月七(爱看动漫的程序员)17 小时前
HiQA: A Hierarchical Contextual Augmentation RAG for Multi-Documents QA---附录
人工智能·单片机·嵌入式硬件·物联网·机器学习·语言模型·自然语言处理