标题: 使用单片机判断拨码开关位数时,返回结果异常 [打印本页]

作者: ziqidong    时间: 2025-5-22 16:30
标题: 使用单片机判断拨码开关位数时,返回结果异常
硬件情况:
             单片机型号是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 ,无法按照期望正确返回待测的拨码开关位数
求助大伙,这是什么原因导致的?


作者: cyi8    时间: 2025-5-23 08:28
程序模拟运行一下,单步运行,设置位然后观察变量变化.这是单片机程序最简单的检查方法.而且你程序不长,很容易发现问题的.
作者: xianfajushi    时间: 2025-5-23 08:51
为什么一定要组合?如果是做表决器,一组单独处理后相加即可.
作者: ziqidong    时间: 2025-5-23 11:17
cyi8 发表于 2025-5-23 08:28
程序模拟运行一下,单步运行,设置位然后观察变量变化.这是单片机程序最简单的检查方法.而且你程序不长,很容 ...

谢谢您的意见
作者: ziqidong    时间: 2025-5-23 11:21
xianfajushi 发表于 2025-5-23 08:51
为什么一定要组合?如果是做表决器,一组单独处理后相加即可.

因为后续程序也会使用到这个组合后的结果,如果分开的话,后面每个调用这个结果的语句及函数都需要进行修改

不过,问题已经找到了,8位的char 左移8位结果会全部丢失,需要强制类型转换
再加上硬件端口排布的小问题

感谢您的回复
作者: WL0123    时间: 2025-5-23 13:14
#define PD P0<<8|P1


unsigned int con_bit()
{
        static unsigned int num=0;
        if(num!=PD)
        {
                num=PD;
                return num;
        }       
}
作者: xianfajushi    时间: 2025-5-23 15:06
ziqidong 发表于 2025-5-23 11:21
因为后续程序也会使用到这个组合后的结果,如果分开的话,后面每个调用这个结果的语句及函数都需要进行修 ...

如果用赋值十进制读取十进制再转二进制计算0的个数或1的个数是很容易的,也容易理解,代码也简洁易读;
多组IO读取一组处理一组,顺理成章的;
况且,还可以只使用1组IO当输入,其他IO当控制公共端,可以组成8组8输入,64人表决器。
例如使用51单片机的P0端作为独立按键输入,按键公共端由另外IO控制,赋值P0=255,读取也是十进制的值,按键1按下时读取到的值254即11111110,254转二进制,逢0计数即得1,假如按键2按下读取到253转二进制也得1即11111101,按键1、2按下读取到252转二进制即得2即11111100。




欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1