外部中断探索,CubeMX的前面基础操作我就不写了,外部晶振 串口之类的初始化操作
这次需要PE13 PE14 PE15的外部中断检测开启
在Cube MX中,外部中断就需要自己手动开启对应位置
这里配置成下降沿触发中断,为了方便可以自定义上标签
在gpio.c文件中可以找到生成的外部中断的初始化代码
这里就是中断的函数了,HAL库这里有个特殊的回调函数,可以把很多操作写道回调函数里面,这里我们也要写到回调函数中
我们在这里可以找到回调函数,HAL都已经写的非常模块化和人性化,这里的操作只需要写在HAL_GPIO_EXTI_Callback函数中就可以了,清除中断的操作自己触发后直接执行了,然后启动回调函数执行操作。
这个要删除掉,这是弱函数的定义。我们可以看到,PE13 PE14 PE15比较巧合都是在中断线15_10上,并且都是外部中断,所以可以用同一个回调函数。
HAL_GPIO_EXTI_Callback()回调函数在外部中断里可以理解成为,中断触发后,就会进入到HAL_GPIO_EXTI_Callback中来执行定义的操作,然后进来后我们需要判断GPIO_Pin是具体由哪个IO口来触发的。
最简单的就是这种
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(GPIO_Pin);
/* NOTE: This function Should not be modified, when the callback is needed,
the HAL_GPIO_EXTI_Callback could be implemented in the user file
*/
if(GPIO_Pin == A_Pin)
{
A_flag = 1;
}
if(GPIO_Pin == B_Pin)
{
B_flag = 1;
}
if(GPIO_Pin == SW_Pin)
{
SW_flag = 1;
}
}
这个就是如果A_Pin被下降沿触发,就执行A_flag = 1;其他同理
这个是简单的操作,我们显然要判断更多。首先做个测试,看一看旋转编码器的AB电平来到的先后顺序,有个直观的体会
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(GPIO_Pin);
/* NOTE: This function Should not be modified, when the callback is needed,
the HAL_GPIO_EXTI_Callback could be implemented in the user file
*/
if(GPIO_Pin == A_Pin)
{
printf("A\r\n");
}
if(GPIO_Pin == B_Pin)
{
printf("B\r\n");
}
}
串口助手中可以观察到的现象是正转先后显示A B,反转是先后显示 B A,这也能测试到我们的编码器工作正常。
到了这里,其实就可以中断中写出来一个最简单的判断函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(GPIO_Pin);
/* NOTE: This function Should not be modified, when the callback is needed,
the HAL_GPIO_EXTI_Callback could be implemented in the user file
*/
if(GPIO_Pin == A_Pin)
{
if(HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_14) == 1)
printf("A\r\n");
else if(HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_14) == 0)
printf("B\r\n");
}
}
把A的波形当作一个时钟信号,当检测到下降沿时候,读取B的高低电平就可以判断出来正转还是反转了。
这样虽然可以实现,但是也有自己的局限性,因为这样无法判断是不是误检测到电平的变化,没有消抖,也没有判断到B是否有下降沿的变化。