[STM32]STM32双机串口通信
[STM32]STM32双机串口通信
上一篇的通信方案在发送端高强度通信下寄了,发现是函数HAL_UART_Transmit()的锅,一个函数居然能跑0.3s左右。。。于是打算选用DMA收发数据,但是DMA在接收数据时遇到一些玄学问题,于是改用DMA发送数据,串口IDLE中断接收数据的策略。
cubeMX配置
接收端部分
开启USART1,打开全局中断。
发射端部分
开启USART1,开启全局中断,打开TX的DMA通道,为normal模式,内存地址自增,并打开DMA_TX的中断。
代码部分
接收端
usart.c:
/* USER CODE BEGIN 0 */
#include "string.h"
#include "main.h"
uint8_t aRxBuffer;
uint8_t Uart_RxBuff[256];
uint8_t Uart_Rx_Cnt;
uint8_t Uart_RxFlag;
uint8_t cAlmStr[] = "Warning!\r\n";
int rxUpdateFlag = 0;
int startReadFlag = 0;
/* USER CODE END 0 */
/* USER CODE BEGIN 1 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(huart);
if(huart == &huart1 && rxUpdateFlag == 0)
{
if(Uart_Rx_Cnt >= 255) // 溢出判断
{
Uart_Rx_Cnt = 0;
memset(Uart_RxBuff,0x00,sizeof(Uart_RxBuff));
HAL_UART_Transmit(&huart1, (uint8_t *)&cAlmStr, sizeof(cAlmStr),0xFFFF);
}
else // 没有溢出
{
if(aRxBuffer == '@')
{
startReadFlag = 1;
}
if(startReadFlag == 1)
{
Uart_RxBuff[Uart_Rx_Cnt++] = aRxBuffer; // 接收数据转存
if((Uart_RxBuff[Uart_Rx_Cnt-1] == 0x0A)&&(Uart_RxBuff[Uart_Rx_Cnt-2] == 0x0D)) //判断结束
{
startReadFlag = 0;
rxUpdateFlag = 1; // 数据更新
}
}
}
}
HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1); //再开启接收中???
}
/* USER CODE END 1 */
usart.h:
/* USER CODE BEGIN Prototypes */
extern uint8_t aRxBuffer;
extern uint8_t Uart_RxBuff[256];
extern uint8_t Uart_Rx_Cnt;
extern uint8_t Uart_RxFlag;
extern int rxUpdateFlag;
/* USER CODE END Prototypes */
main.c:
/* USER CODE BEGIN Includes */
#include "string.h"
#include "stdio.h"
/* USER CODE END Includes */
/* USER CODE BEGIN PV */
char rxStr[256];
char drawBuffer1[256]; // 提取出的数据变量
char drawBuffer2[256];
char drawBuffer3[256];
/* USER CODE END PV */
/* USER CODE BEGIN PFP */
//Not include 'start' and 'end'
void get_Data(const char* str, char* dst, char start, char end)
{
int i = 0, j = 0;
while(str[i++] != start && i<= 40);
while(str[i] != end && i<= 40)
{
dst[j] = str[i];
j++;
i++;
}
dst[j] = '\0';
}
/* USER CODE END PFP */
/* USER CODE BEGIN 2 */
HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1);
/* USER CODE END 2 */
/* USER CODE BEGIN 3 */
if(rxUpdateFlag == 1) // 收到新数据,开始处理数据
{
strcpy(rxStr, (char *)Uart_RxBuff);
//printf("%s\r\n", rxStr);
// 处理数据
get_Data(rxStr, drawBuffer1, 'a', 'b');
get_Data(rxStr, drawBuffer2, 'b', 'c');
get_Data(rxStr, drawBuffer3, 'c', 'd');
// 清除标志位,缓存等
memset(Uart_RxBuff,0x00,sizeof(Uart_RxBuff));
rxUpdateFlag = 0;
Uart_Rx_Cnt = 0;
}
/* USER CODE END 3 */
发射端
- 记住,MX的代码生成完毕后一定要把MX_DMA_Init放到MX_UARTx_UART_Init之前
然后使用HAL_UART_Transmit_DMA函数发送即可。
注意,不要连续调用这个函数,因为DMA搬运数据也是需要时间的,需要判断DMA通道是否空闲再发送。
通信格式:“@axxxxbxxxxcxxxxdxxxx”(xxxx为数字)
[STM32]STM32双机串口通信的更多相关文章
- 嵌入式02 STM32 实验07 串口通信
STM32串口通信(F1系列包含3个USART和2个UART) 一.单片机与PC机串行通信研究目的和意义: 单片机自诞生以来以其性能稳定,价格低廉.功能强大.在智能仪器.工业装备以及日用电子消费产品中 ...
- stm32中的串口通信你了解多少
在基础实验成功的基础上,对串口的调试方法进行实践.硬件代码顺利完成之后,对日后调试需要用到的printf重定义进行调试,固定在自己的库函数中. b) 初始化函数定义: void USART_Confi ...
- stm32 hal库串口通信资料汇集
串口的发送接收函数:HAL_UART_Transmit();串口轮询模式发送,使用超时管理机制.HAL_UART_Receive();串口轮询模式发送,使用超时管理机制.HAL_UART_Transm ...
- stm32与三菱PLC通信
一.三菱PLC通讯概要 三菱PLC FX系列通信结构如下图所示: 三菱PLC FX系列的通信规格如下图所示: 三菱PLC FX系列一般有以下几种通信模块,以FX2N为例: FX2N-232-BD ...
- (三)stm32之串口通信DMA传输完成中断
一.DMA功能简介 首先唠叨一下DMA的基本概念,DMA的出现大大减轻了CPU的工作量.在硬件系统中,主要由CPU(内核).外设.内存(SRAM).总线等结构组成,数据经常要在内存和外设之间,外设和外 ...
- STM32学习笔记:【004】USART串口通信
版本:STM32F429 Hal库v1.10 串口通信能够实现两块电路之间不同的通信,在开发中作为打印调试也是一门利器(printf重定向). 补充一点小知识: 1. weak修饰符修饰的函数,说明这 ...
- Stm32串口通信(USART)
Stm32串口通信(UART) 串口通信的分类 串口通信三种传递方式 串口通信的通信方式 串行通信的方式: 异步通信:它用一个起始位表示字符的开始,用停止位表示字符的结束.其每帧的格式如下: 在一帧格 ...
- STM32 串口通信使用奇偶校验
STM32串口通信如果使用奇偶校验,需要设置数据位长度为9bit USART_InitStructure.USART_BaudRate = 9600; USART_InitStructure.USAR ...
- stm32串口通信实验,一点笔记
第一次深入学习stm32,花了好长时间才看懂代码(主要是C语言学习不够深入),又花了段时间自己敲了一遍,然后比对教程,了解了利用中断来串口通信的设置方法. 板子是探索版f407,本实验工程把正点原子库 ...
- STM32串口通信UART使用
STM32串口通信UART使用 uart使用的过程为: 1. 使能GPIO口和UART对应的总线时钟 2. 配置GPIO口的输出模式 3. 配置uart口相关的基本信息 4. 使能uart口的相关的中 ...
随机推荐
- Linux反空闲的设置和关闭
有一定工作经验的运维人基本都会遇到这样的场景,某个窗口自动断开了,提示超时: [oracle@jystdrac1 ~]$ timed out waiting for input: auto-logou ...
- Delphi-判断一个对象是否释放,改造官方的Assigned
直接上例子了,基础知识自己去了解,首先定义一个类: TPerson = class public name: string; age: Integer; constructor Create(name ...
- Shell中调用可执行文件,手动执行可以执行,crontab执行就报错:exec: java: not found
今天发现一个很奇怪的问题,就是我编写的shell脚本, 手动执行可以正常执行,但是放到crontab中就报错.line 60: exec: java: not found 百度搜索发现原来是java ...
- MFC-ODBC API动态连接配置数据库
一.ODBC管理器介绍 在Window中,ODBC数据远管理器有6个标签:用户DSN.系统DSN.文件DSN.驱动程序.跟踪.连接池,通常情况下,使用用户DSN或者系统DSN,这里主要了解用户DSN和 ...
- .NET周刊【2月第2期 2024-02-11】
国内文章 C#/.NET该如何自学入门? https://www.cnblogs.com/Can-daydayup/p/18006914 随着DotNetGuide技术社区交流群的扩大,很多新成员希望 ...
- 【framework】WindowContainer简介
1 前言 WindowContainer 继承自 ConfigurationContainer,是 WMS 家族的重要基类.ConfigurationContainer简介 中,已介绍 Confi ...
- 用ELK分析每天4亿多条腾讯云MySQL审计日志(2)--EQL
上一篇介绍了用ELK分析4亿多条审计日志过程,现在介绍如何用Python3分析ES的程序 需要分析的核心库审计数据: 1,950多张表,几十个账号, 2,5种操作类型(select,update,in ...
- PLSQL编译存储过程无响应
解决方法如下: 1:查V$DB_OBJECT_CACHE SELECT * FROM V$DB_OBJECT_CACHE WHERE name='CRM_LASTCHGINFO_DAY' AND LO ...
- java基础字符串---02
String 概述 String类在java.lang包下,所以使用的时候不需要导包 String类代表字符串,java程序中的所有字符串文字(例如"abc")都被实现为此类的实例 ...
- 01、uwsgi、gunicorn如何实现优雅重启
1.为何需要优雅重启 在实际开发过程中,我们会不断迭代升级产品,每次迭代后,都需要在线上服务器更新代码.一般小公司的迭代升级,是没有做到像金丝雀发布或者使用到kubernetes这些东西的.那如何保证 ...