【蓝桥杯嵌入式】四、各种外设驱动(十)USART+DMA通信方式和串口通信协议的设计与使用

温馨提示:本文不会重复之前提到的内容,如需查看,请参考附录

【蓝桥杯嵌入式】附录

目录

重点提炼:

一、需求分析

1、需要的外设资源分析:

 2、外设具体分析:

CubeMX配置中,我们需要改动的参数:

USART1:

DMA:

二、软件配置

按照分析配置:

然后配置USART1 的 DMA Settings :

打开并设置中断优先级:

三、程序功能实现

用到的函数:

程序流程:

在MDK中编写代码:

四、运行测试


重点提炼:

用到的函数:

一、需求分析

        我们将设计一个示例项目USART_DMA_Demo,进行计算机和开发板之间的串口通信。
        本示例要使用USART1和对应的DMA,还要使用RTC的周期唤醒功能。示例的功能和操作流程如下。

  • 在RTC周期唤醒中断里,读取当前时间后在LCD上显示,将时间转换为字符串之后,通过串口发送给计算机。
  • 在计算机上使用串口监视软件查看接收的数据,并且可以向开发板发送指令数据。
  • MCU 持续以DMA方式进行串口数据接收,接收到一条指令后就解析并执行指令的任务,例如修改当前时间。

        在计算机与开发板的串口通信中,我们一般将计算机称为上位机,将开发板称为下位机。串口的硬件层实现了数据的收发,发送的数据具体是什么意义,需要规定上位机和下位机之间的通信协议。这种通信协议就是传输数据的格式规范及其意义。在本示例中,上位机向开发板发送的串口数据的格式定义如下表所示:

上位机向开发板发送数据的格式定义(xx表示两个位数的数字)
上位机发送的指令字符串指令功能
#Hxx;设置小时,将RTC时间的小时改为xx
#Mxx设置分钟,将RTC时间的分钟改为xx
#Sxx设置秒,将RTC时间的秒改为xx
#U01;或#U00;设置上传数据,或不上传数据

        上位机发送的指令数据固定为5字节,每个指令以#开始,以;结束。紧跟在#后面的一个字母表示指令类型,例如,H表示修改小时,M表示修改分钟。类型字符后面是两位数字,表示指令的参数,例如,"#H13;"表示要将RTC的当前时间的小时数修改为13。
        在计算机上,我们需要使用一个串口通信软件与开发板之间进行串口通信测试。比赛时会提供这样的工具。当波特率设置的和MCU串口的波特率相同时才可以进行通信。串口工具使用起来很简单,只需要设置好串口号和波特率就行,如图:

1、需要的外设资源分析:

  • USART1 (占用引脚PA9和PA10);
  • DMA2;
  • LCD;
  • RTC;

 2、外设具体分析:

查看原理图,和手册。

CubeMX配置中,我们需要改动的参数:
USART1:
  • Mode:工作模式。一般设置为Asynchronous(异步);
  • Baud Rate:波特率。CubeMX默认为115200bit/s,那就设置成115200bit/s即可。
  • Data Direction:数据传输方向。
DMA:

在有DMA功能的外设中都有对DMA的设置,找到USART1的DMA设置模块,点击Add即可添加一个DMA通道。

  • Channel: DMA 通道。每个DMA 请求可用的 DMA 通道会自动列出,选择一个即可。
  • Direction:传输方向。也就是DMA传输模式,会根据DMA请求的特性列出可选项。USARTI RX 是USARTI的DMA 数据输入请求,是将USART1接收的数据存入缓冲区,所以方向是Peripheral To Memory(外设到存储器);USART1 TX是USARTI的DMA 数据输出请求,是将缓冲区的数据用 USART1 输出,所以方向是Memory to Peripheral(存储器到外设)。
  • Priority:优先级别。DMA 流的软件优先级别有Low、Medium、

然后点击 Select 选择通道请求,串口有两个请求。

选择一个DMA流对象后,会弹出DMA请求设置栏:

  • Mode:DMA模式。普通模式和循环模式
  • Data Width: 数据宽度。外设和存储器需要单独设置数据宽度,数据宽度选项有Byte.
    Half Word 和 Word。串口传输数据的基本单位是字节,缓冲区的基本单位也是字节。
  • Increment Address:地址自增。这是指DMA传输个基本数据单位后,外设或存储器的地址是否自动增加,地址增量的大小就等于数据宽度。

二、软件配置

参考附录的内容,建立名为“USART_DMA_Demo”的项目。

按照分析配置:

