目录
1. void USART1_IRQHandler(void);
2. void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
3. HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
4. HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size)
一、STM32CubeMX生成工程
1. 选择stm32f03c8t6芯片
2. 配置RCC
3. 配置sys
4. 配置UART1
5. 配置时钟
6. 工程配置
最后点击生成代码即可
二、串口中断函数介绍(以串口1为例)
一般流程:
1. void USART1_IRQHandler(void);
当发生中断的时候,程序就会执行中断服务函数。然后我们在中断服务函数中编写们相应
该函数在stm32f1xx.it.c里面,可以查看一下该函数定义:
可以看出,当串口1产生中断,就会进入该函数,该函数内部可以自己定义内容,默认的是调用HAL_UART_IRQHandler(&huart1)函数,因此我们在编写逻辑代码的时候,可以在后者函数中实现。
2. void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
该函数只有一个入口参数就是 UART_HandleTypeDef 结构体指针类型的串口句柄 ,是用来指明是哪个串口的触发中断。该函数一般在中断服务函数中调用,作为串口中断处理的通用入口。也就是说,真正的串口中断处理逻辑我们会最终在函数HAL_UART_IRQHandler 内部执行。该函数定义在stm32f1xx.hal_uart.c里面,该函数的功能是对接收到的数据进行判断和处理 判断是发送中断还是接收中断,然后进行数据的发送和接收。
3. HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
第二步中可以判断是接收信息产生中断还是发送信息产生中断,从而调用对应的中断函数,该函数就是接收中断函数,该函数的功能是将串口接收到大小为RXBUFFERSIZE的8bit数据保存到地址为 aRxBuffer的地方。
因此在使用该函数的时候,需要知道接收的大小,还需要定义一个数组来保存接收到的值,如:
uint8_t size=5;
char ReBuff[5];
HAL_UART_Receive_IT(&huart1, (uint8_t *)&ReBuff,size);
这样就将接收端到的五个8bit信息保存到Rebuff里面,但是这里有些不足,当不知道发送端发送的信息大小时,无法填写size的大小,解决此办法的方法是重写printf 和scanf函数。
调用该函数后,标示接收结束,进入回调函数HAL_UART_RxCpltCallback函数进行对应处理。
4. HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size)
该函数的功能是通过串口发送大小为Size的字符数据,以中断模式发送数据。函数会检查UART的状态,如果当前有正在进行的发送操作,则返回忙碌状态。然后,它会检查传入的数据缓冲区指针和数据大小是否合法,如果不合法,则返回错误状态。如果参数合法,函数会设置UART句柄结构体中的成员变量,并根据UART的FIFO模式和数据长度选择相应的中断服务程序的函数指针,并使能相应的中断。最后,函数返回状态值表示发送操作的启动状态。
同样,如果使用串口1发送数据可以如下定义:
uint8_t size=5;
char SendBuff[5]="abcde"
HAL_UART_Transmit_IT(&huart1, (uint8_t *)&SendBuff,size);
三、串口中断程序思路与编写
1. 程序思路
STM32系统给上位机(win10)连续发送“hello windows!”;当上位机给stm32发送字符“stop”后,stm32暂停发送“hello windows!”;发送一个字符“start”后,stm32继续发送。
单片机首先需要开启接收中断,即调用HAL_UART_Receive_IT函数,当单片机接收到数据完成后,就调用中断回调函数HAL_UART_RxCpltCallback,可以编写逻辑,判断接收的字符是否为start,如果是就通过中断给PC机发送一个字符start,并置flag=1(在主函数循环中,flag=1,每隔1s给PC发送一次“Hello Windows!\n”),如果是stop,置flag=0。
2. 程序编写
1. 接收回调函数编写
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance==USART1)
{
if(StringCompare(ReBuff,start)==1)
{
flag=1;
HAL_UART_Transmit_IT(&huart1,(uint8_t *)start,5);
}
else if(StringCompare(ReBuff,stop)==1)
{
flag=0;
HAL_UART_Transmit_IT(&huart1,(uint8_t *)stop,5);
}
HAL_UART_Receive_IT(&huart1, (uint8_t *)&ReBuff,5);
}
}
2. 主函数编写
uint8_t flag;
char ReBuff[5];
char SendBuff[16]="Hello Windows!\n";
char start[5]="start";
char stop[5]="stop ";
void SystemClock_Config(void);
int StringCompare(char rcData[5],char rcData2[5]){
for(uint8_t i = 0 ; i < 5 ; i++){
if (rcData[i] != rcData2[i]) return 0;
}
return 1;
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
HAL_UART_Receive_IT(&huart1, (uint8_t *)&ReBuff, 5);
while (1)
{
if(flag==1)
{
HAL_UART_Transmit_IT(&huart1,(uint8_t *)SendBuff,16);
HAL_Delay(1000);
}
}
}
四、运行效果,仿真计算波特率
1. 实物效果
2. 仿真
仿真查看时序和波特率
修改一下主函数的循环
while (1)
{
HAL_UART_Transmit_IT(&huart1,(uint8_t *)SendBuff,16);
HAL_Delay(1000);
}
仿真查看波形需要修改一下源码,直接在while1中调用流水灯程序,查看电平持续时间,仿真需要的MDK配置:
波形:
输出:
由于发送了160个bit,那么波特率为:
这里与我们设置的波特率115200误差相差1500hz
五、总结与参考
1. 通过该实验,完成了中断方式的串口通信,掌握了中断串口方式配置的流程,还有一些中断的函数。
2. 实验结果分析:从实物效果,通过串口调试助手的方式,和我们设想的目标一样,当发送start时,开始通信,发送stop时,单片机就停止给PC机发送信息。实物效果还是很明显的。通过仿真的方式,查看仿真输出,的确是和我们的结果是一样的。那么可以判断其时序图也是正确的,但是在这上面不好看出具体的某一个字符。其波特率的计算方式是通过计算发送16个字符,即160个bit总共花费时间,通过上面的标线来查看,误差还是很大,相差1500hz,可能是仿真本身存在的问题,或者在标线的时候没有很准确。
3. 该方式相比之前的轮询方式,占用CPU资源低,效率高。
参考:
STM32 HAL库函数——HAL_UART_Transmit_IT()详解-优快云博客
STM32学习笔记-SMT32使用HAL库UART中断方式使用_hal_uart_rxcpltcallback_楚云歌的博客-优快云博客
源码下载:
交流群 :456948834