关于28BYJ-48电机驱动代码中位运算(0x99>>j)&(0x80>>i)的疑问
28BYJ-48电机驱动代码的位运算解析与改写问题排查
问题背景
研究位运算后找到一段能驱动28BYJ-48 5V电机的Python代码(唯一可用的Python驱动代码),但自行改写的代码无法运行,存在两个困惑:
- 代码中
(0x99>>j)&(0x08>>i)的位运算逻辑,曾误以为>>是左移位,理解存疑; - 改写后的分步代码为何无法生效。
已查阅位运算资料和讲解视频,仍搞不懂十六进制值的移位运算,也不清楚自写代码失效原因,请求解答。
有效代码
import RPi.GPIO as GPIO from time import sleep #configuring pins and motors motorPin = (18,23,24,25) #GPIO pin in BCM mode refer to map rolePerMinute =13 stepsPerRevolution = 2048 stepSpeed = (60/rolePerMinute)/stepsPerRevolution #setup the pins to the motor def setup(): GPIO.setwarnings(False) GPIO.setmode(GPIO.BCM) for i in motorPin: GPIO.setup(i, GPIO.OUT) def rotary1(): n =1 while n < 10000: for j in range(4): for i in range(4): GPIO.output(motorPin[i],0x99>>j & (0x08>>i)) sleep(stepSpeed) n +=1
自行改写的代码
import RPi.GPIO as GPIO from time import sleep #configuring pins and motors motorPin = (18,23,24,25) #GPIO pin in BCM mode refer to map rolePerMinute =13 stepsPerRevolution = 2048 stepSpeed = (60/rolePerMinute)/stepsPerRevolution #setup the pins to the motor def setup(): GPIO.setwarnings(False) GPIO.setmode(GPIO.BCM) for i in motorPin: GPIO.setup(i, GPIO.OUT) def rotary(): n = 1 while n < 10000: GPIO.output(18,0x99>>1 & (0x08>>1)) sleep(stepSpeed) GPIO.output(23,0x99>>2 & (0x08>>2)) sleep(stepSpeed) GPIO.output(24,0x99>>3 & (0x08>>3)) sleep(stepSpeed) GPIO.output(25,0x99>>4 & (0x08>>4)) sleep(stepSpeed) n+= 1
一、位运算逻辑解析
首先明确:>>是右移位运算符,左移位是<<。右移位会把二进制数的每一位向右移动指定位数,左侧补0,右侧超出的位直接丢弃。
先把代码里的十六进制转成二进制,方便理解:
0x99= 二进制10011001(8位)0x08= 二进制00001000(8位)
代码里的双层循环:
- 外层
j从0到3:控制0x99的右移位数,对应步进电机的每一步驱动状态 - 内层
i从0到3:控制0x08的右移位数,对应四个GPIO引脚的电平设置
按位与&运算的规则是:对应位都为1时结果为1,否则为0。非零值在GPIO输出中代表高电平,0代表低电平。
举几个具体例子:
- 当
j=0、i=0:0x99>>0=10011001,0x08>>0=00001000,按位与结果为00001000(非零)→ 对应引脚输出高电平 - 当
j=0、i=1:0x08>>1=00000100,和10011001按位与结果为00000000→ 对应引脚输出低电平 - 当
j=1:0x99>>1=01001100,再和不同i移位后的0x08做与运算,就能生成下一步的四个引脚电平组合
这段逻辑的本质是用0x99的二进制位序列,生成28BYJ-48需要的四相步进驱动时序——单极四相步进电机需要四个绕组按特定顺序通断电,才能完成步进动作。
二、改写代码失效的原因
你的代码和原代码的核心逻辑完全不符,问题集中在三点:
- 驱动时序错误:原代码是先一次性设置完四个引脚的电平(内层
i循环),再等待stepSpeed完成一步;而你是设置一个引脚就延迟一次,相当于每个引脚的电平变化不同步,完全不符合步进电机的驱动要求——步进电机需要四个绕组的电平同步切换(或按固定时序同时更新),才能带动转子转动。 - 移位参数错误:原代码中
j和i的取值范围都是0-3,但你用了1-4,移位后的二进制值完全偏离原有的驱动序列。比如0x99>>4是00001001,0x08>>4是00000001,按位与的结果和原代码的驱动电平完全不匹配。 - 循环逻辑错误:原代码中每完成4步(
j循环一次),n才加1;而你的代码每次while循环只做了一轮四个引脚的逐个输出就加1,步进的步数和时序完全混乱,电机无法识别正确的驱动信号。
如果要改写,必须保留原代码的时序逻辑:先同步设置四个引脚的电平,再进行延迟。比如可以把四个引脚的电平提前计算好,再批量设置,或者用循环完成四个引脚的电平设置后再sleep。
内容的提问来源于stack exchange,提问作者Michael Silva
相关产品推荐
相关产品推荐

