Mobile wallpaper 1Mobile wallpaper 2Mobile wallpaper 3Mobile wallpaper 4
1430 字
7 分钟
数码管相关功能实现与考点解析

一、数据定义与基础函数#

在数码管的应用中,首先进行数据定义:

  • idata unsigned char Seg_Pos;:定义了数码管显示位置变量,idata表示该变量存储在内部数据存储器中
  • pdata unsigned char Seg_Buf[8] = {10, 10, 10, 10, 10, 10, 10, 10};:定义了数码管显示缓存数组,pdata表示存储在分页外部数据存储器中,数组初始化为熄灭状态(值为10,通常可自定义表示熄灭)

数码管处理函数 Seg_Proc() 初步搭建了数码管的处理逻辑框架:

void Seg_Proc()
{
// 数码管处理逻辑可以在这里添加
Seg_Buf[0] = 1 + ','; // 显示"1."
}

二、小数点显示优化#

为了更便捷地控制小数点显示,利用 ASCII 码特性实现了一种优化方法:

  • 原理

    • 段选数组seg_dula[]有效索引通常不超 20 。

    • 需显示小数点时,给显示数字加上逗号(逗号 ASCII 码为 44 ) 。

    • 通过判断缓存值是否大于 20 确定是否显示小数点,显示时将缓存值减去逗号 ASCII 码得原始数字。

  • 定时器中断服务函数中的应用

    void Timer1_Isr(void) interrupt 3
    {
    uwTick++; // 系统计时增加
    Seg_Pos = (++Seg_Pos) % 8; // 循环更新数码管位置
    // 数码管显示处理: 自动判断是否需要显示小数点
    if (Seg_Buf[Seg_Pos] > 20)
    Seg_Disp(Seg_Pos, Seg_Buf[Seg_Pos] - ',', 1); // 显示带小数点的数字
    else
    Seg_Disp(Seg_Pos, Seg_Buf[Seg_Pos], 0); // 显示不带小数点的数字
    }

此定时器中断服务函数中,每次中断更新数码管位置Seg_Pos ,并根据Seg_Buf中对应位置的值判断是否显示小数点,调用Seg_Disp函数进行显示。这种设计节省内存空间,代码简洁易维护,显示逻辑集中。

