理论部分:
1.霍尔传感器的工作原理:

这里原理不想多讲了,放几张图自用

依据霍尔效应和洛伦兹力,会在“铁板”上产生霍尔电压


通过读取A和B的脉冲,来判断正转反转以及位置

介绍一下中断:
中断与gpioread不同,同样一段脉冲信号,gpioread捕捉的是此时的高低电平信号,中断捕捉的是高低电平变化的信号,下图红色的是中断捕捉的,蓝色的gpioread捕捉的


encoder++和encoder--的思路:

因为我们打算通过中断来计数
这里介绍一下外部中断的特点:并不是读取某一时刻的高低电平,而是捕捉高低电平的变化,即上升沿和下降沿
把A相设置成双边沿触发,即上升沿触发和下降沿都触发,此时如何判断电机旋转的方向呢
假如来了一个上升沿,此时会进入中断函数,然后这个发生时间是有先后顺序的,是先有上升沿,然后再进入中断,此时进入中断的时间,要比上升沿滞后一些,所以如果是在上升沿后触发的中断,在此刻读取电平应该是高电平,下降沿就是低电平,我们只要判断A,B项在中断函数时刻的高低电平,就能判断正反转了,现在我们把上升沿当成高电平,下降沿当成低电平,对如下表格进行编程

CubeMx部分:
先看一下原理图

一共有PB3,PB4,PB13,PB14其中PB3和PB14是EXTI引脚
设置EXTI引脚的方法是,右键某个引脚选择GPIO_EXTIX

哦对了关于引脚重定义,用HAL库无需像标准库那样麻烦,直接在图形化界面点击引脚像平常那么设置就好了

在具体的GPIO中,设置PB3和PB14的模式为双边沿触发,然后上拉电阻
为什么非得是上拉电阻呢:
 

  • 上拉时,引脚默认高电平,要触发中断需主动拉低(如接 GND、按键按下),外界干扰很难轻易将高电平拉低(需足够大的电流)。
  • 下拉时,引脚默认低电平,外界干扰(如静电、电磁辐射)可能轻易将低电平拉高,导致中断误触发。




最后记得在NVIC里开启中断,优先级设置0为最高

PB4和PB15设置成输入引脚就好,默认上拉,我们要用这两个引脚来ReadPin高低电平

Keil代码编写部分:
我们新建两个文件encoder.c.h
在中断函数为:void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
这个函数是GPIO外部触发中断的总函数,具体判断哪个引脚需要在其中加上if判断

(使用此中断函数的时候,仅需在.h文件中声明一下,不用在main函数里提前声明之类的,触发中断的时候会自动跳转到此中断函数,标准库里的中断函数需要对标志位清零,HAL库很方便不用)
函数内的代码就是依据不同电平--,相同电平++,判断正反转和计数

判断左电机的时候++和--与右电机相反,是因为位置朝向不同,两个电机对称摆放

获取encoder值的函数,也非常简单

测试函数:

这里串口注意是要发送int32_t类型的数字,而且vofa解析的话是要特殊格式的,比如两个数据之间用逗号分离可以显示两路通道,用\n表示一组数据,不然无法解析,这是我自己的串口函数如下:
 

HAL_StatusTypeDef USART_Send_TwoInt32(UART_HandleTypeDef *huart, int32_t data1, int32_t data2)
{
    char send_buf[32]; // 缓冲区,足够存储两路int32_t的字符串(含逗号、换行)
    int len;
    len = sprintf(send_buf, "%ld,%ld\r\n", (long)data1, (long)data2);
    return HAL_UART_Transmit(huart, (uint8_t*)send_buf, len, 1000);
}



最后成功显示波形

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