所有可用资源可在我的gitee仓库查找,点击即可前往。

一、前言

本篇文章继续介绍stm32的一些基本使用,文章主要是介绍外部中断的使用,同样以按键控制LED灯为例,之前我用查询方式来实现的,这篇文章尝试用中断的方式实现,废话不多说,咱们开始。

二、准备工作

硬件:

  • stm32F103C8T6开发板
  • ST-LINK V2下载器一个
  • 3~5V的LED灯(发光二极管)一个
  • 四引脚按键一个
  • 杜邦线若干+面包板

软件:

其他(需要自行下载,点击前往,下载template文件即可):

  • stm32工程模板(由于新建模板比较麻烦,初学还是找个工程模板吧,方便点)

电路图:
风行男孩

三、编写代码

为了方便对比,我这里先给出用查询方式实现LED灯开关的代码,对比可以发现,在查询方式中Turn_LED函数是写在while循环里面的,而在中断方式里是写在中断函数里面的。

3.1用查询方式实现LED开关

#include "stm32f10x.h"
#include "delay.h"

uint8_t flag1 = 0;  //表示是否按下的标志位
uint8_t is_led_turn = 0;  //LED灯状态标志位默认为关

void Trun_LED(void);  //开灯关灯

void Trun_LED(void){
	if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14) == 0){
		flag1 = 1;  //表示按下
		Delay(50);
		if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14) == 1 && flag1 == 1){
			// 取反状态:如按下前为关则置为开,反之亦然
			is_led_turn = !is_led_turn;
			GPIO_WriteBit(GPIOB, GPIO_Pin_10, is_led_turn == 1 ? Bit_SET : Bit_RESET);
			flag1 = 0;  // 重置
		}
	}
}

int main(void)
{
	//按键引脚初始化
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_14;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;  //设置为输入上拉模式
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
	
	GPIO_Init(GPIOB, &GPIO_InitStruct);
  //初始化连接LED的引脚
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;  //设置为输出推挽模式
	GPIO_ResetBits(GPIOB, GPIO_Pin_10);
	
	GPIO_Init(GPIOB, &GPIO_InitStruct);
	
	while(1){
		Trun_LED();
	}
}

上面就是用查询方式实现的当个按键开关控制LED,也挺丝滑的哈。

3.2用中断方式实现LED开关

在stm32中使用中断我感觉还是有点麻烦,大概就以下的步骤:开启时钟 -> 配置GPIO和AFIO -> 配置EXTI -> 配置NVIC -> 配置中断函数,大概就这些了。

#include "stm32f10x.h"
#include "delay.h"

uint8_t is_led_turn = 0;  //LED灯状态标志位默认为关

void Turn_LED(void);  //开灯关灯
void Key_Init(void);  //初始化中断
void EXTI0_IRQHandler(void);  //中断函数

void Key_Init(void){
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
	
	//配置AFIO
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);
	
	//配置EXTI
	EXTI_InitTypeDef EXTI_InitStructure;
	EXTI_InitStructure.EXTI_Line = EXTI_Line14;
	EXTI_InitStructure.EXTI_LineCmd = ENABLE; 
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿出发
	EXTI_Init(&EXTI_InitStructure);
	
	//配置NVIC
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  //抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;  //响应优先级
	
	NVIC_Init(&NVIC_InitStructure);
}

// 这里注意
// GPIO引脚0~4使用的是独立中断线Line0~4,Line5-9是同一中断线,Line10-15同一中断线
// 如果使用的是同一中断线,下面的函数名相应的改动,如EXTI0_IRQHandler()
void EXTI15_10_IRQHandler(void){ //配置中断函数函数
	if(EXTI_GetITStatus(EXTI_Line14) == SET){ //中断标志判断
		Delay(10);
		Turn_LED();
	}
	 EXTI_ClearITPendingBit(EXTI_Line14); // 清除标志位
}

void Turn_LED(void){
	//按键按下
	if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14) == 0){
		// 取反状态:如按下前为关则置为开,反之亦然
		is_led_turn = !is_led_turn;
		GPIO_WriteBit(GPIOB, GPIO_Pin_10, is_led_turn == 1 ? Bit_SET : Bit_RESET);
		//等待松开,防止重复进入中断(学习使用,工作中应避免这种用法)
		while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14) == 0);  
		Delay(10);
	}
}

int main(void)
{
	//按键引脚初始化
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_14;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;  //设置为输入上拉模式
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	
	GPIO_Init(GPIOB, &GPIO_InitStruct);
  //初始化连接LED的引脚
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;  //设置为输出推挽模式
	GPIO_ResetBits(GPIOB, GPIO_Pin_10);
	
	GPIO_Init(GPIOB, &GPIO_InitStruct);
	
	Key_Init();  //初始化中断
	
	while(1){
		//Turn_LED();
	}
}

四、结束语

好了,stm32的基本使用——外部中断的使用先介绍到这,后续有时间我继续更新这方面的文章,敬请期待,我是“风行男孩”,咱有缘再见!(码字不易,转载请标明出处!若是文章有帮助,点个赞留个痕迹即可。)

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