隐约 发表于 2025-9-8 09:56:34

点亮四位数码管学习

点亮四位数码管学习,数码管从0000-9999显示,间隔1秒,外加一个输出口

隐约 发表于 2025-9-8 09:56:46

#include <STC8H.H>
#include <intrins.h>

// 数码管段引脚定义(共阳极)
sbit SEG_D = P1^5;// D段连接P1.5
sbit SEG_G = P1^3;// G段连接P1.3
sbit SEG_C = P1^4;// C段连接P1.4
sbit SEG_A = P5^4;// A段连接P5.4
sbit SEG_E = P1^6;// E段连接P1.6
sbit SEG_F = P1^7;// F段连接P1.7
sbit SEG_B = P1^2;// B段连接P1.2

// 数码管位选引脚(低电平有效)
sbit DIGIT_QIAN = P3^6;// 千位通过P3.6控制
sbit DIGIT_BAI= P3^7;// 百位通过P3.7控制
sbit DIGIT_SHI= P1^0;// 十位通过P1.0控制
sbit DIGIT_GE   = P1^1;// 个位通过P1.1控制

// 共阳极数码管段码表(0-9)
unsigned char code SEG_TABLE[] = {
    0x3F, // 0
    0x06, // 1
    0x5B, // 2
    0x4F, // 3
    0x66, // 4
    0x6D, // 5
    0x7D, // 6
    0x07, // 7
    0x7F, // 8
    0x6F// 9
};

// 全局变量
unsigned char qian_num = 0;// 千位数字,初始为0
unsigned char bai_num = 0;   // 百位数字,初始为0
unsigned char shi_num = 0;   // 十位数字,初始为0
unsigned char ge_num = 0;    // 个位数字,初始为0
unsigned inttimer_count = 0;   // 定时器计数(用于1秒更新)
unsigned char scan_count = 0;    // 扫描计数(用于高频刷新)
bit         update_flag = 0;   // 更新标志

// 定时器0初始化(0.05ms中断)
void Timer0_Init(void) {
    TMOD = 0x01;                // 定时器0工作在方式1
    TH0 = (65536 - 50) / 256;   // 0.05ms中断初值(12MHz晶振)
    TL0 = (65536 - 50) % 256;
    ET0 = 1;                  // 允许定时器0中断
    EA = 1;                     // 允许总中断
    TR0 = 1;                  // 启动定时器0
}

// 端口初始化
void Port_Init(void) {
    // 配置段选和位选引脚为推挽输出
    P1M0 = 0xA7;// P1.0-P1.7推挽输出
    P1M1 = 0x00;
    P5M0 = 0x10;// P5.4推挽输出
    P5M1 = 0x00;
   
    // 配置百位和千位控制引脚为推挽输出
    P3M0 = 0xC0;// P3.6(千位)和P3.7(百位)推挽输出
    P3M1 = 0x00;
   
    // 初始关闭所有数码管
    DIGIT_QIAN = 1;
    DIGIT_BAI = 1;
    DIGIT_SHI = 1;
    DIGIT_GE = 1;
}

// 设置数码管段码
void Set_Segment(unsigned char num) {
    unsigned char seg_code = SEG_TABLE;
   
    // 共阳极数码管:段码位为1时,对应引脚输出0点亮
    SEG_A = (seg_code & 0x01) ? 0 : 1;
    SEG_B = (seg_code & 0x02) ? 0 : 1;
    SEG_C = (seg_code & 0x04) ? 0 : 1;
    SEG_D = (seg_code & 0x08) ? 0 : 1;
    SEG_E = (seg_code & 0x10) ? 0 : 1;
    SEG_F = (seg_code & 0x20) ? 0 : 1;
    SEG_G = (seg_code & 0x40) ? 0 : 1;
}

// 快速动态扫描显示四位数字
void Fast_Scan_Display(void) {
    // 关闭所有位选,防止串扰
    DIGIT_QIAN = 1;
    DIGIT_BAI = 1;
    DIGIT_SHI = 1;
    DIGIT_GE = 1;
   
    // 循环扫描千位、百位、十位、个位
    switch(scan_count % 4) {
      case 0:// 显示千位
            Set_Segment(qian_num);
            DIGIT_QIAN = 0;
            break;
      case 1:// 显示百位
            Set_Segment(bai_num);
            DIGIT_BAI = 0;
            break;
      case 2:// 显示十位
            Set_Segment(shi_num);
            DIGIT_SHI = 0;
            break;
      case 3:// 显示个位
            Set_Segment(ge_num);
            DIGIT_GE = 0;
            break;
    }
}

// 定时器0中断服务程序(高频刷新+计时)
void Timer0_ISR(void) interrupt 1 {
    // 重装载初值(0.05ms)
    TH0 = (65536 - 50) / 256;
    TL0 = (65536 - 50) % 256;
   
    // 每0.05ms执行一次快速扫描
    scan_count++;
    Fast_Scan_Display();
   
    // 累计20000次中断为1秒(0.05ms * 20000 = 1000ms)
    if (timer_count < 20000) {
      timer_count++;
    } else {
      timer_count = 0;
      update_flag = 1;// 置位更新标志
    }
}

// 更新数字(从0000递增到9999后循环到0000继续)
void Update_Number(void) {
    ge_num++;                // 个位先加1
    if (ge_num > 9) {      // 个位满10
      ge_num = 0;          // 个位归零
      shi_num++;         // 十位加1
      if (shi_num > 9) {   // 十位满10
            shi_num = 0;   // 十位归零
            bai_num++;       // 百位加1
            if (bai_num > 9) {// 百位满10
                bai_num = 0;    // 百位归零
                qian_num++;   // 千位加1
                if (qian_num > 9) {// 千位满10(达到9999)
                  // 循环到0000重新开始
                  qian_num = 0;
                  bai_num = 0;
                  shi_num = 0;
                  ge_num = 0;
                }
            }
      }
    }
}

void main(void) {
    Port_Init();      // 初始化端口
    Timer0_Init();    // 初始化定时器
   
    while (1) {
      // 主循环处理数字更新,显示由定时器中断控制
      if (update_flag) {
            update_flag = 0;
            Update_Number();
      }
    }
}
   

隐约 发表于 2025-9-8 09:57:36

烧录文件
页: [1]
查看完整版本: 点亮四位数码管学习