【软件STM32cubeIDE下H73xx配置串口uart1+中断接收/DMA收发+HAL库+简单数据解析-基础样例】

news2024/11/26 14:48:54

#【软件STM32cubeIDE下H73xx配置串口uart1+中断接收/DMA收发+HAL库+简单数据解析-基础样例】

  • 1、前言
  • 2、实验器件
  • 3-1、普通收发+中断接收实验
    • 第一步:代码调试-基本配置
      • (1)基本配置
      • (3)时钟配置
      • (4)保存后,就可以生成代码
    • 第二步:加入prinf打印
      • (1)不重复造轮子:打印相关连接
      • (2)加入代码片段,注意第四步要放到main里运行
      • (3)代码测试
    • 第三步:加入接收代码
      • (1)加入初始化配置
      • (2)加入回调函数部分
      • (3)加入到中断内
    • 第四步:实验验证
  • 3-2、DMA收发实验
    • 第一步:加入DMA初始化
    • 第二步:加入DMA相关数组
    • 第三步:加入回调函数
    • 第四步:加入到中断函数内
    • 第四步:简单数据解析功能
      • (1)加入接收部分代码
      • (2)加入处理部分代码
      • (3)测试代码
  • 4、代码连接
  • 5、注意细节
      • (1)总是多个字符,或者多个其它字符。
      • (2)复制函数的使用。
      • (3)逻辑调试与测试。
      • (4)十进制的1与十六进制0x31。
      • (5)不同串口工具,有些信息不显示。
      • (6)数据解析注意
      • (7)初始化顺序不对,不运行
      • (8)回调函数写的有问题,只返回一个字符
      • (9)在网上找到样例,进行测试,没有成功
  • 总结

1、前言

最近有段时间没有调试STM32了,想着H743调试串口1,也不能老师吃灰,也遇到了问题,即使最简单的功能,一些细节也是非常重要的,保持初学者之心,是非常重要的,同时也算做记录,对于初学者会有帮助,另外因为之前做过很多相关实验,遇到问题基本轻车熟路了,体现了记录的好处。

2、实验器件

软件环境:STM32cubeIDE 1.8.0
硬件环境:STM32H743xx(正点原子阿波罗开发板)
下载模块:ST-link下载器 (下载器)
串口模块:串口转换器 (可用开发板上232模块代替)

3-1、普通收发+中断接收实验

第一步:代码调试-基本配置

(1)基本配置

新建stm32项目,先配置(下载口)和(时钟口),如下图,在这里插入图片描述在这里插入图片描述

###q (2)uart1以及DMA相关配置
uart1配置稍微复杂点,但是配置串口多了,熟悉了,其实也就知道了,分为几个步骤。
(0)先锁定自己需要引脚,记得F4默认是FA9,FA10,但是H7不是,我们想使用特定引脚的话,需要选择引脚,然后再选择uart1
在这里插入图片描述

(1)配置异步通信与开启中断使能,这个时候uart1锁定的引脚就会变成绿色,没选好之前,是黄色的。
在这里插入图片描述
这里需要注意的是,在自己实际操作生成代码时,发现并没有生成中断函数,所以最好在中断上再点下。
在这里插入图片描述

(2)配置DMA,这部分直接添加就好,都是默认的也不需要改什么。
在这里插入图片描述

(3)配置串口的波特率相关设置,改成你需要的波特率,一般也只改波特率,其它不用动。

在这里插入图片描述

(3)时钟配置

也就是外部时钟配置,之前F4用的是168M,F1是72M,H7一般是480M,配置如下。
在这里插入图片描述

(4)保存后,就可以生成代码

建议先保存,然后生成代码,否则直接生成代码,可能导致软件崩掉,之前遇到过。
在这里插入图片描述在这里插入图片描述

第二步:加入prinf打印

(1)不重复造轮子:打印相关连接

具体打印方式,之前就写过,所以不要重复造轮子,之前看文章,将代码复制过来。
文章连接:# 关于软件stm32cubeIDE下配置printf重定向无法输出问题-解决方式之一

