基于HAL库的STM32外部中断模式

基于HAL库的STM32外部中断模式

板子:STM32F103C8

编译工具:Keil&STM32CubeMX

烧录工具:FlyMcu
串口调试工具:XCOM

文章目录

  • 基于HAL库的STM32外部中断模式
    • 〇、什么是中断
      • 1. 数据输出方式
      • 2. 中断过程
      • 3. 中断程序执行过程
      • 4. 作用
      • 5. 中断优先级
      • 6. 中断向量
    • ------中断控制LED灯亮灭------
    • 一、STMCubeMX配置项目
      • 1. 引脚配置
      • 2. GPIO与NVIC设置
      • 3. 生成项目
    • 二、Keil配置代码
    • 三、实际效果
    • --------中断串口通信--------
    • 四、STMCubeMX配置项目
      • 1. 设置引脚
      • 2. 使能USERT1中断
      • 3. 生成项目
    • 五、Keil配置代码
    • 六、实际效果
    • 七、总结
    • 八、参考文章

〇、什么是中断

指处理机处理程序运行中出现的紧急事件的整个过程.程序运行过程中,系统外部、系统内部或者现行程序本身若出现紧急事件,处理机立即中止现行程序的运行,自动转入相应的处理程序(中断服务程序),待处理完后,再返回原来的程序运行,这整个过程称为程序中断;当处理机接受中断时,只需暂停一个或几个周期而不执行处理程序的中断,称为简单中断.
中断又可分为屏蔽中断和非屏蔽中断两类.可由程序控制其屏蔽的中断称为屏蔽中断或可屏蔽中断.屏蔽时,处理机将不接受中断.反之,不能由程序控制其屏蔽,处理机一定要立即处理的中断称为非屏蔽中断或不可屏蔽中断.非屏蔽中断主要用于断电、电源故障等必须立即处理的情况.处理机响应中断时,不需执行查询程序.由被响应中断源向CPU发向量地址的中断称为向量中断,反之为非向量中断.向量中断可以提高中断响应速度。

1. 数据输出方式

处理器和外部设备的数据传输方式:
① 无条件传输处理器不必了解外部设备状态,直接进行数据传输,用于指示灯和按键等简单设备

② 查询方式传输前,一方先查询另一方的状态,若已经准备好就传输,否则就继续查询

③ 中断方式一方通过申请中断的方式与另一方进行数据传输,收发双方可以并行工作

④ 直接存储器访问处理器内部建立片内外设和内存之间的数据传输通道,传输过程不需要处理器参与

2. 中断过程

中断发生:当CPU在处理某一事件A时,发生了另一事件B,请求CPU迅速去处理
↓↓↓↓↓↓↓↓
中断处理:CPU暂停当前的工作,转去处理事件B
↓↓↓↓↓↓↓↓
中断返回:当CPU将事件B处理完毕后,再回到事件A中被暂停的地方继续处理事件A

3. 中断程序执行过程

基于HAL库的STM32外部中断模式_第1张图片

4. 作用

  • 可以解决快速的CPU与慢速的外部设备之间的传送数据的矛盾。
  • CPU可以分时为多个外部设备服务,提高计算机的利用率。
  • CPU能够及时处理应用系统的随机事件,增强系统的实用性。
  • CPU可以处理设备故障及掉电等突发事件,提高系统可靠性。

5. 中断优先级

处理器根据不同中 断的重要程序设置 不同的优先等级。 不同优先级中断的 处理原则是:高级 中断可以打断低级 中断;低级中断不 能打断高级中断。

6. 中断向量

中断服务程序:在响应一个特定中断的时候,处理器会执行一个函数,该函数一般称为中断处理程序或者中断服务程序

中断向量和中断向量表:

  • 中断向量:中断服务程序在内存中的入口地址称为中断向量。
  • 中断向量表:把系统中所有的中断向量集中起来放到存储器的某一区
    域内,这个存放中断向量的存储区就叫中断向量表

------中断控制LED灯亮灭------

一、STMCubeMX配置项目

1. 引脚配置

  • A6输出控制LED灯的亮灭,所以为GPIO_Output
  • A4持续输出高电平,同上
  • B0持续输出低电平,同上
  • B5模拟按钮,设置为GPIO_Exit5

基于HAL库的STM32外部中断模式_第2张图片

2. GPIO与NVIC设置

  • B5引脚的GPIO mode设置为Rising/Falling
    基于HAL库的STM32外部中断模式_第3张图片

  • A4设置为高电平输出,A6B0不管,因为CubeMX默认设置是低电平
    基于HAL库的STM32外部中断模式_第4张图片

  • 设置用户标签,方便写代码。这一步看自己,我不推荐,因为不是每一个人的CubeMX都可以成功生成对应代码
    基于HAL库的STM32外部中断模式_第5张图片

