[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双机串口通信的更多相关文章

  1. 嵌入式02 STM32 实验07 串口通信

    STM32串口通信(F1系列包含3个USART和2个UART) 一.单片机与PC机串行通信研究目的和意义: 单片机自诞生以来以其性能稳定,价格低廉.功能强大.在智能仪器.工业装备以及日用电子消费产品中 ...

  2. stm32中的串口通信你了解多少

    在基础实验成功的基础上,对串口的调试方法进行实践.硬件代码顺利完成之后,对日后调试需要用到的printf重定义进行调试,固定在自己的库函数中. b) 初始化函数定义: void USART_Confi ...

  3. stm32 hal库串口通信资料汇集

    串口的发送接收函数:HAL_UART_Transmit();串口轮询模式发送,使用超时管理机制.HAL_UART_Receive();串口轮询模式发送,使用超时管理机制.HAL_UART_Transm ...

  4. stm32与三菱PLC通信

    一.三菱PLC通讯概要   三菱PLC FX系列通信结构如下图所示: 三菱PLC FX系列的通信规格如下图所示: 三菱PLC FX系列一般有以下几种通信模块,以FX2N为例: FX2N-232-BD ...

  5. (三)stm32之串口通信DMA传输完成中断

    一.DMA功能简介 首先唠叨一下DMA的基本概念,DMA的出现大大减轻了CPU的工作量.在硬件系统中,主要由CPU(内核).外设.内存(SRAM).总线等结构组成,数据经常要在内存和外设之间,外设和外 ...

  6. STM32学习笔记:【004】USART串口通信

    版本:STM32F429 Hal库v1.10 串口通信能够实现两块电路之间不同的通信,在开发中作为打印调试也是一门利器(printf重定向). 补充一点小知识: 1. weak修饰符修饰的函数,说明这 ...

  7. Stm32串口通信(USART)

    Stm32串口通信(UART) 串口通信的分类 串口通信三种传递方式 串口通信的通信方式 串行通信的方式: 异步通信:它用一个起始位表示字符的开始,用停止位表示字符的结束.其每帧的格式如下: 在一帧格 ...

  8. STM32 串口通信使用奇偶校验

    STM32串口通信如果使用奇偶校验,需要设置数据位长度为9bit USART_InitStructure.USART_BaudRate = 9600; USART_InitStructure.USAR ...

  9. stm32串口通信实验,一点笔记

    第一次深入学习stm32,花了好长时间才看懂代码(主要是C语言学习不够深入),又花了段时间自己敲了一遍,然后比对教程,了解了利用中断来串口通信的设置方法. 板子是探索版f407,本实验工程把正点原子库 ...

  10. STM32串口通信UART使用

    STM32串口通信UART使用 uart使用的过程为: 1. 使能GPIO口和UART对应的总线时钟 2. 配置GPIO口的输出模式 3. 配置uart口相关的基本信息 4. 使能uart口的相关的中 ...

随机推荐

  1. Linux反空闲的设置和关闭

    有一定工作经验的运维人基本都会遇到这样的场景,某个窗口自动断开了,提示超时: [oracle@jystdrac1 ~]$ timed out waiting for input: auto-logou ...

  2. Delphi-判断一个对象是否释放,改造官方的Assigned

    直接上例子了,基础知识自己去了解,首先定义一个类: TPerson = class public name: string; age: Integer; constructor Create(name ...

  3. Shell中调用可执行文件,手动执行可以执行,crontab执行就报错:exec: java: not found

    今天发现一个很奇怪的问题,就是我编写的shell脚本, 手动执行可以正常执行,但是放到crontab中就报错.line 60: exec: java: not  found 百度搜索发现原来是java ...

  4. MFC-ODBC API动态连接配置数据库

    一.ODBC管理器介绍 在Window中,ODBC数据远管理器有6个标签:用户DSN.系统DSN.文件DSN.驱动程序.跟踪.连接池,通常情况下,使用用户DSN或者系统DSN,这里主要了解用户DSN和 ...

  5. .NET周刊【2月第2期 2024-02-11】

    国内文章 C#/.NET该如何自学入门? https://www.cnblogs.com/Can-daydayup/p/18006914 随着DotNetGuide技术社区交流群的扩大,很多新成员希望 ...

  6. 【framework】WindowContainer简介

    1 前言 ​ WindowContainer 继承自 ConfigurationContainer,是 WMS 家族的重要基类.ConfigurationContainer简介 中,已介绍 Confi ...

  7. 用ELK分析每天4亿多条腾讯云MySQL审计日志(2)--EQL

    上一篇介绍了用ELK分析4亿多条审计日志过程,现在介绍如何用Python3分析ES的程序 需要分析的核心库审计数据: 1,950多张表,几十个账号, 2,5种操作类型(select,update,in ...

  8. PLSQL编译存储过程无响应

    解决方法如下: 1:查V$DB_OBJECT_CACHE SELECT * FROM V$DB_OBJECT_CACHE WHERE name='CRM_LASTCHGINFO_DAY' AND LO ...

  9. java基础字符串---02

    String 概述 String类在java.lang包下,所以使用的时候不需要导包 String类代表字符串,java程序中的所有字符串文字(例如"abc")都被实现为此类的实例 ...

  10. 01、uwsgi、gunicorn如何实现优雅重启

    1.为何需要优雅重启 在实际开发过程中,我们会不断迭代升级产品,每次迭代后,都需要在线上服务器更新代码.一般小公司的迭代升级,是没有做到像金丝雀发布或者使用到kubernetes这些东西的.那如何保证 ...