第四周——过度模拟一

问题一:电压采集界面输入错误 :white_check_mark:

解决方案(已验证正确)

 C1if(Key_Down >= 1 && Key_Down <= 10) {  // 按键输入
 2    if(Seg_Intput_Detix <= 3 && Seg_Mode == 0) {  // 输入不超过四位,在第一个模式下
 3        Seg_Intput[Seg_Intput_Detix] = Key_Down - 1;
 4        Seg_Intput_Detix++;
 5    }
 6}
 7

原理说明

  • 按键中断处理中进行输入操作

  • 按键值1-10映射到数字0-9

  • 位置索引递增,确保依次输入


问题二:电压采集界面无法逐个闪烁 :white_check_mark:

解决方案(已验证正确)

 C1for(i = 0; i < 4; i++)
 2    Seg_Buf[2 + i] = Seg_Input[i];
 3
 4if(Seg_Buf[5] == 11) {  // 只有当最后一位为'-'时,才实现数码管闪烁功能
 5    Seg_Buf[2 + Seg_Input_Index] = Seg_Flag ? Seg_Input[Seg_Input_Index] : 10;
 6}
 7

原理说明

  • 先显示所有输入数字

  • 判断最后一位是否为结束符’-'(11)

  • 通过闪烁标志位切换当前位显示/熄灭


问题三:电压设置模式无法显示所设置的电压 :white_check_mark:

解决方案(已验证正确)

 C1Seg_Buf[3] = (unsigned char)Voltage_Parameter % 10;
 2Seg_Buf[4] = (unsigned int)(Voltage_Parameter * 100) / 10 % 10;
 3Seg_Buf[5] = (unsigned int)(Voltage_Parameter * 100) % 10;
 4

原理说明

  • 使用强制类型转换处理float类型

  • 先乘以100转整数,再进行取模运算

  • 分离百位、十位、个位显示


问题四:计数统计界面卡死现象 :white_check_mark:

解决方案1:零点穿过检测(已验证正确)

 C1if(Voltage_Set < Voltage) {  // 现在电压大于设置电压
 2    Clock_Num_Flag = 1;      // 拉高标志位
 3}
 4else if(Clock_Num_Flag == 1) {  // 现在电压小于设置电压
 5    Clock_Num_Flag = 0;      // 降低标志位
 6    Clock_Num++;             // 次数加一
 7}
 8

注意:相当于零点定理

解决方案2:高位显示为0处理(已验证正确)

 C1while(Seg_Buf[j] == 0) {  // 高位为0时熄灭
 2    Seg_Buf[j] = 10;
 3    j++;
 4    if(j == 5) break;  // 关键点:跳出循环,防止卡死,并且最后一位为0
 5}
 6

原理说明

  • 零点穿过:当电压穿过设置值时,通过标志位翻转完成计数

  • 高位处理:防止前导零显示,当高位为0时设置为熄灭状态(10)

  • 防卡死:if(j==5) break 确保至少保留最后一位显示


问题五:S14清零时无法再次输入 :white_check_mark:

解决方案(已验证正确)

 C1case 14:  // 清零参数按键
 2    if(Seg_Mode == 0) {
 3        Seg_Intput_Detix = 0;  // 复位
 4        for(j = 0; j < 4; j++) {
 5            Seg_Intput[j] = 13;
 6        }
 7    }
 8    break;
 9

原理说明

  • 清零时同时复位输入位置指针输入数组

  • 13表示清空符号

  • 下次输入时能够从头开始


问题六:LED模块驱动 :white_check_mark:

Led.h(已验证正确)

 C1#ifndef __LED_H__
 2#define __LED_H__
 3
 4void Led_Disp(unsigned char arrd, unsigned char enable);
 5
 6#endif
 7

Led.c(已验证正确)

 C1#include "Led.h"
 2
 3void Led_Disp(unsigned char arrd, unsigned char enable) {
 4    static unsigned char temp = 0x00;        // 静态变量,永不改变
 5    static unsigned char temp_old = 0xff;
 6    
 7    if(enable) {
 8        temp |= (0x01 << arrd);              // 置位
 9    }
 10    else {
 11        temp &= ~(0x01 << arrd);             // 清位
 12    }
 13    
 14    if(temp != temp_old) {
 15        P1 = ~temp;
 16        temp_old = temp;  // 跳出if语句
 17    }
 18}
 19

原理说明

  • 使用静态变量保存LED状态,永久保留

  • 位操作:|= 置1(亮),&=~ 置0(灭)

  • 只在状态改变时更新端口,提高效率

  • P1 = ~temp:取反输出(因为LED通常低电平亮)

使用方式

 C1Led_Disp(0, 1);  // LED0亮
 2Led_Disp(1, 0);  // LED1灭
 3Led_Disp(2, 1);  // LED2亮
 4

核心要点总结

:warning: 声明变量一定要注意是char型还是int类型

 C1// 标志位、开关 → char/unsigned char
 2unsigned char Clock_Num_Flag = 0;
 3unsigned char Seg_Flag = 0;
 4
 5// 计数值 → int/unsigned int
 6unsigned int Clock_Num = 0;
 7
 8// 浮点数据 → float
 9float Voltage_Set = 0.0;
 10
 11// 数字数组 → unsigned char数组
 12unsigned char Seg_Buf[6];
 13

:key: 关键技巧

  1. 零点穿过:用标志位检测电压穿过设置值

  2. 高位处理:防止前导零显示

  3. 防卡死:循环中加入边界判断

  4. 静态变量:保存状态,实现记忆功能

  5. 位操作:高效的状态管理