LCD的设置参见附录。

RTC的配置参见上一篇文章的按照分析配置:

除了不打开闹钟外,其他配置类似。

这里只需要设置USART1 的模式为Asynchronous即可,其余保持。

然后配置USART1 的 DMA Settings :

Add两个DMA通道,会自动设置通道号和传输方向;将RX的优先级设置为中优先级,模式设置为循环模式;TX保持默认。如图所示:

打开并设置中断优先级:

        为DMA请求配置DMA 流之后,用到的DMA 流的中断会自动打开。要对DMA流的中断进行响应和处理,就必须开启USART1的全局中断。在NVIC组件里设置中断的优先级,如图所示:

        将USART1和两个DMA 流的中断抢占优先级都设置为1,因为在它们的中断处理函数里会用到函数HAL_Delay()。

生成项目文件后,打开MDK;

导入LCD驱动程序文件。

三、程序功能实现

用到的函数:

中断服务函数:

RX对应的通道的中断服务函数:

DMA1_Channel1_IRQHandler(void)

拓展:DMA模式的中断回调函数其实映射了对应外设的中断回调函数,这里使用中断回调函数更加合理。但由于比赛涉及的中断不多,不会引发冲突,所以这种直接在中断服务函数里实现代码的方式也是可行的。

USART函数:

 	HAL_UART_Transmit_DMA(设备句柄地址,数据指针,数据大小);
	HAL_UART_Receive_DMA(设备句柄地址,缓冲区指针,数据大小);

自定义函数:

解析指令函数

程序流程:

  1. 在初始化HAL库后初始化LCD,之前实验发现中断可能会影响LCD初始化。
  2. 在main.c中定义一些全局变量
  3. 用DMA方式发送一个“hello”,表示串口正常。
  4. 开启DMA循环接收。
  5. 写RTC中断服务函数(见附录)
  6. 写指令处理函数,为了方便管理,所有的私有函数都预定义在main.h中
  7. 写RX对应的通道的中断服务函数
    1. 复制数据缓冲区并返回给上位机。
    2. 指令解析处理,改变时间值。
    3. 在LCD上显示

在MDK中编写代码:

 在main.h中 对应代码段进行引入、函数预定义、引用外部变量。

/* USER CODE BEGIN Includes */
#include "lcd.h"
#include <stdio.h>
/* USER CODE END Includes */
/* USER CODE BEGIN EFP */
void updataRTCTime(void);
/* USER CODE END EFP */
/* USER CODE BEGIN Private defines */
extern uint16_t cmdLen;
extern uint8_t proBuffer[10];
extern uint8_t rxBuffer[10];
extern uint8_t isUploadTime;
/* USER CODE END Private defines */

main.c 的 /* USER CODE BEGIN WHILE */ 代码段,编写以下代码

  /* USER CODE BEGIN WHILE */
	uint8_t hello[]="Hello,DMA transmit\n";
	HAL_UART_Transmit_DMA(&huart1,hello,sizeof(hello));
	HAL_UART_Receive_DMA(&huart1,rxBuffer,cmdLen);
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */

stm32g4xx_it.c 中找到RTC的中断服务函数:

在如下代码段编写程序:

 代码如下,这里只显示时间,所以注释掉日期显示:

 RTC_TimeTypeDef sTime;
	RTC_DateTypeDef sData;
	
	if(HAL_RTC_GetTime(&hrtc,&sTime,RTC_FORMAT_BIN) == HAL_OK)
	{
		HAL_RTC_GetDate(&hrtc,&sData,RTC_FORMAT_BIN);
		char str[20];
		//sprintf(str,"Data:20%2d-%2d-%2d",sData.Year,sData.Month,sData.Date);
		//LCD_DisplayStringLine(Line3,str);
		sprintf(str,"Time:%2d:%2d:%2d",sTime.Hours,sTime.Minutes,sTime.Seconds);
		LCD_DisplayStringLine(Line5,str);
	}

找到RX对应的通道的中断服务函数,我设置的是通道1:

  /* USER CODE BEGIN DMA1_Channel1_IRQn 1 */
	for(uint16_t i=0;i<cmdLen ;i++)
			proBuffer[i]=rxBuffer [i];
	HAL_UART_Transmit_DMA(&huart1 ,rxBuffer ,cmdLen +1);
	HAL_Delay(10);
	updataRTCTime();
	LCD_DisplayStringLine(Line7,rxBuffer);
  /* USER CODE END DMA1_Channel1_IRQn 1 */

