一、数码管显示相关
1. 高位熄灭处理
- 功能说明:当数码管高位为 0 时,将其熄灭(不显示 0),只显示有效数字
- 实现原理:通过循环判断数码管缓存数组(Seg_Buf)中的高位数据,若为 0 则设置为特殊值 10(代表熄灭状态),直到遇到非 0 数据或循环结束
- 代码示例:
c
运行
while(Seg_Buf[j]==0)//判断高位是否为0
{
Seg_Buf[j]=10; //设置为熄灭状态
if(++j==5)break; //防止数组越界,最多判断5位
}
2. 数码管闪烁功能
- 功能说明:使数码管特定位置实现闪烁效果,需满足特定条件才触发
- 实现要点:
- 先正常显示数据,再用熄灭状态覆盖显示,通过标志位(Seg_Flag)控制切换
- 需判断最后一位状态,只有满足条件(如最后一位为 11,代表 “-”)才闪烁,否则可能导致程序卡死
- 代码示例:
c
运行
//只有当最后一位为"-"(用11表示)时,才实现数码管闪烁
if(Seg_Buf[5] == 11)
//通过Seg_Flag标志位控制显示原数据或熄灭状态
Seg_Buf[2+Seg_Input_Index] = Seg_Flag?Seg_Input[Seg_Input_Index]:10;
3. 数码管显示逻辑控制
- 判断哪一位点亮的方法:
- 先对 LED 控制变量(uLed)取反(~uLed),此时只有一个位为 1
- 通过循环左移 0x01,与取反后的变量进行 & 运算,判断结果是否为 0 来确定点亮位置
- 代码示例:
c
运行
if((LED_Mode==0)||(LED_Mode==1))
{
Seg_Buf[4]=10; //熄灭第4位
//循环判断哪一位被点亮
while(~uled&(0x01<<i)==0)
{
i++;
}
Seg_Buf[5]=i-1; //在第5位显示位置信息
i=0; //重置循环变量
}
else if((LED_Mode==2)||(LED_Mode==3))
{
//同样判断点亮位置
while(~uled&(0x01<<i)==0)
{
i++;
}
Seg_Buf[5]=i-1; //第5位显示位置
Seg_Buf[4]=9-(i-1); //第4位显示计算后的数据
i=0; //重置循环变量
}
二、按键控制相关
1. 按键长按处理
- 功能说明:检测按键长按操作,并执行相应功能
- 实现要点:结合系统状态(System_Flag)和显示模式(Seg_Disp_Mode)判断是否执行长按操作
- 代码示例:
c
运行
if(System_Flag == 0)//系统处于暂停状态时
{
//在显示界面下长按S4按键(Key_Old == 4)
if(Key_Old == 4 && Seg_Disp_Mode == 0)
Data_Disp_Flag = 1;//设置标志位,显示数据
else
Data_Disp_Flag = 0;//清除标志位,显示状态
}
2. 按键操作场景考虑
- 设计原则:明确不同场景下按键的功能,避免逻辑混乱
- 示例场景:
- 在显示界面下才能进行数值设置
- 保存功能需要按两次按键确认
- 代码示例:
c
运行
else if(Seg_Disp_Mode == 1)//在设置模式下
{
Set_Flag ^= 1;//切换设置状态(0和1交替)
if(Set_Flag == 0)//第二次按下(回到0状态),保存设置
{
//将设置缓冲区的数据保存到实际数据区
for(i=0;i<4;i++)
Led_Time_Data[i] = Led_Time_Set[i];
Seg_Disp_Mode = 0;//退出设置模式,返回显示模式
}
}
三、数据处理相关
1. 四舍五入算法
- 实现方法:先将各位数据拼接成整数,加上 5 后再进行除法运算,实现四舍五入效果
- 代码示例:
c
运行
//将4位输入数据拼接成整数,加5后除以1000.0实现四舍五入
voltage =(Seg_Input[0]*1000+Seg_Input[1]*100+Seg_Input[2]*10+Seg_Input[3]+5)/1000.0;
//强制类型转换为整数
(int)voltage;
2. 浮点数据处理
- 注意事项:
- 浮点数(float 类型)写入数码管时,需进行强制类型转换
- 避免多次除法运算,防止精度丢失或数据溢出
- 处理方法:先通过乘法将小数部分转换为整数,再进行处理
四、LED 控制相关
1. LED 工作原理
- 二极管具有单向导通性,给低电平时 LED 导通点亮
- 控制逻辑:通过 CBA 信号控制 Y 通道,Y 通道控制串口开关使能
2. RS 锁存器
- 功能:用于锁存 LED 的控制信号,保持输出状态稳定
- 真值表:
| R(复位) | S(置位) | Q(输出) | 说明 |
|---|---|---|---|
| 0 | 0 | Q(原值) | 保持原有状态 |
| 0 | 1 | 1 | 输出置为 1 |
| 1 | 0 | 0 | 输出置为 0 |
| 1 | 1 | X(不确定) | 禁止此状态 |
- 使能控制:EN=0 时,锁存器状态不变;EN=1 时,输出与输入一致
3. 译码器 74HC138
- 功能:将 3 个输入信号(CBA)转换为 8 个输出信号(Y0-Y7),实现 8421 编码控制
- 编码规则:CBA 对应 421 编码(忽略 8),如 001 对应 Y1,011 对应 Y3
- 控制流程:控制译码器选择对应通道→控制使能端→传输数据→关闭锁存器
4. 系统初始化底层代码
c
运行
void System_Init()
{
P0=0xff; //关闭所有LED(输出高电平)
P2=P2&0x1f |0x80; //选中Y4锁存器(先清后5位,再配置前3位)
P2=P2&0x1f; //关闭锁存器
P0 = 0x00; //关闭蜂鸣器(输出低电平)
P2=P2&0x1f | 0xa0; //选中Y5锁存器
P2=P2&0x1f; //关闭锁存器
}
5. LED 显示底层代码
c
运行
//addr:LED位置(0-7),enable:使能位(1点亮,0熄灭)
void Led_Disp(unsigned char addr, enable)
{
static unsigned char temp=0x00; //保存当前LED状态
static unsigned char temp_old=0xff; //保存上一次LED状态
if(enable)
{
temp|=(0x01<<addr); //设置对应位置为1(点亮)
}
else
{
temp&=~(0x01<<addr); //设置对应位置为0(熄灭)
}
//只有状态发生变化时才更新显示,减少IO操作
if(temp!=temp_old)
{
P0=~temp; //取反输出(因为低电平点亮)
P2=P2&0x1f |0x80; //选中Y4锁存器
P2=P2&0x1f; //关闭锁存器
temp_old=temp; //更新状态记录
}
}
五、编程规范与注意事项
- 寄存器操作:不要直接操作寄存器,应引入中间变量进行处理,提高代码可读性和稳定性
- 计时方法:计时功能应使用中断实现,避免占用主程序运行时间
- 条件判断:使用 else if () 避免 if () 只执行一次的问题,确保所有分支都能被正确判断
- 场景考虑:代码设计需明确不同场景下的功能逻辑,如 “在什么状态下执行什么操作”,避免逻辑冲突