笔者在这里使用了用户标签来写函数但报错了,原因是未声明,但是按理来说CubeMX应该在生成代码时用#define声明了这几个标签,可是没有,所以我也不建议非要用用户标签来写代码。

  • NVIC中勾选EXTI line[9:5] interrupts

基于HAL库的STM32外部中断模式_第6张图片

3. 生成项目

因为本次使用到的是Keil,所以我们在IDE这一栏要选择MDK-ARM,Version选择V5及以上。其他的不再多说
基于HAL库的STM32外部中断模式_第7张图片
这里记得勾选,用于创造一些必要的头文件

基于HAL库的STM32外部中断模式_第8张图片

二、Keil配置代码

生成Keil代码后点击Open project来到keil界面:

  • 点击stm32f1xx_hal_gpio.c文件可以找到中断服务函数
    基于HAL库的STM32外部中断模式_第9张图片
    右键点击stm32f1xx_hal_gpio.c,选择F12,进入该函数声明部分,往下划,找到HAL_GPIO_EXTI_Callback
    基于HAL库的STM32外部中断模式_第10张图片
    这个函数是回调函数,前面__weak表示此函数为虚函数,需要用户重写。

  • 在里面重写下列代码

    void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
     
      if(GPIO_Pin == GPIO_PIN_5){
     
        //获取B5的电位
        GPIO_PinState pinState = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_5);

        //低电位
        if(pinState==GPIO_PIN_RESET)
        HAL_GPIO_WritePin(GPIOA,GPIO_PIN_6,GPIO_PIN_RESET);//把A6变为低电位
        //高电位
        else
            HAL_GPIO_WritePin(GPIOA,GPIO_PIN_6,GPIO_PIN_SET);//把A6变为高电位
        }
    }
  • 编译生成.hex文件,烧录

在此之前记得配置一下魔法棒!

三、实际效果

--------中断串口通信--------

四、STMCubeMX配置项目

1. 设置引脚

根据F103C8原理图,得知PA9,PA10分别负责串口1的发送和接收
基于HAL库的STM32外部中断模式_第11张图片
所以将PA9,PA10引脚的TXD,RXD激活
基于HAL库的STM32外部中断模式_第12张图片

2. 使能USERT1中断

基于HAL库的STM32外部中断模式_第13张图片

3. 生成项目

步骤和配置LED一致,不再叙述。

五、Keil配置代码

  • main.c中添加以下声明
uint8_t aRxBuffer;			//接收中断缓冲
uint8_t Uart1_RxBuff[256];		//接收缓冲
uint8_t Uart1_Rx_Cnt = 0;		//接收缓冲计数
uint8_t	cAlmStr[] = "数据溢出(大于256)\r\n";
  • int main(void){}之后找到如下位置修改代码
    基于HAL库的STM32外部中断模式_第14张图片
/* USER CODE BEGIN 4 */
/**
  * @brief  Rx Transfer completed callbacks.
  * @param  huart pointer to a UART_HandleTypeDef structure that contains
  *                the configuration information for the specified UART module.
  * @retval None
  */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
     
  /* Prevent unused argument(s) compilation warning */
  UNUSED(huart);
  /* NOTE: This function Should not be modified, when the callback is needed,
           the HAL_UART_TxCpltCallback could be implemented in the user file
   */
 
	if(Uart1_Rx_Cnt >= 255)  //溢出判断
	{
     
		Uart1_Rx_Cnt = 0;
		for(int i=0;i<255;i++)
		{
     
			Uart1_RxBuff[i]=0;
		}
		HAL_UART_Transmit(&huart1, (uint8_t *)&cAlmStr, sizeof(cAlmStr),0xFFFF);	
	}
	else
	{
     
		Uart1_RxBuff[Uart1_Rx_Cnt++] = aRxBuffer;   //接收数据转存
	
		if((Uart1_RxBuff[Uart1_Rx_Cnt-1] == 0x0A)&&(Uart1_RxBuff[Uart1_Rx_Cnt-2] == 0x0D)) //判断结束位
		{
     
			HAL_UART_Transmit(&huart1, (uint8_t *)&Uart1_RxBuff, Uart1_Rx_Cnt,0xFFFF); //将收到的信息发送出去
			Uart1_Rx_Cnt = 0;
			for(int i=0;i<255;i++)
		    {
     
			    Uart1_RxBuff[i]=0;
		    } //清空数组
		}
	}
	
	HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1);   //再开启接收中断
}
/* USER CODE END 4 */
  • 编译烧录

六、实际效果

七、总结

通过中断操作可以更加灵活地使用程序,如果有必要还能够设置优先级使程序能够优先处理紧急任务。

八、参考文章

https://blog.csdn.net/ChenJ_1012/article/details/120962950

https://blog.csdn.net/qq_45659777/article/details/121110712

你可能感兴趣的:(嵌入式系统,stm32,单片机,arm)