这是旋转编码器的样子：编码器工作原理：像一个方向旋转，比如向左旋转会A先与GND接通然后到B，向右转就是反过来B先与GND导通然后到A。（这里只是做个比喻，实际不一定是这样的，问题不大）向左转的时序图：为了使它工作稳定A和B引脚需要接一个10K左右的上拉电阻。清楚它的工作原理就可以开始写代码了先在cubeMX配置（这里只需要配置PC11为A，PA15为B，其他不用管）：然后在nvic选项中把对应的中断勾上否则无法进入回调函数（选不同引脚显示是不一样的反正把带EXTI的选项勾上就对了）下面就是代码（发生中断会自动进入这条函数不需要调用，放主函数下面就行了） //声明这些全局变量，使用方法：读取bmq_flag，如果这个变量为0就是编码器没动作 //如果是1，说明向左转了，再读取bmq_go_int，这个变量是转的步数（脉冲数） //如果是2，说明向右转了，再读取bmq_go_int，这个变量是转的步数（脉冲数) //读完以后需要对变量清零 bmq_flag=0；bmq_go_int=0； char bmq_flag; //0 nothink . 1 L . 2 R int bmq_go_int; long bmq_old_time; char bmq_lr; //0 l . 1 r void HAL_GPIO_EXTI_Callback(uint16_tGPIO_Pin) { #definewx 40 //两个脉冲之间的延时，用于识别是新的动作还是连续的脉冲 switch(GPIO_Pin) //识别中断引脚 { case GPIO_PIN_11: //A被拉低 if(HAL_GetTick()<(bmq_old_time+wx))//如果距离上一个脉冲的时间很短说明在连续旋转 { if(bmq_lr==1) { if(bmq_flag!=1) { bmq_flag=2; bmq_go_int=0; } bmq_go_int+=1; } }else { bmq_lr=0; } bmq_old_time=HAL_GetTick(); break; case GPIO_PIN_15: if(HAL_GetTick()<(bmq_old_time+wx)) { if(bmq_lr==0) { if(bmq_flag!=2) { bmq_flag=1; bmq_go_int=0; } bmq_go_int+=1; } }else { bmq_lr=1; } bmq_old_time=HAL_GetTick(); break; default: break; } __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin); //清除中断 }