三、负数显示与高位熄灭考点#

  • 负数显示:在竞赛等场景中常需显示负数,假设显示范围 - 99 到 99 ,负号段选值设为 11 。实现时先取校准值相反数,再根据数值范围判断分段显示: (或者也可以直接用abs()函数来找整数,但注意的是int/char类型,这样才能包含小数)

    char Calibration = 0;
    void Seg_Proc()
    {
    unsigned char Temp_Calibration = -Calibration; // 先获取一个校准值相反数
    // 代表会占用三个位置显示
    if (Calibration <= -10)
    {
    Seg_Buf[5] = 11; // -
    Seg_Buf[6] = Temp_Calibration / 10 % 10;
    Seg_Buf[7] = Temp_Calibration % 10;
    }
    // 代表占用两个位置显示
    else if (Calibration < 0)
    {
    Seg_Buf[5] = 10;
    Seg_Buf[6] = 11; // -
    Seg_Buf[7] = Temp_Calibration % 10;
    }
    // 代表占用一个位置显示
    else if (Calibration < 10)
    {
    Seg_Buf[5] = 10;
    Seg_Buf[6] = 10;
    Seg_Buf[7] = Calibration % 10;
    }
    // 代表占用两个位置显示
    else
    {
    Seg_Buf[5] = 10;
    Seg_Buf[6] = Calibration / 10 % 10;
    Seg_Buf[7] = Calibration % 10;
    }
    }
  • 高位熄灭:高位熄灭用于消除数值前导零,提升显示效果。实现要求如下:

    • 仅题目明确要求时实现。

    • 每个数码管位置只能赋值一次,避免多次赋值引发显示中断冲突致数码管闪烁。

    • 实现方案

      • 数值比较法:判断显示数值是否大于对应位权值,大于则显示实际数值,否则熄灭(显示 10 ) ,逻辑直观。代码示例:

        //高位熄灭1
        Seg_Buf[0] = (Freq >= 10000000)
        ? Freq / 10000000 % 10
        : 10;
        Seg_Buf[1] = (Freq >= 1000000)
        ? Freq / 1000000 % 10
        : 10;
        Seg_Buf[2] = (Freq >= 100000)
        ? Freq / 100000 % 10
        : 10;
        Seg_Buf[3] = (Freq >= 10000)
        ? Freq / 10000 % 10
        : 10;
        Seg_Buf[4] = (Freq >= 1000)
        ? Freq / 1000 % 10
        : 10;
        Seg_Buf[5] = (Freq >= 100)
        ? Freq / 100 % 10
        : 10;
        Seg_Buf[6] = (Freq >= 10)
        ? Freq / 10 % 10
        : 10;
        Seg_Buf[7] = Freq % 10;
      • 零值检测法:结合当前位值和前一位状态,当前位为 0 且前一位熄灭时,当前位也熄灭,更符合从高到低处理逻辑。代码示例:

        //高位熄灭2
        Seg_Buf[0] = (Freq / 10000000 % 10 == 0)
        ? Freq / 10000000 % 10
        : 10;
        Seg_Buf[1] = ((Freq / 1000000 % 10==0) && (Seg_Buf[0] == 10))
        ? Freq / 1000000 % 10
        : 10;
        Seg_Buf[2] = ((Freq / 100000 % 10==0) && (Seg_Buf[1] == 10))
        ? Freq / 100000 % 10
        : 10;
        Seg_Buf[3] = ((Freq / 10000 % 10==0) && (Seg_Buf[2] == 10))
        ? Freq / 10000 % 10
        : 10;
        Seg_Buf[4] = ((Freq / 1000 % 10==0) && (Seg_Buf[3] == 10))
        ? Freq / 1000 % 10
        : 10;
        Seg_Buf[5] = ((Freq / 100 % 10==0) && (Seg_Buf[4] == 10))
        ? Freq / 100 % 10
        : 10;
        Seg_Buf[6] = ((Freq / 10 % 10==0) && (Seg_Buf[5] == 10))
        ? Freq / 10 % 10
        : 10;
        Seg_Buf[7] = Freq % 10;

四、数码管闪烁效果实现#

数码管闪烁是一种常见的显示效果,其实现原理主要通过两个关键变量控制:

  1. 位变量 (bit):用于控制数码管的显示状态(显示 / 熄灭)。

  2. 计时变量:用于控制闪烁的时间间隔。

核心思路是在定时器中断中周期性地翻转位变量,从而实现数码管的交替显示和熄灭。

以下是具体的代码实现:

// 闪烁控制变量
bit Seg_Show_Light = 0; // 控制显示状态的位变量
unsigned int Time_500ms = 0; // 500ms计时变量
void Seg_Proc(void)
{
// 根据闪烁状态决定显示1还是熄灭
Seg_Buf[0] = Seg_Show_Light ? 1 : 10; // 闪烁显示1
}
void Timer1_Isr(void) interrupt 3
{
uwTick++; // 系统计时增加
// 数码管位置循环更新
Seg_Pos = (++Seg_Pos) % 8;
// 数码管显示处理:自动判断是否需要显示小数点
if (Seg_Buf[Seg_Pos] > 20)
Seg_Disp(Seg_Pos, Seg_Buf[Seg_Pos] - ',', 1); // 显示带小数点的数字
else
Seg_Disp(Seg_Pos, Seg_Buf[Seg_Pos], 0); // 显示不带小数点的数字
// 闪烁时间控制(500ms翻转一次)
if (++Time_500ms == 500)
{
Time_500ms = 0;
Seg_Show_Light ^= 1; // 位变量取反,翻转显示状态
}
}
数码管相关功能实现与考点解析
https://mizuki.mysqil.com/posts/蓝桥杯单片机/数码管相关功能实现与考点解析/
作者
风过无痕
发布于
2025-11-06
许可协议
CC BY 4.0

部分信息可能已经过时

封面
Sample Song
Sample Artist
封面
Sample Song
Sample Artist
0:00 / 0:00