HAL+M4学习记录_5

news2024/10/11 16:41:22

一、串口

记录使用HAL库开发串口

1.1 简介

USART中文意思是通用同步异步收发器,常用串口是异步串口,简记为UART,是内部集成的硬件外设。使用两根通信线,发送端TX和接收端RX,工作时RX和TX交叉连接。由于计算机的USB接口协议与单片机的TTL协议不相容,需要用到USB转TTL模块
CH340模块

F407内部集成4个通用同步/异步收发器(USART1,USART2,USART3和USART6),2个通用异步收发器(UART4和UART5)。
USART对比

1.2 串口硬件框图

这里给出参考手册里面的串口硬件框图
串口硬件框图
由图可以得出以下信息

  • TX和RX接口分别用于数据的发送和接收
  • SW_RX接口用于智能卡模式下接收数据
  • IRAD_OUT和IRAD_IN接口用于IRAD模式下的数据发送和接收
  • RST和CTS接口用于硬件流控制
  • USART_BRR用于生成波特率

发送过程和接收过程如下

  • 发送过程
    数据先进入USART_TDR,同时TXE置零;再由USART_TDR进入USART_TSR并置位TXE;最后由USART_TSR经由TX发送出去
  • 接收过程
    数据先经由RX进入USART_RSR;再由USART_RSR进入USART_RDR,同时RXE置零;最后由USART_RDR进入总线被接受并置位RXE

1.3 串口参数及数据帧

数据帧具体包括以下参数

  • 波特率:串口通信速率
  • 起始位:固定为低电平
  • 数据位:1为高电平,0为低电平,低位先行,可配置数据位长度(8/9)
  • 校验位:数据位的最后一位
  • 停止位:固定为高电平,可设置停止位长度(0.5/1/1.5/2)

数据帧
这里给出江协科教程中的串口时序图
串口时序图

1.4 串口发送时序图

这里给出串口发送时序图,以理解TC和TXE行为
串口发送时序图
该图解读如下

  • 软件使能USART,USART外设就绪,TXE=1
  • 等待TXE=1标志,将F1数据写入DR同时TXE=0,数据F2就绪
  • DR中数据F1进入TX line发送出去同时TXE=1
  • 数据F2和数据F3按以上流程进行发送
  • 数据F3发送完成后,TC=1标志发送完成

1.5 串口接收

  • 起始位检测
    当识别到特定序列时才能检测起始位,该序列是1110X0X0X0000,在一位时间内进行16位采样,如下图所示
    起始位检测
    由图可以看出,先检测RX线的下降沿,检测到下降沿后的三个采样点中至少有2个为0能确定起始位,之后的三个采样点中至少有2个为0才能确定当前起始位有效。
  • 数据采样
    当一个数据帧接收完毕,配置RXNE=1,表明RSR为空,RDR正常接收到数据,可继续接收下一帧数据

二、串口的HAL库驱动

2.1 串口原理分析

根据stm32f4xx_hal_uart.c这一文件,给出USART外设的使用步骤

  • 通过HAL_UART_MspInit()进行UART外设硬件配置
  • 通过UART_HandleTypeDef进行UART外设配置

GPIO复用

注意:这里使用的是USART1,该外设是复用在GPIOA上,需要映射复用输入7(AF7)。串口发射脚需要产生高低电平,应设置为推挽输出模式;串口空闲帧为高电平,开发板RX脚未接上拉电阻,因此接收脚设置为上拉模式。

2.2 HAL库代码编写

  • uart.c文件
/*
*********************************************************************************************************
*	                                   Module Description
*
*	串口模块,开发板串口接口为PA9和PA10引脚,分别为USART1_TX和USART1_RX
*********************************************************************************************************
*/
#include "bsp.h"

/* private function prototypes */
void uart_Config();
/*
**********************************************************************************
*   @brief    板载串口初始化
*   @param	  None
*   @return	  None
*   @note	  
**********************************************************************************
*/
void bsp_InitUart()
{
	uart_Config();
}

/*
**********************************************************************************
*   @brief    将USART1外设配置为UART
*				-数据位8字节
*				-1字节停止位
*				-无校验位
*				-波特率9600
*				-禁用硬件流控制
*   @param	  None
*   @return	  None
*   @note	  
**********************************************************************************
*/
void uart_Config()
{
	UART_HandleTypeDef UART_HandleStructure;
	UART_HandleStructure.Instance = USART_DEBUG;					// UART寄存器基址
	UART_HandleStructure.Init.BaudRate = USART_BAUDRATE;			// UART波特率
	UART_HandleStructure.Init.HwFlowCtl = UART_HWCONTROL_NONE;		// 禁用硬件流控制
	UART_HandleStructure.Init.Mode = UART_MODE_TX_RX;				// 收发模式
	UART_HandleStructure.Init.Parity = UART_PARITY_NONE;			// 禁用校验位
	UART_HandleStructure.Init.StopBits = UART_STOPBITS_1;			// 1字节停止位
	UART_HandleStructure.Init.WordLength = UART_WORDLENGTH_8B;		// 8字节数据位
	UART_HandleStructure.Init.OverSampling = UART_OVERSAMPLING_16;	// 过采样
	
	if(HAL_UART_Init(&UART_HandleStructure) != HAL_OK)
	{
		Error_Handler();
	}
}

