一、数据定义与基础函数
在数码管的应用中,首先进行数据定义:
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); // 显示带小数点的数字elseSeg_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 ) ,逻辑直观。代码示例:
//高位熄灭1Seg_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 且前一位熄灭时,当前位也熄灭,更符合从高到低处理逻辑。代码示例:
//高位熄灭2Seg_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;
-
-
四、数码管闪烁效果实现
数码管闪烁是一种常见的显示效果,其实现原理主要通过两个关键变量控制:
-
位变量 (bit):用于控制数码管的显示状态(显示 / 熄灭)。
-
计时变量:用于控制闪烁的时间间隔。
核心思路是在定时器中断中周期性地翻转位变量,从而实现数码管的交替显示和熄灭。
以下是具体的代码实现:
// 闪烁控制变量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; // 位变量取反,翻转显示状态 }}部分信息可能已经过时














