一、STM32中断使用
NVIC 中断优先级管理
Nested Vectored Interrupt Controller,嵌套向量中断控制器。
CM3支持256个中断,16个内核中断,240个外部中断,256级可编程中断设置。
STM32使用了其中一部分,16个内核中断,107系列有68个可屏蔽中断(103系列只有60个),16级可编程的中断优先级。
中断寄存器
ISER[8],Interrupt Set-Enable Registers,中断使能寄存器组,用8个32位寄存器控制(256个可编程中断),每个位控制一个中断。由于STM32f103只有60个可屏蔽中断,于是只用了 ISER[0] 和 ISER[1] 64个中断中的前60位。
ISER[0] 的 bit0 至 bit31 对应中断0至31,ISER[1] 的 bit0 至 bit27 对应中断32至59,使能某个中断就将对应的 ISER 置1
ICER[8],Interrupt Clear-Enable Register,中断除能寄存器组。中断对应与ISER相同,但作用是置1清除中断使能
ISPR[8],Interrupt Set-Pending Register,中断挂起控制寄存器组。置1将正在进行的中断挂起,暂停等待执行,执行同级或更高级别的中断
ICPR[8],Interrupt Clear-Pending Register,中断解挂控制寄存器组,置1将挂起的中断解挂
IABR[8],Interrupt Active Bit Register,中断激活标志位寄存器组,只读寄存器,为1表示该位对应的中断正在被执行
IP[240],Interrupt Priority Registers,中断优先级控制寄存器组,相当重要! STM32的中断分组与其密切相关。
IP[240]有240个8bit寄存器组成,每个可屏蔽中断占用8bit,总共可表示240个可屏蔽中断,STM32f1使用其中60个,IP[59]至IP[0]分别对应中断59至0。每个可屏蔽中断只用高4位,分为抢占优先级和响应优先级,抢占优先级在前、响应优先级在后,各占几位由SCB->AIRCR中的中断分组设置。采用库函数==NVIC_PriorityGroupConfig () ==配置。
如果组设置为3,则每个中断的中断优先寄存器高4位中前3位是抢占优先级,优先级级别0-7;低1位是响应优先级,优先级级别0-1。
STM32的中断向量有抢占属性和响应属性,属性编号越小,优先级别越高。
抢占属性是打断其他中断的属性,有这个属性就有嵌套中断。由库函数NVIC_IRQChannelPreemptionPriority() 进行参数配置。
响应属性应用在抢占属性相同时(前提),两个中断向量的抢占优先级相同时,如果同时到达,则优先处理响应优先级高的中断。由库函数NVIC_IRQChannelSubPriority() 进行参数配置。
先建立新工程,选择自己的芯片,然后点击start project
修改RCC的设置,将High Speed Clock选择为“Crystal......”
修改SYS,将Debug选择“Serial Wire”
点击GPIO,选择管脚,这里我选择PB5为我的led管脚并设置为GPIO_Output,再将PA1设置为 GPIO_EXTI1.
设置PA1如图
设置PB5如图
点击NVIC并进行如下修改
修改时钟,修改如图所示
接下来生成工程和代码就行了
在keil5里面打开刚刚建立好的工程,并修改main函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
/* Prevent unused argument(s) compilation warning */
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_5);
/* NOTE: This function Should not be modified, when the callback is needed,
the HAL_GPIO_EXTI_Callback could be implemented in the user file
*/
}
最终结果
二、串口中断实现串口通信
1.创建工程,选择芯片;
2.修改RCC
3.设置USART1,点击Mode,选择Asynchronous设置中断,在NVIC Settings中点击Enabled
修改时钟
创建,生成代码
打开工程,修改代码
在stm32f1xx_hal.c文件添加头文件
#include <stdio.h>
extern UART_HandleTypeDef huart1; //声明串口
重新改写fget和fput函数
/**
* 函数功能: 重定向c库函数printf到DEBUG_USARTx
* 输入参数: 无
* 返 回 值: 无
* 说 明:无
*/
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
return ch;
}
/**
* 函数功能: 重定向c库函数getchar,scanf到DEBUG_USARTx
* 输入参数: 无
* 返 回 值: 无
* 说 明:无
*/
int fgetc(FILE *f)
{
uint8_t ch = 0;
HAL_UART_Receive(&huart1, &ch, 1, 0xffff);
return ch;
}
在修改main函数
printf("hello windows!\r\n");
HAL_Delay(1000);
添加定义,接收串口数据
#include "stdio.h"
#include <string.h>
#define RXBUFFERSIZE 256 //最大接收字节数
char RxBuffer[RXBUFFERSIZE]; //接收数据
uint8_t aRxBuffer; //接收中断缓冲
uint8_t Uart1_Rx_Cnt = 0; //接收缓冲计数
在主函数main.c文件中添加开启接收中断的语句
HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1);
添加中断回调函数
/* 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;
memset(RxBuffer,0x00,sizeof(RxBuffer));
HAL_UART_Transmit(&huart1, (uint8_t *)"数据溢出", 10,0xFFFF);
}
else
{
RxBuffer[Uart1_Rx_Cnt++] = aRxBuffer; //接收数据转存
if((RxBuffer[Uart1_Rx_Cnt-1] == 0x0A)&&(RxBuffer[Uart1_Rx_Cnt-2] == 0x0D)) //判断结束位
{
HAL_UART_Transmit(&huart1, (uint8_t *)&RxBuffer, Uart1_Rx_Cnt,0xFFFF); //将收到的信息发送出去
while(HAL_UART_GetState(&huart1) == HAL_UART_STATE_BUSY_TX);//检测UART发送结束
Uart1_Rx_Cnt = 0;
memset(RxBuffer,0x00,sizeof(RxBuffer)); //清空数组
}
}
HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1); //再开启接收中断
}
/* USER CODE END 4 */
烧录仿真
三、STM32采用串口DMA方式发送数据
建立工程,选择芯片
修改SYS,在Debug中选择Serial....
在RCC中把High Speed Clock设置为Crystal/Ceramic
在Connectivity中选择YUSART1,勾选如下
在点击DMA Setting中的Add,添加如下
修改时钟如下:
生成代码:
打开工程在main函数里添加代码
uint8_t Senbuff[] = "Hello windows!\n"; //定义一个数组,将想要发送的数据放到数组中去
同时在main函数的里在添加代码
HAL_UART_Transmit_DMA(&huart1,Senbuff, sizeof(Senbuff));
HAL_Delay(1000);
添加成功之后编译,生成hex文件。如下图,编译没有出差。
烧录仿真
完成。
四、资料链接
https://blog.csdn.net/xwj2633673783/article/details/112749476
https://blog.csdn.net/as480133937/article/details/104827639/
https://www.cnblogs.com/breezy-ye/articles/12157442.html
五、总结
本次实验内容较多,但是相对来说还是比较简单的,通过参考学习各位大佬的博客和积极查阅资料解决了我很多问题(当然还有百度yyds)