/*
**********************************************************************************
*   @brief    配置UART底层硬件参数,完成时钟使能、引脚配置和中断配置
*   @param	  hurt:UART寄存器基址
*   @return	  None
*   @note	  此函数原为弱定义,经重定义后即为实际被
*			  HAL_UART_Init(UART_HandleTypeDef *huart)函数调用
**********************************************************************************
*/
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	if(huart->Instance == USART_DEBUG)
	{
		/* 开启硬件时钟 */
		USART1_CLK_ENABLE();
		USART1_TX_GPIO_CLK_ENABLE();
		USART1_RX_GPIO_CLK_ENABLE();
		/* 配置引脚 */
		GPIO_InitStructure.Pin 			= USART1_TX_PIN;		// TX引脚
		GPIO_InitStructure.Mode 		= GPIO_MODE_AF_PP;		// 复用推挽
		GPIO_InitStructure.Pull			= GPIO_PULLUP;			// 上拉模式
		GPIO_InitStructure.Alternate	= USART1_TX_AF;			// 复用映射
		GPIO_InitStructure.Speed		= GPIO_SPEED_FREQ_HIGH;	// 高速
		HAL_GPIO_Init(USART1_TX_GPIO_PORT, &GPIO_InitStructure);
		
		GPIO_InitStructure.Pin			= USART1_RX_PIN;		// RX引脚
		GPIO_InitStructure.Alternate	= USART1_RX_AF;			// 复用映射
		HAL_GPIO_Init(USART1_RX_GPIO_PORT, &GPIO_InitStructure);
		
	}
}

/*
**********************************************************************************
*   @brief    重定向c库函数fputc,可以使用printf函数从串口1打印输出
*   @param	  None
*   @return	  None
*   @note	  
**********************************************************************************
*/
int fputc(int ch, FILE *f)
{
	while((USART1->SR & 0X40) == 0);	// 等待上一个字符发送完成
	USART1->DR = (uint8_t)ch;			// 将要发送的字符写入DR
	return ch;
}

  • uart.h文件
#ifndef __BSP_UART_FIFO_H
#define __BSP_UART_FIFO_H

/* private define */
#define USART_DEBUG						USART1
#define USART_BAUDRATE					115200
#define USART1_CLK_ENABLE()				do{__HAL_RCC_USART1_CLK_ENABLE();}while(0)

#define USART1_TX_GPIO_CLK_ENABLE()		do{__HAL_RCC_GPIOA_CLK_ENABLE();}while(0)
#define USART1_TX_GPIO_PORT				GPIOA
#define USART1_TX_PIN					GPIO_PIN_9
#define USART1_TX_AF					GPIO_AF7_USART1

#define USART1_RX_GPIO_CLK_ENABLE()     do{__HAL_RCC_GPIOA_CLK_ENABLE();}while(0)
#define USART1_RX_GPIO_PORT             GPIOA
#define USART1_RX_PIN                   GPIO_PIN_10
#define USART1_RX_AF                    GPIO_AF7_USART1

/* public statement */
void bsp_InitUart();

#endif

以上即完成了USART1作UART的配置,在main函数中即可使用printf函数经串口打印数据。

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

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

相关文章

【计算机网络】详谈TCP协议确认应答机制捎带应答机制超时重传机制连接管理机制流量管理机制滑动窗口拥塞控制延迟应答

一、TCP 协议段格式 1.1、4位首部长度 4位首部长度的基本单位是4字节,也就是说如果4位首部长度填6,那报头长度就是24字节。报头长度的取值范围为[0,60]字节,也就是说选项的最大长度为40字节。 二、确认应答机制 发送数据和发送应答&#x…

python爬虫 - 初识正则表达式

🌈个人主页:https://blog.csdn.net/2401_86688088?typeblog 🔥 系列专栏:https://blog.csdn.net/2401_86688088/category_12797772.html 目录 前言 一、正则表达式 (一)正则表达式的基本作用 &#xf…

DAY7 继承多态

继承 目的 提高代码的重用性,减少一些重复代码的书写 权限修饰符 就是是用来限制类中的成员(成员变量、成员方法、构造器)能够被访问的范围。 private 只能本类 缺省 本类、同一个包中的类 protected 本类,同一个包中的类、子…

thenable的执行时机

thenable执行只有2个时机 1.触发resolve()时,代码尚未注册then的内容,那么直到代码扫描到then那一行,才会把then的内容放进队列 2.先注册then,直到后期遇到resolve(),才会进入队列 视频教学 https://www.bilibili.com/video/BV12zsqeMEyt

传智杯 第六届—C

题目描述: 输入两个字符串,从第一字符串中删除第二个字符串中所有的字符。例如:第一个字符串是"They are students.",第二个字符串是”aeiou"。删除之后的第一个字符串变成"Thy r stdnts."。保证两个字符…

