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

相关推荐
星辰pid2 小时前
STM32控制四自由度机械臂(SG90舵机)(硬件篇)(简单易复刻)
stm32·单片机·嵌入式硬件·机械臂
威桑4 小时前
STM32 专有名词缩写整合
stm32·单片机·嵌入式硬件
星源~4 小时前
tree 命令集成到 Git Bash:可视化目录结构的指南
git·单片机·物联网·嵌入式·项目开发
SKYDROID云卓小助手5 小时前
无人设备遥控器之自动调整编码技术篇
人工智能·嵌入式硬件·算法·自动化·信号处理
所念皆星海9115 小时前
图灵完备之路(数电学习三分钟)----数据选择器与总线
嵌入式硬件·通信·数电
智者知已应修善业7 小时前
【51单片机节日彩灯控制器设计】2022-6-11
c语言·经验分享·笔记·单片机·嵌入式硬件·51单片机
开-悟8 小时前
嵌入式编程-使用AI查找BUG的启发
c语言·人工智能·嵌入式硬件·bug
许白掰10 小时前
【stm32】HAL库开发——CubeMX配置RTC,单片机工作模式和看门狗
stm32·单片机·嵌入式硬件·学习·实时音视频
DIY机器人工房10 小时前
0.96寸OLED显示屏 江协科技学习笔记(36个知识点)
笔记·科技·stm32·单片机·嵌入式硬件·学习·江协科技
国科安芯11 小时前
【AS32系列MCU调试教程】SPI调试的常见问题解析
单片机·嵌入式硬件·性能优化·硬件架构·硬件工程