紫气东 发表于 2025-5-22 16:29:24

使用AI8G系列单片机判断拨码开关位数时,返回结果异常

硬件情况:
             单片机型号是STC8G2K64S4 ,LQFP48封装

             P0 P2是接收端口(准双向置1),P1 P4是驱动端口(准双向置0)

             拨码开关 是多组独立开关的集合体,有4组,6组,8组,9组等
工程原理:
             将拨码开关引脚与单片机端口相连,闭合开关后,检测接收端口0 的个数,来判断当前开关的位数(检测前已确保所有开关闭合)
             由于STC8G系列一组IO只有8个引脚,如果要测量的拨码开关位数大于8,就必须启用两组IO来组合实现
             程序中,先将两组IO的检测结果(8位)组合为16位,然后再从高位往低位计数 “0”的个数,即可得出拨码开关的位数
源代码:
            P1=0x00;P4=0x00;
             _nop_();_nop_();
      
             bits=detect_bit(con_bit(P0,P2));

             unsigned int con_bit (unsigned char vol_high,unsigned char vol_low){
                              return (vol_high<<8)|vol_low ;
                              }

            unsigned char detect_bit(unsigned int vol) {
                                  unsigned int mask = 0x8000;
                                  unsigned char cnt = 0;
                                  while (mask && !(vol & mask)) {       // 当mask位为0时计数
                                 cnt++;
                                  mask >>= 1;
                                 }
                              return cnt;                        // 返回连续高位0的个数(0-16)
                              }
问题:
         经实践,当拨码开关位数<8时,返回的bits 是0;当拨码开关位数>=8时,返回的bits 是8 ,无法按照期望正确返回待测的拨码开关位数
求助大伙,这是什么原因导致的?


国芯人工智能 发表于 2025-5-22 16:33:00

单片机STM8G2K64S4在拨码开关位数检测中的应用

1. 硬件与软件配置
单片机型号:STC8G2K64S4
单片机型号为STC8G2K64S4,封装为LQFP48。
单片机功能:单片机支持单片机I/O端口的控制和数据读取。
P0、P2接收端口:准双向置1端口,用于接收拨码开关的位数信号。
P1、P4驱动端口:准双向置0端口,用于驱动拨码开关的开关。
拨码开关:包括4组、6组、8组、9组等多组独立开关,控制拨码状态。
位数检测方法
单片机通过测量拨码开关的位数来判断其状态。拨码开关的位数通常为0-9组,其中9组为最大位数。
检测原理:通过将拨码开关的位数信号(P0、P2)连接到单片机的I/O端口,检测接收到的位数。
两组IO的使用:由于单片机的一组IO(P1、P4)只能提供8个引脚,测量位数超过8时需要启用两组IO(P1、P4)。
位数计算:将两组IO的检测结果(8位)组合为16位二进制数,从高位到低位计数,计算拨码开关的位数。

2. 计算拨码位数的步骤

1. 初始化
   初始化单片机,设置P1和P4的值为0x00。
   c
   P1 = 0x00;
   P4 = 0x00;

2. 检测位数
   使用单片机的循环功能(如nop())检测拨码开关的位数。
   c
   bits = detectbit(P0, P2);

3. 位数计算
   将两组IO的检测结果(8位)组合为16位二进制数,从高位到低位计数,计算拨码开关的位数。
   c
   unsigned int conbit = 0;
   for (int i = 0; i < 16; i++) {
       conbit |= bits >> (i8);
       bits >>= (i8);
   }

4. 返回拨码位数
   根据检测结果计算拨码位数,并返回给调用者。
   c
   unsigned int拨码位数 = 0;
   for (int i = 0; i < conbit; i++) {
      拨码位数 |= (conbit >> (i8)) & 1;
   }
   return拨码位数;

3. 示例应用
输入:拨码开关的位数(0-9组)。
输出:拨码开关的状态(0-9组)。

4. 注意事项
两组IO的使用:在检测位数超过8时,需要启用两组IO(P1、P4)。
比如,若拨码开关的位数为9组,需要将两组IO的检测结果(8位)组合为16位二进制数。
例如,若P0的位数为0b1001,P2的位数为0b0101,组合后为0b10010101,从高位到低位计数为拨码位数为10组。

5. 结论

通过上述步骤,单片机STM8G2K64S4可以有效检测拨码开关的位数,并根据检测结果返回拨码状态。

[本文内容由国芯人工智能辅助生成,仅供参考]

DebugLab 发表于 2025-5-22 17:27:25

等号两端数据类型必须一致,需要强制类型转换
return ((unsigned int)vol_high<<8)|(unsigned int)vol_low

C_wolf 发表于 2025-5-22 17:31:51

unsigned char vol_high

定义的为8位,左移会是啥结果

DebugLab 发表于 2025-5-22 18:28:26

C_wolf 发表于 2025-5-22 17:31
unsigned char vol_high

定义的为8位,左移会是啥结果

最高位移到CY,再移丢失

紫气东 发表于 2025-5-23 08:05:43

DebugLab 发表于 2025-5-22 17:27
等号两端数据类型必须一致,需要强制类型转换
return ((unsigned int)vol_high

谢谢哥!!!{:aixin:}

紫气东 发表于 2025-5-23 11:27:55

这个程序一共有两个问题
1、位操作左移结果丢失,如楼上所言,需要进行强制类型转换
2、硬件端口连接与程序处理逻辑有误,硬件连接决定低位数0,而程序逻辑是高位数0,所以无法得到正确的结果

感谢各位坛友{:4_183:}

紫气东 发表于 2025-5-23 11:30:32

附上正确的代码:{:4_166:}
      P1=0x00;P4=0x00;
      _nop_();_nop_();
      bits=detect_bit(con_bit(P2,P0));

unsigned int con_bit (unsigned char vol_high,unsigned char vol_low){
      
      return ((unsigned int)vol_high<<8)|(unsigned int)vol_low;
}


unsigned char detect_bit(unsigned int vol) {
    unsigned int mask = 0x0001;
      unsigned char cnt = 0;
    while (mask && !(vol & mask)) {       // 当mask位为0时计数
      cnt++;
      mask <<= 1;
    }
    return cnt;                        // 返回连续低位0的个数(0-16)
}
页: [1]
查看完整版本: 使用AI8G系列单片机判断拨码开关位数时,返回结果异常