在 stm32g4xx_it.c 最后面编写自定义函数

/* USER CODE BEGIN 1 */
void updataRTCTime(void)
{
	if(proBuffer[0] != '#')
		return;
	uint8_t timeSection=proBuffer[1];
	uint8_t tmp10=proBuffer[2];
	uint8_t tmp1=proBuffer[3];
	uint8_t val=10*tmp10+tmp1;
	if(timeSection == 'U')
	{
		isUploadTime=val;
		return ;
	}
	RTC_TimeTypeDef sTime;
	RTC_DateTypeDef sDate;
	if(HAL_RTC_GetTime(&hrtc ,&sTime ,RTC_FORMAT_BIN)==HAL_OK )
	{
		HAL_RTC_GetDate(&hrtc ,&sDate ,RTC_FORMAT_BIN );
		if(timeSection == 'H')
			sTime.Hours = val;
		else if (timeSection == 'M')
			sTime.Minutes = val;
		else if (timeSection == 'S')
			sTime.Seconds = val;
		HAL_RTC_SetTime(&hrtc ,&sTime ,RTC_FORMAT_BIN );
	}
}
/* USER CODE END 1 */

四、运行测试

编译、下载(见附录)。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C 语言中位取反操作符 ~ 和逻辑取反操作符 !

在 C 语言中&#xff0c;有两种取反操作符&#xff0c;分别是位取反操作符 ~ 和逻辑取反操作符 !。 位取反操作符 ~&#xff1a; 位取反操作符 ~ 是一个一元操作符&#xff0c;用于执行按位取反操作。它会将操作数的每个位取反&#xff0c;即将 0 变为 1&#xff0c;将 1 变为 …

成为高效Java工程师的干货笔记

&#x1f482; 个人网站:【 摸鱼游戏】【神级代码资源网站】【工具大全】&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交流&#xff0c;摸鱼划水的小伙伴&#xff0c;请点击【全栈技术交流群】 作为一名Java工程师&…

手撕算法-判断是不是平衡二叉树

描述&#xff1a;分析&#xff1a;只需要看左右子树的深度差小于等于1&#xff0c;且左右子树都是平衡二叉树。 代码&#xff1a; public class Solution {public boolean IsBalanced_Solution (TreeNode pRoot) {if (pRoot null) return true;return Math.abs(deep(pRoot.l…

科普一下|了解胎牛血清

胎牛血清是从未出生的胎牛中经过穿刺采血后&#xff0c;经过层析、离心、三级0.1m微滤除菌等操作而收集到的上清液。本文将会探讨胎牛血清的生产流程、应用、储存以及胎牛血清的成分&#xff0c;让我们一起走进胎牛血清的世界吧&#xff01; 1、胎牛血清的生产流程&#xff1a…

redis的安装与string类型

1. redis的安装 1.1 升级gcc版本 因为centos7.x的gcc版本还是4.8.5&#xff0c;而编译指定的版本是需要5.3以上。 环境部署与安装scl源 yum install gcc cmake -y --部署安装环境 yum install centos-release-scl scl-utils-build -y --安装scl源 安装gcc新版本 yum -y ins…

Batch Normalization(批量归一化)和 Layer Normalization(层归一化)

Batch Normalization(批量归一化)和 Layer Normalization(层归一化)都是深度学习中用于改善网络训练过程的归一化技术。尽管它们的目标相似,即通过规范化中间层的激活值来加速训练过程并提高性能,但它们在细节上有所不同。 Batch Normalization (批量归一化) Batch Nor…

如何处理WordPress网站域名循环重定向

我在 HostEase 搭建了一个 WordPress 网站。在访问网站时出现了循环重定向的问题。经检查&#xff0c;发现是我在 .htaccess 文件中设置的重定向规则导致的。 重定向循环通常指的是一个网页或者URL地址在不断地进行重定向&#xff0c;最终形成一个循环&#xff0c;导致网页无法…

docker swarm 集群创建

1&#xff0c;目的&#xff1a; 通过docker swarm 工具将一台或者多台安装了docker的服务器组成一个完整的集群&#xff0c;该集群中的node节点可以通过Leader节点管理。在使用docker stack部署时&#xff0c;可以将容器自动分发到合适的节点上。 2&#xff0c;服务器准备&am…

C# 数组(Array)

C# 数组&#xff08;Array&#xff09; 初始化数组 声明一个数组不会在内存中初始化数组。当初始化数组变量时&#xff0c;您可以赋值给数组。 数组是一个引用类型&#xff0c;所以您需要使用 new 关键字来创建数组的实例。 例如&#xff1a; double[] b new double[10];…

