1.GPIO读取按键状态
配置
首先,我们通过STM32CubeMX选择对应的芯片型号STM32L431RCT6,
然后选择外部时钟
上图为LED引脚的原理图,然后在STM32CubeMX中选择13号GPIO
然后设置用户标签为LED
接着确定控制按键引脚,这里我们的F1按键接的是PB2,F2按键接的是PB3。
所以接下来我们选择配置PB2
引脚和PB3
引脚为外部中断触发引脚:
因为没有设置硬件上拉,所以我们配置开启上拉电阻,并设置用户标签为KEY1
和KEY2
,
开启外部触发中断有三种:
1.开启下降沿触发中断:在按下按键时电平由高变为低时触发
2.开启上升沿触发中断:在按下按键后松开时电平由低变为高时触发
3.开启下降沿上升沿都触发中断:在按下时触发,松开时再次触发
这里我选择开启下降沿触发中断:
配置NVIC设置中断优先级
NVIC全称Nested vectored interrupt controller
,即嵌套向量中断控制器,用来决定中断的优先级。
NVIC在 ARM Conrtex-M 内核中,用一个 8 位的寄存器来配置,总共可以配置2的8次方=256, 级
中断,但是 ST 公司在生产 STM32 的时候,发现一个小小的单片机根本用不了这么多,纯属费,
所以将该寄存器的低 4 位
全部置0,只使用高 4 位
来配置,这样一来 STM32 就只有 2^4=16 级
中断啦。简化为16级中断后,ST发现 STM32 内部这么丰富的外设,还是不方便配置,干脆人工
给这4位来个分组,划分出了5个分组:
这5种中断分组规则是人为的,而STM32默认使用的规则是 NVIC_PriorityGroup_0 。
STM32 的CPU判断优先级的方法如下:
-
先判断抢占优先级,数字越小,优先级越高;
-
若抢占优先级相同,判断子优先级,同样,数字越小,优先级越高;
在本次的学习中,配置使用中断优先级分组规则 NVIC_PriorityGroup_2:
STM32L4的最高主频到80M,所以配置PLL,最后使HCLK = 80Mhz即可:
最后生成工程文件:
STM32 HAL库中断处理机制
可以看到其中处理EXIT2和EXIT3中断都调用了同一个函数,但是EXIT2和EXIT3向该函数传入的
参数不同,该函数的原型:
可以看到,在该函数中首先读取了一下中断寄存器,确认该中断是否发生,确认之后又调用了一
个函数,并将接收到的参数 GPIO_Pin
继续传给该函数,该函数称为EXIT中断的回调函数,用来处
理所有发生的EXIT中断事件
该回调函数使用__weak
进行了弱定义,所以用户可以再次定义该函数,并且这个note
写的非常清楚:这个函数不应该被改变,如果需要使用回调函数,请重新在用户文件中实现该函数。
说得通俗一些就是,在写一个void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)函数,这样的
话,在中断所处理的内容就是你自己写在void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)函
数的内容,并且不会在进入上图所示的函数中。
这个函数放在哪都行,为了方便,我们放在gpio.c
的最后。
实现的基本思想是:
-
因为所有的EXIT中断都会调用该函数,所以首先判断具体的中断事件;
-
对该中断事件进行处理
代码:
/* USER CODE BEGIN 2 */
/**
* @brief EXIT中断回调函数
* @param GPIO_Pin —— 触发中断的引脚
* @retval none
*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
/* 判断哪个引脚触发了中断 */
switch(GPIO_Pin)
{
case GPIO_PIN_2:
/* 处理GPIO2发生的中断 */
//点亮LED
HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_SET);
break;
case GPIO_PIN_3:
/* 处理GPIO3发生的中断 */
//熄灭LED
HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_RESET);
break;
default:
break;
}
}
/* USER CODE END 2 */
最后烧录即可。
在开发板中,我们分别按下两个按键,会看到LED灯亮和灭的效果。
2.EXIT读取按键状态
首先,我们通过STM32CubeMX选择对应的芯片型号STM32L431RCT6,
然后选择外部时钟
配置
小熊派开发板板载ST-Link并且虚拟了一个串口,原理图如下:
在小熊派的开发板上,先将开关拨到AT-MCU
模式,使PC的串口与USART1之间连接。
接下来开始配置USART1
:
然后STM32L4的最高主频到80M,所以配置PLL,最后使HCLK = 80Mhz
即可,
接着生成工程文件,
代码:
int main(void)
{
/* USER CODE BEGIN 1 */
char str[12] = "Hello World\n";
char recv_buf[12] = {0};
/* USER CODE END 1 */
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
HAL_UART_Transmit(&huart1, (uint8_t*)str, 12, 0xFFFF);
/* USER CODE END 2 */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
//接收12个字节的数据,不超时
if(HAL_OK == HAL_UART_Receive(&huart1, (uint8_t*)recv_buf, 12, 0xFFFF))
{
//将接收到的数据发送
HAL_UART_Transmit(&huart1, (uint8_t*)recv_buf, 12, 0xFFFF);
}
}
/* USER CODE END 3 */
}
最后烧录,在电脑中打开串口,按一下小熊派的复位键,我们会发现,它会先发送数据到串口上,然后我们在串口助手发送数据,也能成功发送过去。