使用的是正点原子的精英版,单片机是STM32F103ZET6,本例程实现使用外部中断线,实现KEY UP控制BEEP响停,KEY1控制LED1翻转,KEY0控制LED0翻转。先看一下原理图以及分析:
当KEY_UP按下时,PA0为高电平,所以说是上升沿触发外部中断EXTI0,接着跳转中断服务函数,最后执行一个中断回调函数。(这里的当KEY_UP按下时,PA0为高电平,为了设置上升沿触发方式,所以我们要将PA0设置为下拉输入)。当KEY0按下时,PE4为低电平,所以说是下降沿触发外部中断EXTI4,接着跳转中断服务函数,最后执行一个中断回调函数。(这里的当KEY_UP按下时,PA0为高电平,为了设置下降沿触发方式,所以我们要将PE4设置为下拉输入)。KEY1和KEY0配置相同。
了解原理之后我们复制上节课按键代码 参考上一章代码,打开图形化配置将PA0配置为GPIO_EXTI0,PE4配置为GPIO_EXTI4,PE3配置为GPIO_EXTI3
接下里配置它的一个触发模式 ,PA0配置为上升沿触发,下拉。PE4和PE3配置为下降沿触发,上拉。
接下来配置一下中断以及优先级 ,首先勾选使能中断,然后将抢占优先级设置为相同(优先级从1到15,数字越小越优先执行,优先执行必不能打断另外一个在执行的任务,他只是优先执行。先判断抢占优先级,当一样时再判断响应优先级),设置完成后生成代码。
在主函数中添加以下代码
/* USER CODE BEGIN 0 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)//中断回调函数,可以理解为中断函数具体要响应的动作
{
HAL_Delay(10);//延时消抖
switch(GPIO_Pin)//switch语句
{
case WK_UP_Pin :
if(WK_UP == GPIO_PIN_SET)//判断按下为高电平
{
BEEP_TOGGLE();//蜂鸣器翻转
break;
}
case KEY0_Pin :
if(WK_UP == GPIO_PIN_RESET)//判断按下为低电平
{
LED0_TOGGLE();//LED0翻转
break;
}
case KEY1_Pin :
if(WK_UP == GPIO_PIN_RESET)//判断按下为低电平
{
LED1_TOGGLE();//LED1翻转
break;
}
}
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
HAL_Delay(1000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
编译下载我们可能会发现没有实验现象产生,这是因为延迟函数属于滴答定时器,默认配置的抢占优先级为15(最低档) ,当在中断回调函数中执行的时候,由于我们配置的中断优先级为2,所以在中断优先级执行的时候,延迟函数虽然被触发,但是无法执行卡住了,所以运行有问题,解决办法就是将滴答定时器的优先级设置比中断优先级高就可以了。
打开图形化配置,按照图中将滴答定时器的优先级设置为1即可。(默认为15)
重新生成代码,编译下载,实验现象正常,即可实现KEY UP控制蜂鸣器响停,KEY1控制LED1翻转,KEY0控制LED0翻转。