(2)加入代码片段,注意第四步要放到main里运行

另外注意自己测试发现,不能使用如下定义的方式。

//>>第三步:定义输出函数printf
#define printf(...)  HAL_UART_Transmit_DMA((UART_HandleTypeDef * )&huart3, (uint8_t *)u_buf,\
											sprintf((char *)u_buf,__VA_ARGS__));

需要使用以下方式,并且需要加入换行符号 \n

printf(“\r\n star \r\n\r\n”); //起来之后输出一条语句
printf(“\r\n star \r\n\r\n”); //起来之后输出一条语句
printf(“\r\n star \r\n\r\n”); //起来之后输出一条语句


//>>第一步:添加库
#include "string.h"
#include "stdint.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */
//>>第二步:定义数组
uint8_t u_buf[64];

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
//>>第三步:定义输出函数printf
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
//STM32cubeIDE下
PUTCHAR_PROTOTYPE
{
    HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1,0x200);
    return ch;
}

//keil下 //没在keil下尝试过 一直使用软件stm32cubeIDE没有取keil验证
//UART_HandleTypeDef huart1; //UART句柄
int fputc(int ch,FILE *f)
{
	HAL_UART_Transmit(&huart1,(uint8_t*)&ch,1,0xffff);
	return ch;
}


/* USER CODE END PTD */

//>>第四步:打印输出
	  	   printf("\r\n star \r\n\r\n");  //起来之后输出一条语句
		  HAL_Delay(1000);

(3)代码测试

随便输出些什么,进行打印测试,在网上找个串口上位机工具,然后连接后串口转USB工具,对应引脚,就可以进行测了。
第四步代码放在主函数,这里没有截图上位机串口数据,打印可以放置的位置指示下,下图已经做完实验的一个截图,开始中断时还没有加入printf,这点请熟知,有疑问可以看代码或评论。
在这里插入图片描述

第三步:加入接收代码

(1)加入初始化配置

具体代码见下边连接,这里放置图片展示代码内容。
在这里插入图片描述

(2)加入回调函数部分

触发发送与接收,都会回调函数,我们这次就简单些,收到什么就发送什么。


uint8_t aRxBuffer[1];
void UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  static uint32_t rxIndex = 0;

  if(huart->Instance == USART1)
      {

	  HAL_UART_Transmit(&huart1, (uint8_t *)aRxBuffer, 1,0xFFFF);
	  HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, 1);

      }



}

在这里插入图片描述

(3)加入到中断内

这点还是挺重要,在中断函数内加入回调函数,不加入相应功能无法实现。
在这里插入图片描述

第四步:实验验证

(1)发送
在这里插入图片描述
(2)中断接收

在这里插入图片描述

3-2、DMA收发实验

因为上述步骤,相关配置已经完成了,我们不需要,再重新配置,直接使用即可。

第一步:加入DMA初始化

__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);//开启空闲中断
  /*.虽然我们使用的CubeMx来配置DMA,
   * 但只是配置DMA模式为串口到内存,
   * 所以还需要在程序中进一步指定:
   * DMA具体搬运到内存的哪一个位置中,
   * 我们建立一个数组用以存放DMA搬运的串口数据,
   * 并使用HAL_UART_Receive_DMA()函数来配置*/
  HAL_UART_Receive_DMA(&huart1, (uint8_t*)UART1_ReceBuf, UART1_Buf_LEN);

在这里插入图片描述

第二步:加入DMA相关数组

/* USER CODE BEGIN PTD */
//>>第二步:定义数组
uint8_t u_buf[64];
#define UART1_Buf_LEN 100
 uint8_t UART1_SendBuf[UART1_Buf_LEN];
 uint8_t UART1_ReceBuf[UART1_Buf_LEN];
/* USER CODE END PTD */

第三步:加入回调函数

/* USER CODE BEGIN PFP */

uint8_t aRxBuffer[1];
//void UART_RxCpltCallback(UART_HandleTypeDef *huart)
//{
//  static uint32_t rxIndex = 0;
//
//  if(huart->Instance == USART1)
//      {
//
//	  HAL_UART_Transmit(&huart1, (uint8_t *)aRxBuffer, 1,0xFFFF);
//	  HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, 1);
//
//      }
//
//
//
//}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)//发送完成回调函数
{

}

