第一讲 决赛试题与过渡模拟一

第一讲 决赛试题与过渡模拟一

在这里插入图片描述

笔记根据b站教程:

题目1(决赛试题)

后续补充

注意点
1.彩灯设计

从左往右、从右往左—位移操作:

_crol_(位移变量,位移次数)   ---  a=_cror_(a,1)

_cror_()
2.不要对寄存器直接进行操作,须使用中间变量进行
P1 = ucLed;
3.避免模式4到模式1忽略L1
if(ucLed ==0x7e) //判断是否从模式4切换至模式1 若是,则复位ucLed数据
  ucLed == 0xfe;
else
{
	ucLed == _cror_(ucLed,1);//模式1 L1-L8
	if(ucLed == 0x7f) Led_Mode = 1;//当L8点亮时,跳转到模式2
}
4.数码管闪烁
全部正常显示
case 1://流转时间设置界面
  Seg_Buf[0] = 13;
  Seg_Buf[1] = Led_Time_Set_Index++;
  Seg_Buf[2] = Led_Time_Set[Led_Time_Set_Index] / 1000 %10;
  Seg_Buf[3] = Led_Time_Set[Led_Time_Set_Index] / 100 % 10;
  Seg_Buf[4] = Led_Time_Set[Led_Time_Set_Index] / 10 % 10;
  Seg_Buf[5] = Led_Time_Set[Led_Time_Set_Index] % 10;
设置闪烁时间和取反变量
if(++Timer_400Ms == 400)//400毫秒触发一次
{
	Timer_400Ms = 0;
	Seg_Star_Flag ^= 1;
}
覆盖闪烁显示
if(Seg_Flag == 0)
{
	Seg_Buf[0] = Seg_Star_Flag?13:10;
	Seg_Buf[1] = Seg_Star_Flag?Led_Time_Set_Index+1:10;
}
else
{
	Seg_Buf[2] = Seg_Star_Flag?Led_Time_Set[Led_Time_Set_Index] / 1000 % 10:10;
	Seg_Buf[3] = Seg_Star_Flag?Led_Time_Set[Led_Time_Set_Index] / 100 % 10:10;
	Seg_Buf[4] = Seg_Star_Flag?Led_Time_Set[Led_Time_Set_Index] / 10 % 10:10;
	Seg_Buf[5] = Seg_Star_Flag?Led_Time_Set[Led_Time_Set_Index] % 10:10;
}
避免按下切换按键后再执行一次
case 6://设置切换按键
  if(Seg_Disp_Mode == 0)//若在显示界面下使能此按键
  {
      for(i=0;i<4;i++)//读取当前设置数据
          Led_Time_Set[i] = Led_Time_Data[i]
      Seg_Disp_Mode = 1;//跳转到参数设置界面
  }
  else if(Seg_Disp_Mode == 1)//else-为了避免第一次按下后直接执行下列程序 所以需要另外加else使得在执行完if语句后跳转出判断主体
  {
      Seg_Flag ^= 1;//用于判断设置处于哪个状态的变量
      if(Seg_Flag == 0)//第二次跳转到模式设置状态
      {
          for(i=0;i<4;i++)
              Led_Time_Data[i] = Led_Time_Set[i];//保存当前设置数据
          Seg_Disp_Mode = 0;
      }
  }
break;
注释—知识点回忆—异或

结合代码 Seg_Flag ^= 1;,我们可以更具体地理解异或操作在C51中的应用场景。这行代码的作用是翻转 Seg_Flag 的最低位(即第0位),通常用于切换某个状态标志。

1.代码分析

Seg_Flag ^= 1;  // 等价于 Seg_Flag = Seg_Flag ^ 1;
  • Seg_Flag 是一个变量,用于表示某个状态或标志。
  • ^= 1 表示将 Seg_Flag 的最低位与 1 进行异或操作。

2.异或操作的具体行为:

  • 如果 Seg_Flag 的最低位是 0,则 0 ^ 1 = 1,最低位变为 1
  • 如果 Seg_Flag 的最低位是 1,则 1 ^ 1 = 0,最低位变为 0

因此,这行代码的作用是切换 Seg_Flag 的最低位

3.结合应用场景

Seg_Flag 是一个用于判断设置处于哪个状态的变量。假设 Seg_Flag 的最低位用于表示某个状态(例如 0 表示状态A,1 表示状态B),那么 Seg_Flag ^= 1; 的作用就是在状态A和状态B之间切换。

示例:

假设 Seg_Flag 的初始值为 0(状态A):

  1. 第一次执行 Seg_Flag ^= 1;
    • Seg_Flag = 0 ^ 1 = 1,切换到状态B。
  2. 第二次执行 Seg_Flag ^= 1;
    • Seg_Flag = 1 ^ 1 = 0,切换回状态A。

通过这种方式,Seg_Flag ^= 1; 可以用于在两个状态之间循环切换。

4.更完整的代码示例

以下是一个更完整的代码示例,展示如何使用 Seg_Flag ^= 1; 来切换状态并执行不同的操作:

#include <reg51.h>

bit Seg_Flag = 0;  // 定义一个位变量,用于表示状态

