目录
一、中断的介绍
1.1 单片机的中断
中断,在单片机中占有非常重要的地位。代码默认地从上向下执行,遇到条件或者其他语句,会按照指定的地方跳转。而在单片机执行代码的过程中,难免会有一些突发的情况需要处理,这样就会打断当前的代码,待处理完突发情况之后,程序会回到被打断的地方继续执行。
1.2 STM32的中断
几乎任何一款单片机都会有中断。以STM32F103来说,这是一款基于Cortex-M3内核的芯片,在CM4内核中有关于中断的一些管理,在STM32芯片中也有关于中断的一些管理。因此可以总结出一条规律,STM32的中断是有两层控制器分别控制的,如果你想使用中断,那么必须同时配置内核和芯片。
从内核架构图可以看到,NVIC控制器来管理内核中的中断。内核对中断的控制主要表现为几个方面:中断地址、中断优先级、中断使能
1.2.1 中断地址
程序的执行无非就是寻找地址,中断也是程序的一部分,而它的地址却是由内核来确定的,而且是不允许修改的。NVIC控制器可以帮我们找到中断的地址
1.2.2 中断优先级
优先级在中断里是一个非常重要的概念,如果同时产生多个中断,CPU会根据他们的优先级来选择这些中断的处理顺序。在CM4内核中,优先级用整数来表示,这个数越小代表级别越高。
1.2.3 中断使能
NVIC对中断有总控的功能,因此这里会有一个开关决定中断功能能否被开启
- STM32外部中断
外部中断只是中断的一种,一般由IO口的电平信号变化而引起。STM32有23个用于产生事件/中断请求的边沿检测器。每根输入线都可以单独配置,可以选择类型(中断或事件)和相应的触发事件(上升沿触发、下降沿触发、边沿触发)。每根线还可以单独配置。
- 中断框架
从上图可以看出外部中断的配置方法:
1)打开对应的APB时钟
2)选择外部中断输入线
3)设置中断的触发方式
4)选择工作模式(外部中断、事件)
5)使能
- 外部中断选择
1.3 中断的过程
中断的步骤又中断发生、中断处理、中断返回执行的过程如下图
下图是中断程序的执行流程图
二、通过中断实现LED的控制
2.1 HAL库代码生成
- 在Patr Number中找到stm32f103c8,并双击选择芯片
- 点击sys,选择Serial Wire
- 点击RCC,选择Crystal/Ceramic Resonator
- 点击芯片接口,将PA1作为输出,选择为GPIO_Output,PB0作为中断口,选择为GPIO_EXIT0
- 选则Clock Configuration配置时钟,然后将后面的晶振频率最大值改为72M赫兹
- 选择GENERATE CODE生成代码
2.2 代码配置
打开自动生成Kei工程,打开主函数文件main.c,在其中添加以下函数代码。
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
GPIO_PinState b0_pin = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0); // 读取b0的状态
b0_pin = 1 - b0_pin;
switch (GPIO_Pin){//判断引脚
case GPIO_PIN_0:
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1,1 - b0_pin); // 将a1写入与b0相同的电位
break;
}
}
- 效果展示
三、通过HAL库实现串口通信
3.1 使用STM32CubeMX生成代码
- 在CubeMX中选择工程,选择芯片stm32f103c8后,RCC设置如下
- SYS设置如下
- USART1设置为异步模式,并使能中断
USART1 参数配置如下
设置DMA
时钟改为72MHz
3.2 代码
打开Cube生成的工程,打开main.c文件,更改以下代码
uint8_t aRxBuffer; //接收中断缓冲
uint8_t Uart1_RxBuff[256]; //接收缓冲
uint8_t Uart1_Rx_Cnt = 0; //接收缓冲计数
uint8_t cAlmStr[] = "数据溢出(大于256)\r\n";
/* USER CODE BEGIN 2 */
HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1);
/* USER CODE END 2 */
/* USER CODE BEGIN 4 */
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 */c
3.3 效果展示
四、总结
本次实验采用了中断模式编程,反别通过中断控制了led并且通过中断实现了串口通信,中断程序在单片机程序中非常重要,通过中断可以更加灵活地处理程序,以后还需要继续学习中断的使用。