单片机:实现数码管动态显示(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简化了数码管的控制。

相关推荐
欢乐熊嵌入式编程1 小时前
智能手表固件升级 OTA 策略文档初稿
嵌入式硬件·学习·智能手表
欢乐熊嵌入式编程1 小时前
智能手表 MCU 任务调度图
单片机·嵌入式硬件·智能手表
【云轩】2 小时前
电机密集型工厂环境下的无线通信技术选型与优化策略
经验分享·嵌入式硬件
sword devil9002 小时前
将arduino开发的Marlin部署到stm32(3D打印机驱动)
stm32·单片机·嵌入式硬件
GodKK老神灭2 小时前
STM32 变量存储
stm32·单片机·嵌入式硬件
木宁kk3 小时前
51单片机引脚功能概述
单片机·嵌入式硬件
JANYI20183 小时前
嵌入式MCU和Linux开发哪个好?
linux·单片机·嵌入式硬件
sword devil9004 小时前
Arduino快速入门
stm32·单片机·嵌入式硬件
GodKK老神灭5 小时前
STM32实现循环队列
stm32·单片机·嵌入式硬件
不脱发的程序猿7 小时前
从MCU到SoC的开发思维转变
单片机·嵌入式硬件