//采用DMA空闲串口中断模式  貌似不会回调到这里
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)//接收完成回调函数
{

}
/* USER CODE END 0 */

uint8_t UART1_ReceBuf_deal_with_data[5];
void USAR_UART_IDLECallback(UART_HandleTypeDef *huart)
{

//(1)
 HAL_UART_DMAStop(&huart1);                    //停止本次DMA传输 需要使用DMA发送则需要关掉  如果使用的阻塞方式HAL_UART_Transmit发送请使用本行
HAL_UART_Transmit(&huart1,(uint8_t*)UART1_ReceBuf,3,0x200);//阻塞方式发送 使用时需要关闭DMA模式 阻塞发送没有问题,收啥 发啥
//数据头正确了再赋值
if(UART1_ReceBuf[0]==0x31 &&  UART1_ReceBuf[1]==0x32)
{
	//		目标							源地址	    	数据量
	memcpy(&UART1_ReceBuf_deal_with_data,&UART1_ReceBuf,3);


}

memset(UART1_ReceBuf,0,UART1_Buf_LEN);                                            //清零接收缓冲区
  //  data_length = 0;
HAL_UART_Receive_DMA(&huart1, (uint8_t*)UART1_ReceBuf, UART1_Buf_LEN);                    //重启开始DMA传输 每次255字节数据

}


void USER_UART_IRQHandler(UART_HandleTypeDef *huart)
{
    if(  huart->Instance == USART1)
    {


    	  if(RESET != __HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE))   //判断是否是空闲中断
    	         {
    	             __HAL_UART_CLEAR_IDLEFLAG(&huart1);                     //清楚空闲中断标志(否则会一直不断进入中断)
    	             USAR_UART_IDLECallback(huart);                          //调用中断处理函数
    	         }
    }
}

/* USER CODE END PFP */

第四步:加入到中断函数内

void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */

  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */
  USER_UART_IRQHandler(&huart1);
  /* USER CODE END USART1_IRQn 1 */
}

在这里插入图片描述

第四步:简单数据解析功能

(1)加入接收部分代码

我们收到什么数据,就发出什么数据,因为在回调函数里,不能再用DMA发送了,但可以堵塞发出。

在这里插入图片描述

(2)加入处理部分代码

我们将数据收到后,如果数据对了,我们只是将数据复制一份,处理不在回调内做,以免拖慢回调。
在这里插入图片描述

(3)测试代码

这里这里发放出成功接收并解析代码,处理后发送出来,就是如果接收到数据“123”,那么返回数据“ABC”。
在这里插入图片描述

4、代码连接

(1)中断接收

代码链接:https://download.csdn.net/download/qq_22146161/88500425

(2)DMA收发

代码链接:https://download.csdn.net/download/qq_22146161/88500428

5、注意细节

(1)总是多个字符,或者多个其它字符。

实际测试中发现,总会多个0x0D数字,不知道哪里来的,多次检查后,发现其实之前有发送,因为进入空闲中断后,停止了造成这种奇特现象。
在这里插入图片描述
原因点如下:发现有奇怪数据时候,一定看看有没其它地方输出。
在这里插入图片描述

(2)复制函数的使用。

调试解析时候,我甚至将收到数据打印出来了,但是就是无法触发发送,才发现复制函数数组赋值那块弄错了,还是需要注意的。
在这里插入图片描述

(3)逻辑调试与测试。

在我们不清楚的情况,或者要测试逻辑时候,可以让其将数据打印出来了,帮助我们定位错的原因。如下图,我们不知道收到什么是数据时候,可以让其直接发回来,帮助我们判断,甚至,复制完数据后,成没成功,也可以打印出来。

在这里插入图片描述

(4)十进制的1与十六进制0x31。

我这里代码有时候说“123”,有时候又说0x31,0x32,0x33,其实这是他们进制表示不同,一个是十进制,一个是十六进制,比如,十进制的1等同于十六进制0x31,跟ascii码对照表有关系。