void main() {
    while (1) {
        if (Seg_Flag == 0) {
            // 状态A的操作
            P1 = 0x0F;  // 例如,设置P1端口的低4位为高电平
        } else {
            // 状态B的操作
            P1 = 0xF0;  // 例如,设置P1端口的高4位为高电平
        }

        // 切换状态
        Seg_Flag ^= 1;

        // 延时
        delay();
    }
}

void delay() {
    int i, j;
    for (i = 0; i < 100; i++)
        for (j = 0; j < 100; j++);
}

5.总结

结合 Seg_Flag ^= 1; 这行代码,异或操作在C51中的意义是:

  1. 切换状态:通过翻转 Seg_Flag 的最低位,可以在两个状态之间切换。
  2. 高效操作:异或操作是位运算,执行速度快,适合在嵌入式系统中使用。
  3. 简洁代码:使用 ^= 1 可以避免复杂的条件判断,使代码更简洁。

Seg_Flag ^= 1; 用于切换设置状态,可能是为了在设置小时和分钟之间切换,或者在设置闹钟的不同参数之间切换。

按键长按
if(System_Flag == 0)//系统处于暂停状态
{
	if(Key_Old == 4 && Seg_Disp_Mode == 0)//在显示界面下长按S4
	  Data_Disp_Flag = 1;//显示数据
	else
	  Data_Disp_Flag = 0;//显示状态
}
else
  Data_Disp_Flag = 0;
LED数据
i = 0;//每次循环判断前将i置0,便于读取Led状态
while(~ucLed & (0x01 << i) == 0)
  i++;

题目2(过渡模拟一)—模拟电压采集记录器

后续补充

注意点
1.输入限制
if(Key_Down >= 1 && Key_Down <= 10)//键盘使能条件
{
	if(Seg_Disp_Mode == 0 && Seg_Input_Index < 4)
    {
        Seg_Input[Seg_Input_Index] = Key_Down -1;
        Seg_Input_Index++;
        Key_Error_Count = 0;
    }
    else
        Key_Error_Count++;
}
2.闪烁避免程序卡死
if(Seg_Buf[5] == 11)//只有当最后一位为-时,才实现数码管闪烁功能
   Seg_Buf[2+Seg_Input_Index] = Seg_Flag?Seg_Input[Seg_Input_Index]:10;
3.进位的思路

在这里插入图片描述

四舍五入保留两位数字

Voltage = (Seg_Input[0] * 1000 + Seg_Input[1] * 100 + Seg_Input[2] * 10 +Seg_Input[3] +5)/1000.0;
4.Float显示数码管

思路:强制类型转换

Seg_Buf[3] = (unsigned char)Voltage_Parameter % 10;
Seg_Buf[4] = (unsigned int)(Voltage_Parameter * 100) / 10 % 10;
Seg_Buf[5] = (unsigned int)(Voltage_Parameter * 100) % 10;
5.9999mV进位之后为10.0V
Seg_Point[3+(int)Voltage/10] = 1;
6.数码管数据刷新
case 0://电压采集界面
  Seg_Point[3+(int)Voltage/10] = 0;
  Seg_Buf[0] = Seg_Buf[1] = 10;
  for(i = 0;i<4;i++)
      Seg_Buf[2+i] = Seg_Input[i];
  if(Seg_Buf[5] == 11)//只有当最后一位为-时,才实现数码管闪烁功能
      Seg_Buf[2+Seg_Input_Index] = Seg_Flag?Seg_Input[Seg_Input_Index]:10;
break;
case 1://数据显示界面
  Seg_Point[3+(int)Voltage / 10] = 1;
  Seg_Buf[0] = 12;
  Seg_Buf[1] = Seg_Buf[2] = 10;
  Seg_Buf[3] = (int)Voltage/10?1:(unsigned char)Voltage % 10;
  Seg_Buf[4] = (unsigned int)(Voltage * 100) / 10 % 10;
  Seg_Buf[5] = (unsigned int)(Voltage * 100) % 10;
break;
7.高位熄灭
while(Seg_Buf[j] == 0)
{
	Seg_Buf[j] = 10;
	if(++j == 5) break;
}
8.计数值增加
if(Voltage > Voltage_Parameter_Ctrol)//当实际电压大于参考电压时
   Voltage_Flag = 1;//拉高标志位
else if(Voltage_Flag == 1)
{
	Voltage_Flag = 0 ;//标志位复位
	count++;//计数值+1
}
9.注意LED模块的显示
void Led_Disp(unsigned char addr,ebable)
{
    static unsigned char temp = 0x00;
    static unsigned char temp_old = 0xff;
    if(enable)
        temp |= 0x01 << addr;
    else
        temp &= ~(0x01 << addr);
    if(temp != temp_old)
    {
        P1 =~temp;
        temp_old = temp;
    }
}
if(++Led_Pos == 8) Led_Pos = 0;
Led_Disp(Led_Pos,ucLed[Led_POS]);
ucLed[1] = Count % 2;
ucLed[2] = Key_Error_Count / 3;

后续或将补充完整代码及题目…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值