蓝桥杯单片机第四周笔记

一、数码管显示相关

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;             //更新状态记录
  }
}

五、编程规范与注意事项

  1. 寄存器操作:不要直接操作寄存器,应引入中间变量进行处理,提高代码可读性和稳定性
  2. 计时方法:计时功能应使用中断实现,避免占用主程序运行时间
  3. 条件判断:使用 else if () 避免 if () 只执行一次的问题,确保所有分支都能被正确判断
  4. 场景考虑:代码设计需明确不同场景下的功能逻辑,如 “在什么状态下执行什么操作”,避免逻辑冲突