找回密码
 立即注册
查看: 123|回复: 9

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

[复制链接]
  • 打卡等级:偶尔看看III
  • 打卡总天数:30
  • 最近打卡:2025-06-16 10:11:48
已绑定手机

6

主题

26

回帖

196

积分

注册会员

积分
196
发表于 2025-5-22 16:29:24 | 显示全部楼层 |阅读模式
硬件情况:
             单片机型号是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 ,无法按照期望正确返回待测的拨码开关位数
求助大伙,这是什么原因导致的?


回复

使用道具 举报 送花

3

主题

722

回帖

155

积分

等待验证会员

积分
155
发表于 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。  
  
  1. c
  2.    P1 = 0x00;
  3.    P4 = 0x00;
复制代码

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

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

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

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

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

5. 结论

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

[本文内容由国芯人工智能辅助生成,仅供参考]
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:468
  • 最近打卡:2025-06-16 07:06:57
已绑定手机

79

主题

5131

回帖

9138

积分

超级版主

DebugLab

积分
9138
发表于 2025-5-22 17:27:25 | 显示全部楼层
等号两端数据类型必须一致,需要强制类型转换
return ((unsigned int)vol_high<<8)|(unsigned int)vol_low
DebugLab
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:236
  • 最近打卡:2025-06-16 00:04:38
已绑定手机

7

主题

97

回帖

1197

积分

金牌会员

积分
1197
发表于 2025-5-22 17:31:51 | 显示全部楼层
unsigned char vol_high

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

点评

最高位移到CY,再移丢失  详情 回复 发表于 2025-5-22 18:28
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:468
  • 最近打卡:2025-06-16 07:06:57
已绑定手机

79

主题

5131

回帖

9138

积分

超级版主

DebugLab

积分
9138
发表于 2025-5-22 18:28:26 | 显示全部楼层
C_w*** 发表于 2025-5-22 17:31
unsigned char vol_high

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

最高位移到CY,再移丢失

点评

没错,所以不符合他的需求。 这种低级错误都犯过。  发表于 2025-5-22 21:00
DebugLab
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:30
  • 最近打卡:2025-06-16 10:11:48
已绑定手机

6

主题

26

回帖

196

积分

注册会员

积分
196
发表于 2025-5-23 08:05:43 | 显示全部楼层
Debu*** 发表于 2025-5-22 17:27
等号两端数据类型必须一致,需要强制类型转换
return ((unsigned int)vol_high

谢谢哥!!!
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:30
  • 最近打卡:2025-06-16 10:11:48
已绑定手机

6

主题

26

回帖

196

积分

注册会员

积分
196
发表于 2025-5-23 11:27:55 | 显示全部楼层
这个程序一共有两个问题
1、位操作左移结果丢失,如楼上所言,需要进行强制类型转换
2、硬件端口连接与程序处理逻辑有误,硬件连接决定低位数0,而程序逻辑是高位数0,所以无法得到正确的结果

感谢各位坛友
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:30
  • 最近打卡:2025-06-16 10:11:48
已绑定手机

6

主题

26

回帖

196

积分

注册会员

积分
196
发表于 2025-5-23 11:30:32 | 显示全部楼层
附上正确的代码:
        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)
}
回复 支持 反对

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-6-16 13:02 , Processed in 1.681615 second(s), 87 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表