(5)不同串口工具,有些信息不显示。

不同上位机串口工具,在使用的时候有差异的,如果不切换到16进制进行显示,我也不会发现十六进制的0x0D,后来发现这个其实是换行符‘\n’。
在这里插入图片描述

(6)数据解析注意

开始自己看之前的文章的时候,没主要,就发了数据“12”,发现不回,检查后,才知道,数据为12的时候,只复制,不在while进行发送,这点给忘了。
在这里插入图片描述
在这里插入图片描述
如下错误,为只输入了“12”
在这里插入图片描述

(7)初始化顺序不对,不运行

需要将DMA初始化,放在uart前在这里插入图片描述

(8)回调函数写的有问题,只返回一个字符

在这里插入图片描述

(9)在网上找到样例,进行测试,没有成功

在这里插入图片描述

总结

再次调试相同东西,再简单东西,也有细节值得记录吧~~~。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1169466.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

TEMU拼多多跨境平台要求提供的UL测试报告如何办理?电子产品UL测试标准要求

平台销售的电子产品,要符合指定的标准,如果不合格很容易发生起火,等危及消费者生命财产的安全,因此很多客户因为缺少UL报告,导致产品被下架,销售权被移除等问题,也少不了同行之间的恶意举报触发…

ActiveMQ、RabbitMQ、RocketMQ、Kafka介绍

一、消息中间件的使用场景 消息中间件的使用场景总结就是六个字:解耦、异步、削峰 1.解耦 如果我方系统A要与三方B系统进行数据对接,推送系统人员信息,通常我们会使用接口开发来进行。但是如果运维期间B系统进行了调整,或者推送过…

如何开始短视频的制作,短视频脚本如何写?

在短视频创作拍摄的过程中,你有没有遇到过类似的情况: 拍摄拍到中途手忙脚乱的,不知道接下来该拍摄什么类容,或者拍了一半发现拍摄场景不行,又重新调整拍摄场景,再者,拍摄过程中发现缺少了拍摄道…

【面试专题】设计模式篇①

1.工厂设计模式 工厂设计模式是一种创建型模式,它提供了一种创建对象的接口,但具体创建的对象类型可以在运行时决定。工厂设计模式主要解决的是创建对象的灵活性问题。 工厂设计模式主要包括简单工厂模式、工厂方法模式和抽象工厂模式三种。 简单工厂…

虹科示波器 | 汽车免拆检修 | 2010款江铃陆风X8车发动机怠速抖动、加速无力