VMware 替代专题 | 浅析 VMware 与 SmartX 超融合 I/O 路径差异及其影响

不同的超融合软件&#xff0c;其读写机制有一定的差异性&#xff0c;I/O 路径也不尽相同&#xff0c;这使得他们在 I/O 读写效率以及资源占用上都有不同的表现。有兴趣着手构建超融合基础架构的用户&#xff0c;可能会希望了解更多关于 I/O 路径的细节&#xff0c;从而在实施之…

二极管使用总结

1、整流的二极管、快恢复二极管、肖特基二极管做整流的差异。 标准整流二极管与快恢复二极管主要差异在恢复时间上。 • Standard rectifiers with a trr > 500 ns • Fast rectifiers with a 100 ns < trr < 500 ns • Ultrafast rectifiers with a trr < 100…

软件工程导论画图题汇总:期末+复试

文章目录 一、数据模型&#xff1a;实体联系图&#xff08;E-R图&#xff09;二、行为模型&#xff1a;状态转换图三、功能模型&#xff1a;数据流图四、数据字典五、系统流程图六、层次图七、HIPO图八、结构图九、程序流程图十、盒图十一、PAD图十二、判定表、判定树 一、数据…

【链表】Leetcode 19. 删除链表的倒数第 N 个结点【中等】

删除链表的倒数第 N 个结点 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5] 解题思路 1、使用快慢指针找到要删除节点的前一个节点。2、删…

30-如何使用命令给共享文件夹给人员授权?windows 的共享文件

&#xff08;1&#xff09;需求&#xff1a; 维护公司的DFS真的很烦&#xff0c;每天要给他们人员进行授权。用AD组可以&#xff0c;但是呢&#xff0c;用户想看到他们授权情况&#xff0c;没办法只能一个个授权吗&#xff1f;可以使用命令吗&#xff1f;可以的 &#xff08;2&…

【SpringMVC】知识汇总

SpringMVC 短暂回来&#xff0c;有时间就会更新博客 文章目录 SpringMVC前言一、第一章 SpingMVC概述二、SpringMVC常用注解1. Controller注解2. RequestMapping注解3. ResponseBody注解4. RequestParam5. EnableWebMvc注解介绍6. RequestBody注解介绍7. RequestBody与RequestP…

腾讯游戏全年收入1799亿,DNF手游有望突破100亿

易采游戏网3月21日消息&#xff1a;腾讯公司近期发布的2023财务年度报告显示&#xff0c;其营收和净利润双双显著上升&#xff0c;尤以游戏业务成绩不俗。管理团队承诺&#xff0c;将继续深耕既有游戏产品&#xff0c;同时强化新游研发力度&#xff0c;提升市场竞争力。引人瞩目…

SV-7035VP播放模块通用型播放终端SV-7035VP-SIP 网络通用型播放功放模块

SV-7035VP播放模块通用型播放终端SV-7035VP-SIP 网络通用型播放功放模块 产品介绍 SV-7035VP模块是一款SIP播放模块&#xff0c;具有10/100M以太网接口&#xff0c;其接收网络的音频数据&#xff0c;提供立体声的音频输出。 本SIP播放模块带有一个继电器端子和一个NET接口&a…

C++ —— 内存管理

目录 1. C内存分布 2. C 内存管理方式 2.1 new 和 delete 操作内置类型 2.2 new 和 delete 操作自定义类型 3. operator new与operator delete函数 4. new和delete的实现原理 5. malloc/free 和 new/delete 的区别 1. C内存分布 首先看一段代码&#xff1a; int globalV…

【xr806开发板使用】连接wifi例程实现

##开发环境 win10 WSL ##1、环境配置 参考&#xff1a;https://aijishu.com/a/1060000000287513 首先下载安装wsl 和ubuntu https://docs.microsoft.com/zh-cn/windows/wsl/install &#xff08;1&#xff09;安装repo&#xff1a; 创建repo安装目录&#xff1a; mkdir ~/…

【人工智能Ⅱ】实验2:VGG图像分类

实验2&#xff1a;VGG图像分类 一&#xff1a;实验目的与要求 1&#xff1a;掌握VGG网络的原理与结构。 2&#xff1a;学会利用VGG网络建立训练模型&#xff0c;并对模型进行评估。 3&#xff1a;学会使用VGG网络进行分类。 二&#xff1a;实验内容 1&#xff1a;用VGG网络…