仿生水凝胶微纤维:从蜘蛛丝获得灵感,探索高性能纤维材料的新路径

大家好!今天咱们来了解一种水凝胶微纤维——《Bioinspired Mechanically Robust and Recyclable Hydrogel Microfibers Based on Hydrogen‐Bond Nanoclusters》发表于《Advanced Science》。研究人员从蜘蛛丝那儿获得灵感,想要做出既机械性能好&#xf…

Spring Cloud 配置中心详解:微服务动态读取与案例示范

在微服务架构中,每个微服务往往都有其独立的配置,这些配置可能会根据环境的不同(开发、测试、生产)进行调整和变化。Spring Cloud 配置中心提供了一种集中化管理和动态更新微服务配置的解决方案。在本文中,我们将详细介…

详细分析Spring Framework中 @ConditionalOnProperty的基本知识(附Demo)

目录 前言1. 基本知识2. Demo 前言 基本的Java知识推荐阅读: java框架 零基础从入门到精通的学习路线 附开源项目面经等(超全)【Java项目】实战CRUD的功能整理(持续更新) 从实战中学习启发 1. 基本知识 Conditiona…

一键将表格嵌入ppt作为附件!2个做ppt必知的技巧分享!

怎样把表格作为附件放入ppt? 众所周知,微软推出的Office套件包含了Powerpoint和Excel这两款软件,如果想在Powerpoint中插入表格,且表格数据量比较大,此时最好的呈现方式,是在Excel中来展示这些数据&#x…

msvcp120.dll无法继续执行代码的五个解决方法

在计算机系统中,MSVCP120.dll是一个至关重要的动态链接库文件,它是Microsoft Visual C Redistributable Package的一部分,对于许多基于Windows的应用程序运行至关重要。当系统提示“msvcp120dll丢失”时,意味着该文件可能由于误删…

清华毕业生去向引发的思考....

近日,清华最新发布的毕业生去向一经公布,便在社会上引起了广泛的关注和热议,许多人看完后都陷入了沉默。这一份去向报告,不仅仅是一组数据的呈现,更是对教育成果、社会需求以及个人发展等多方面问题的深刻映射。 一、数…

文件与目录的基本操作

前提:使用su root 切换到权限最大的root用户 1.显示当前工作目录的绝对路径(pwd) 用途:用于显示当前工作目录的绝对路径的命令。无论用户在文件系统的哪个位置,pwd 命令都能提供当前所在位置的完整路径信息。 用法&a…

现货白银交易技巧:向下突破回撤策略

有关现货白银交易的技巧一直是投资者关注的重点,投资者确实应该保持学习,这样才能跟得上市场,不会落后,下面我们就来介绍一个现货白银交易中的突破回撤的策略。 首先这个现货白银交易技巧判断的基础就是找到一波横盘趋势。所谓的突…

【C# 网络编程】基本概念

基本概念 OSI模型 背景: 为了统一和兼容不同计算机厂商的网络体系结构概念,国际标准化组织(ISO)在1979年提出了OSI参考模型(Open System Interconnection,) 结构 物理层(Physica…

java反序列化之CommonCollections6利⽤链的学习

一、源起 前文学习CC1链和URLDNS链的学习,同时学习过程中知道cc1受jdk版本的限制,故而进一步分析cc6链的利用过程,这个利用链不受jdk版本的限制,只要commons collections小于等于3.2.1,都存在这个漏洞。 ps&#xff1…

Flink 介绍(特性、概念、故障容错、运维部署、应用场景)

概述 特性 概念 数据流 状态 时间 savepoint 故障容错 运维部署 部署应用到任意地方 Flink能够更方便地升级、迁移、暂停、恢复应用服务 监控和控制应用服务 运行任意规模应用 应用场景 事件驱动型应用 什么是事件驱动型应用? 事件驱动型应用的优势 Flink如何…

对接外卖霸王餐api要遵循哪些步骤?

对接外卖霸王餐API接口的步骤通常包括以下几个关键环节: 选择服务提供商:根据需求、预算、服务内容、接口稳定性、覆盖范围(是否支持全国多个城市、是否支持主要外卖平台如美团和饿了么等)、技术支持等因素选择合适的霸王餐API服…

实现一个时钟

头文件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include<QPainter>//画家类 #include<QTime>//时间类 #include<QTimer>//定时器类QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget …

vue3.5系列之响应式props解构的几点技巧对比

在最新的版本3.5x中&#xff0c;对props的能力也进行了加强。下面&#xff0c;我们具体看下有哪些变化&#xff0c;给我们带来的新的体验&#xff01; 体验一 3.5之前解构props的效果 // 子组件 <template><div><h1>响应式props</h1><p>{{ co…

【储能优化】使用优化的微电网能源管理系统 (EMS)

摘要 本文介绍了一种基于优化的微电网能源管理系统&#xff08;EMS&#xff09;&#xff0c;通过储能优化实现电网、光伏发电、以及储能设备之间的智能调度。系统旨在降低能源成本、减少碳排放&#xff0c;并提高能源利用效率。利用该EMS系统&#xff0c;电网用户能够在满足负…