基本串口通信通常只能接收到定长数据,无法稳定接收不定长数据,本章介绍利用stm32单片机的idle空闲中断,接收不定长数据。
使能串口1的异步串行通信模式,开启usart1的全局中断。添加dma通道。
使用stm32cubemx生成源码, 打开生成的源码,删除whiel循环中的语句。
打开usart.h文件,在文件开头的user code begin includes下方引入stdio.h头文件
打开usart.c文件,在user code begin 0与 user code end 0之间添加下列代码。
#if 1 struct __file { int handle; };
file __stdout; //定义_sys_exit()以避免使用半主机模式 void _sys_exit(int x) { x = x; } //重定义fputc函数int fputc(int ch, file *f){ while((usart1->sr&0x40)==0);//循环发送,直到发送完毕 usart1->dr=(uint8_t)ch; return ch;}#endif
打开uart.c文件,在文件顶部的user code begin 0下方添加下列变量。
volatile uint8_t rx1_len = 0; //接收一帧数据的长度volatile uint8_t rec1_end_flag = 0; //一帧数据接收完成标志uint8_t rx1_buffer[buffer_size]={0}; //接收数据缓存数组
打开uart.c文件,在文件末尾的user code begin 1下方添加下列函数。
void usart1_idle(void) //usart1的idle接收{ uint32_t tmp_flag = 0; uint32_t temp; tmp_flag =__hal_uart_get_flag(&huart1,uart_flag_idle); //获取idle标志位 if((tmp_flag != reset))//idle标志被置位 { __hal_uart_clear_idleflag(&huart1);//清除标志位 hal_uart_dmastop(&huart1); // 停止dma传输,防止 temp = __hal_dma_get_counter(&hdma_usart1_rx);// 获取dma中未传输的数据个数 rx1_len = buffer_size - temp; //总计数减去未传输的数据个数,得到已经接收的数据个数 rec1_end_flag = 1; // 接受完成标志位置1 }}
void usart1_handle() //usart1对接收的一帧数据进行处理{ dma_usart1_send(rx1_buffer, rx1_len); //将接收到的数据回发给发送端 rx1_len = 0;//清除计数 rec1_end_flag = 0;//清除接收结束标志位 hal_uart_receive_dma(&huart1,rx1_buffer,buffer_size);//重新打开dma接收}
void dma_usart1_send(uint8_t *buf,uint8_t len) //串口发送封装{ if(hal_uart_transmit_dma(&huart1,buf,len)!= hal_ok) //判断是否发送正常,如果出现异常则进入异常中断函数 { error_handler(); }}
打开usart.h文件,在文件开头的user code begin includes下方添加如下语句:
#include stdio.h#include string.h#define buffer_size 100
extern volatile uint8_t rx1_len; //接收一帧数据的长度extern volatile uint8_t rec1_end_flag; //一帧数据接收完成标志extern uint8_t rx1_buffer[buffer_size]; //接收数据缓存数组
void usart1_handle(void);void dma_usart1_send(uint8_t *buf,uint8_t len);//串口发送封装void usart1_idle(void);
进入main.c文件,找到入口函数void mian(void), 在user code begin 2下方开启串口1的dile中断,并打开dma接收。
__hal_uart_enable_it(&huart1, uart_it_idle); //使能idle中断 hal_uart_receive_dma(&huart1,rx1_buffer,buffer_size); //开启dma接收
在while语句中添加接收查询语句。
if(rec1_end_flag) //判断是否接收到1帧数据{ usart1_handle(); //前往数据处理函数处理接收到的数据。}
打开stm32f4xx_it.c文件,在文件开头引入usart.h头文件。
向下翻stm32f4xx_it.c文件,找到void usart1_irqhandler(void)函数,此函数为串口1的中断入口函数。在此函数中添加之前在usart.c文件中创建的idle接收函数。
源码修改完毕后,编译下载,打开串口助手,随意发送100个字节以内的任意长度内容进入单片机,都可得到同样的回复。
Fluke Ti450 SF6气体检漏热像仪,定位泄漏,隐患无处遁形
国企程序员的总结
什么是web服务器?如何选择服务器配置?
揭秘快速充电,这四个阶段将是如何突破
ccd传感器及其原理
STM32CubeMX之串口接收不定长数据
联发科发出声明否认与小米结束合作的传闻
FreeRTOS源代码结构与基本目录
企业利益怎样用区块链技术来增加
基于Linux服务器和VLAN实现策略路由的技术方案
Maxim推出DirectDrive耳机放大器
rs485集线器使用说明书详解
freemodbus教程之freemodbus移植应用串口中断接收和数据解析
MCU助力物联网快速发展
基于DA14531 BLE SoC的低功耗蓝牙信标系统
基于STC12C5A60S2单片机中的AD采样实时采样用于检测电路是否正常的设计
HONEYWELL霍尼韦尔传感器芯片推出了一种新的自诊断传感器
长安新能源空气净化技术车展吸睛
全新IC产品系列—SENZero
关于FPGA的分析和介绍以及应用