一、故障现象 一辆2010款江铃陆风X8车,搭载4G6GS4N发动机,累计行驶里程约为20万km。该车在其他修理厂进行发动机大修,维修后试车,发动机怠速抖动、加速无力。用故障检测仪检测,发动机控制模块(ECM&#xff…

JVM常用命令

jps —查看pid jstat -gcutil 4364 1000 2000 —查看堆内存占用百分比,每秒打印1次,总共打印2000次 S0:幸存1区当前使用比例 S1:幸存2区当前使用比例 E:伊甸园区使用比例 O:老年代使用比例 M:元…

常用的Linux远程桌面配置方法

TigerVNC 是 VNC(虚拟网络计算)的高性能、平台中立的实现,VNC 是一种客户端/服务器应用程序,允许用户在远程计算机上启动图形应用程序并与之交互。 TigerVNC 提供运行 3D 和视频应用程序所需的性能水平,并尝试在其支持…

基于单片机的温室环境数据监测系统的设计

收藏和点赞,您的关注是我创作的动力 文章目录 概要 一、总体方案设计2.1 总体架构设计 二、整体硬件电路设计3.1 主控制器电路 三 系统设计概要4.2 主程序设计原理图程序 四、 结论五、 文章目录 概要 与农业发达国家相比,我国的农业科技方面还处于刚刚…

腾讯云双11云服务器活动:88元一年的云服务器值得买吗?

作为一名程序员,在选择云服务器时,最关注的是网络稳定性、价格以及云服务商的规模。腾讯云在2023年10月23日的​双11活动​中推出了一款性价比极高的云服务器,为我们提供了一个非常有吸引力的选择。 1. 关注网络稳定性、价格和云服务商规模 …

jar包的精细化运营,Java模块化简介 | 京东云技术团队

图:模块化手机概念 一、什么是Java模块化 Java模块化(module)是Java9及以后版本引入的新特性。 官方对模块的定义为:一个被命名的,代码和数据的自描述集合。( the module, which is a named, self-descri…

【C语法学习】15 - fopen()函数

文章目录 1 函数原型2 返回值3 参数3.1 文件名3.2 模式3.2.1 以"r"模式打开3.2.2 以"w"模式打开3.2.3 以"a"模式打开3.2.4 以"r"模式打开3.2.5 以"w"模式打开3.2.6 以"a"模式打开 1 函数原型 fopen()&#xff1a…

AI大模型架构师专家,你会问什么来测试我的水平,如何解答上述问题,学习路径是什么

0. 沈剑老师的大模型产品应用经验: 提示词三步骤: 假如我是xxx专家,你会问什么来测试我的水平;假如你是xxx专家,你会如何解答上述问题;假如你是xxx专家,上述问题的学习路径是什么;…

面试算法54:所有大于或等于节点的值之和

题目 给定一棵二叉搜索树,请将它的每个节点的值替换成树中大于或等于该节点值的所有节点值之和。假设二叉搜索树中节点的值唯一。例如,输入如图8.10(a)所示的二叉搜索树,由于有两个节点的值大于或等于6(即…

GCN火车票识别项目 P3 PaddleOCR识别火车票信息

从这节开始,就正式进入GCN项目的代码环节,我们先使用PaddleOCR,识别出火车票上的文字信息,并提取文字所位置,整理后另存为一个csv文件。 项目的目的是要做信息抽取,所以对训练和测试数据,需要手…

存储器(详解)

概念 存储器(Memory)是计算机系统中用于存储和检索数据的硬件设备或组件。它在计算机中扮演着重要的角色,允许计算机暂时或永久地存储程序、数据和中间结果。 存储器是许多存储单元的集合,按单元号顺序排列。每个单元由若干二进制…

专为个人打造专注工作的便签APP工具推荐哪个

工作中很多人都比较懒散,工作起来动力不足,常常拖延消极怠工,等到一天结束后进行工作盘点时才发现很多项任务都没有处理完;这和日常工作不能专注于工作有很大的关系。 专注工作,在日常办公时可以选择一些好用的手机便…

【Android】android studio 怎么下载NDK

序言 新版的android studio在【Project Structure】里面的NDK路径是灰色的,无法点击,导致找不到ndk路径,也无法添加ndk。 下载方法 去这里找,一定要点这个按钮才能出现ndk。 下载之后,要在这个文件里面添加ndk路径

【不良人7】源源死后,谁将接替成为新的BOSS?全季反派分析

Hello,小伙伴们,我是小郑继续为大家深度解析国漫资讯。 深度解析,国漫精品《不良人》在历经6季的精彩演绎后,终于迎来了李嗣源的下线。这一消息对于广大《不良人》粉丝来说无疑是一个巨大的惊喜。而在即将到来的第7季中,剧情将由…

RPC 原理详解

文章目录 什么是 RPCRPC 基本原理RPC核心功能服务寻址数据编解码网络传输一次RPC的调用过程 实践基于HTTP协议的RPC基于TCP协议的RPC 什么是 RPC RPC(Remote Procedure Call),即远程过程调用,它允许像调用本地服务一样调用远程服…

思路视野杂志思路视野杂志社思路视野编辑部2023年第24期目录

公共文化 公共图书馆文旅融合实践与模式思考 白雪1-3 公共图书馆管理与服务创新路径分析 陈静4-6 提升办公室文书档案管理工作的实践探讨 黄强7-9 《思路视野》投稿邮箱:cn7kantougao163.com(注明投稿“《思路视野》”) 崔编辑Q Q :296078736 微信号&am…