3.2 USART 通用同步/异步收发器

news2024/11/16 19:52:05

文章目录

  • 什么是USART
    • USART框图
  • stm32的Usart串口收发配置
    • 初始化
    • 发送
    • 接收
  • 重定向的几种方法
  • 串口发送数据包

什么是USART

  • USART(Universal Synchronous/Asynchronous Receiver/Transmitter)通用同步/异步收发器
  • USART是STM32内部集成的硬件外设,可根据数据寄存器的一个字节数据自动生成数据帧时序,从TX引脚发送出去,也可自动接收RX引脚的数据帧时序,拼接为一个字节数据,存放在数据寄存器里
  • 自带波特率发生器,最高达4.5Mbits/s
  • 可配置数据位长度(8/9)、停止位长度(0.5/1/1.5/2)
  • 可选校验位(无校验/奇校验/偶校验)
  • 支持同步模式、硬件流控制、DMA、智能卡、IrDA、LIN //基于串口通信的一些变体通信方式

STM32F103C8T6 USART资源: USART1、 USART2、 USART3

USART框图

在这里插入图片描述

  • 灰色的两个寄存器 再物理上是独立的两个寄存器,但软件上共用一个地址
  • 收发数据的细节 移位寄存器与数据寄存器的工作流程
    • 最后都是一位一位的输入或输出.
    • 可以发现输入和输出是相反的操作
    • 输出:
      1. 直接写入一个byte的数据到 发送数据寄存器(TDR)
      2. 发送数据寄存器一位一位的移动到 发送移位寄存器
      3. 再串行输出
    • 输入:
      1. 一位一位的串行数据读入到接收移位寄存器
      2. 当满了一个Byte ,这一个Byte的数据就从 接收移位寄存器 转到接收数据寄存器(RDR)中。
      3. 再直接读取

stm32的Usart串口收发配置

初始化

  • 初始化对应gpio
  • 初始化usart外设
    • USART_BaudRate //波特率
    • USART_HardwareFlowControl //硬件流控制,通常不需要
    • USART_Mode //选择收发模式
    • USART_Parity //选择是否要奇偶校验
    • USART_StopBits //停止位长度,选择1位
    • USART_WordLength //选择字长,即为数据帧的长度
void Serial_Init(void)
{
	/*开启时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);	//开启USART1的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	//开启GPIOA的时钟
	
	/*GPIO初始化*/
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);					//将PA9引脚初始化为复用推挽输出
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);					//将PA10引脚初始化为上拉输入
	
	/*USART初始化*/
	USART_InitTypeDef USART_InitStructure;					//定义结构体变量
	USART_InitStructure.USART_BaudRate = 9600;				//波特率
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;	//硬件流控制,不需要
	USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;	//模式,发送模式和接收模式均选择
	USART_InitStructure.USART_Parity = USART_Parity_No;		//奇偶校验,不需要
	USART_InitStructure.USART_StopBits = USART_StopBits_1;	//停止位,选择1位
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;		//字长,选择8位
	USART_Init(USART1, &USART_InitStructure);				//将结构体变量交给USART_Init,配置USART1
	
	/*中断输出配置*/
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);			//开启串口接收数据的中断
	
	/*NVIC中断分组*/
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);			//配置NVIC为分组2
	
	/*NVIC配置*/
	NVIC_InitTypeDef NVIC_InitStructure;					//定义结构体变量
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;		//选择配置NVIC的USART1线
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//指定NVIC线路使能
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;		//指定NVIC线路的抢占优先级为1
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;		//指定NVIC线路的响应优先级为1
	NVIC_Init(&NVIC_InitStructure);							//将结构体变量交给NVIC_Init,配置NVIC外设
	
	/*USART使能*/
	USART_Cmd(USART1, ENABLE);								//使能USART1,串口开始运行
}

发送

  • 将数据写入发送数据寄存器(TDR)后,要等待写入完成再进行下一次写入(避免数据覆盖)
void Serial_SendByte(uint8_t Byte)
{
	USART_SendData(USART1, Byte);		//将字节数据写入数据寄存器,写入后USART自动生成时序波形
	while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);	//等待发送完成
	/*下次写入数据寄存器会自动清除发送完成标志位,故此循环后,无需清除标志位*/
}

在这里插入图片描述

接收

  • 通过串口中断实现数据接收
void USART1_IRQHandler(void)
{
   if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)		//判断是否是USART1的接收事件触发的中断
   {
   	Serial_RxData = USART_ReceiveData(USART1);				//读取数据寄存器,存放在接收的数据变量
   	Serial_RxFlag = 1;										//置接收标志位变量为1
   	USART_ClearITPendingBit(USART1, USART_IT_RXNE);			//清除USART1的RXNE标志位
   															//读取数据寄存器会自动清除此标志位
   															//如果已经读取了数据寄存器,也可以不执行此代码
   }
}

重定向的几种方法

  1. 直接改fputc 改fputc
    (printf就是由fputc实现的)
  2. 自己封装printf函数

void Serial_Printf(char *format, ...)
{
	char String[100];				//定义字符数组
	va_list arg;					//定义可变参数列表数据类型的变量arg
	va_start(arg, format);			//从format开始,接收参数列表到arg变量
	vsprintf(String, format, arg);	//使用vsprintf打印格式化字符串和参数列表到字符数组String中
	va_end(arg);					//结束变量arg
	Serial_SendString(String);		//串口发送字符数组(字符串)
}

串口发送数据包

  • 两种数据包 ,固定与不固定,文本与十六进制
  • 状态机思想 (注意其中状态的判断用if else if级联,不要用if语句)
    • 接收数据 -> 根据不同的状态做不同的处理
/**
  * 函    数:USART1中断函数
  * 参    数:无
  * 返 回 值:无
  * 注意事项:此函数为中断函数,无需调用,中断触发后自动执行
  *           函数名为预留的指定名称,可以从启动文件复制
  *           请确保函数名正确,不能有任何差异,否则中断函数将不能进入
  */
void USART1_IRQHandler(void)
{
	static uint8_t RxState = 0;		//定义表示当前状态机状态的静态变量
	static uint8_t pRxPacket = 0;	//定义表示当前接收数据位置的静态变量
	if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)		//判断是否是USART1的接收事件触发的中断
	{
		uint8_t RxData = USART_ReceiveData(USART1);				//读取数据寄存器,存放在接收的数据变量
		
		/*使用状态机的思路,依次处理数据包的不同部分*/
		
		/*当前状态为0,接收数据包包头*/
		if (RxState == 0)
		{
			if (RxData == 0xFF)			//如果数据确实是包头
			{
				RxState = 1;			//置下一个状态
				pRxPacket = 0;			//数据包的位置归零
			}
		}
		/*当前状态为1,接收数据包数据*/
		else if (RxState == 1)
		{
			Serial_RxPacket[pRxPacket] = RxData;	//将数据存入数据包数组的指定位置
			pRxPacket ++;				//数据包的位置自增
			if (pRxPacket >= 4)			//如果收够4个数据
			{
				RxState = 2;			//置下一个状态
			}
		}
		/*当前状态为2,接收数据包包尾*/
		else if (RxState == 2)
		{
			if (RxData == 0xFE)			//如果数据确实是包尾部
			{
				RxState = 0;			//状态归0
				Serial_RxFlag = 1;		//接收数据包标志位置1,成功接收一个数据包
			}
		}
		
		USART_ClearITPendingBit(USART1, USART_IT_RXNE);		//清除标志位
	}
}

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

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

相关文章

[Unity Demo]从零开始制作空洞骑士Hollow Knight第十集:制作后坐力系统Recoil和小骑士的生命系统和受伤系统

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、制作后坐力系统Recoil 1.使用代码实现扩展新的后坐力行为2.为敌人脚本添加后坐力行为3.为小骑士添加后坐力行为二、制作小骑士的生命系统和受伤系统 1.制作…

Appium独立测试自动化初始化脚本

1、查看环境初始化参数 确保appium已经开起来了,设置ip ,并点击启动 打开夜神模拟器,点击工具--设置 最下面的版本说明,双击进去 版本号这里再去单击。 直到进入到开发者模式。 可能我们不是开发者模式打开的状态,所以软件访问模…

fo-dicom是如何实现DICOM 的网络通信功能

一、前言 前面的文章,我们介绍了fo-dicom是一个怎样的开源库等一些内容: fo-dicom,第一个基于.NET Standard 2.0 开发的DICOM开源库fo-dicom开源库是如何满足 DICOM标准的基本要求fo-dicom开发之DICOM数据解析:常见数据类型及处…

自学前端的正确姿势是...

师傅带进门,修行在个人。 在前端自学成才的道路上,有些人走的很快,有些人却举步维艰。 为什么会这样子呢?因为他们没有掌握自学前端的正确姿势。 在介绍应该要怎样自学前端之前,首先来看下,自学前端容易…

JavaWeb--小白笔记07:servlet对表单数据的简单处理

这里的servlet对表单数据的处理是指使用IDEA创建web工程,再创建html和class文件进行连接,实现html创建一个表单网页,我们对网页中的表单进行填充,可以通过class文件得到网页我们填充的内容进行打印到控制台。 一登录系统页面---h…

[vulnhub] w1r3s.v1.0

https://www.vulnhub.com/entry/w1r3s-101,220/ 思路:红队笔记 主机发现端口扫描 使用nmap扫描网段类存活主机 因为靶机是我最后添加的,所以靶机IP是133 nmap -sP 192.168.75.0/24 // Starting Nmap 7.93 ( https://nmap.org ) at 2024-09-20 09:09 CST…

MySQL 数据库安装(详细教程)

文章目录 一、前言二、下载 MySQL2.1 安装包方式2.2 压缩包方式(推荐) 三、安装 MySQL3.1 解压 MySQL 文件3.2 配置环境变量3.3 初始化 data 目录3.4 安装 MySQL 服务3.5 开启 MySQL 服务3.6 修改 MySQL 密码 四、卸载 MySQL4.1 停止 MySQL 服务4.2 删除…

MySQL record 08 part

数据库连接池: Java DataBase Connectivity(Java语言连接数据库) 答: 使用连接池能解决此问题, 连接池,自动分配连接对象,并对闲置的连接进行回收。 常用的数据库连接池: 建立数…

【WRF运行第三期】服务器上运行WRF模型(官网案例-Hurricane Matthew)

【WRF运行第三期】运行WRF模型(官网案例-Hurricane Matthew) 官网案例-Hurricane Matthew介绍0 创建DATA文件夹1 WPS预处理1.1 解压GRIB数据(ungrib.exe)1.1.1 解压GRIB数据---GFS(Matthew案例研究数据)1.1…

Bytebase 2.22.3 - 一键回滚 PostgreSQL DML 变更

🚀 新功能 支持一键回滚 PostgreSQL DML 变更。 🎄 改进 优化 DML 事前备份和回滚体验: 引导用户创建 bbdataarchive 数据库。如果没有 bbdataarchive 数据库,无法开启备份功。用户现在可以在创建工单之后开启或关闭备份功能&a…

PyCharm远程连接AutoDL服务器实现程序调试

本文详细介绍了如何在Pycharm中配置SSH和SFTP,以便于在AOTUDL服务器上进行代码修改、调试。步骤包括新建工程、配置SFTP连接、设置Rootpath和Mapping,以及实现自动上传和下载文件的功能。远程服务器编辑调试只是试用于专业版本的pycharm,我的…

【LLM学习之路】9月22日 第九天 自然语言处理

【LLM学习之路】9月22日 第九天 直接看Transformer 第一章 自然语言处理 自然语言处理发展史 只要看的足够多,未必需要理解语言 统计语言模型发展史 统计语言模型: 判断一个句子是否合理,就计算这个句子会出现的概率 缺点是句子越长越…

微软推迟在MDM设备上启用OOBE强制更新 因为IT管理员反馈称缺乏控制

微软很久之前就计划在 Windows 10/11 OOBE 期间强制下载更新,即若检测到系统本身属于旧版本例如并未安装最新累积更新,则在 OOBE 期间强制下载最新累积更新并自动安装。这种更新方式已经在面向消费者的设备上启用,而上周微软则是在适用于企业…

盘点那些功能强大的思维导图在线工具,你用过几个

如果我们日常遇到比较繁杂的信息需要梳理,那我比较推荐使用思维导图在线工具进行梳理。这些工具可以通过图形化的方式展示各种信息之间的关系。这篇文章我将要介绍几款好用的思维导图工具帮我们更好的组织思维。 1.福晰思维导图 链接一下:https://www.…

GPIO与MIO控制LED——ZYNQ学习笔记2

一、GPIO简介 ZYNQ 分为 PS 和 PL 两部分,那么器件的引脚( Pin)资源同样也分成了两部分。 ZYNQ PS 中的外设可以通过 MIO( multiplexed I/O,多路复用 I/O)模块连接到 PS 端的引脚上,也可以通过 …

HTML讲解(三)通用部分

目录 1.空格标记 2.特殊文字的标记 3.注释语句 4.对文字字体的设置 5.修改文字形态 6.换行标记 7.居中标记 8.水平线标记 9.设置滚动弹幕 1.空格标记 在HTML中,我们想打印空格并不能直接敲一个空格键,因为如果是敲空格键,那无论你敲…

【JUC并发编程系列】深入理解Java并发机制:Volatile从底层原理解析到高级应用技巧(六、Volatile关键字、JMM、重排序、双重检验锁)

文章目录 【JUC并发编程系列】深入理解Java并发机制:Volatile从底层原理解析到高级应用技巧(六、Volatile关键字、JMM、重排序、双重检验锁)1. Volatile的特性2. Volatile的用法3. CPU多核硬件架构剖析4. JMM内存模型4.1 主要特性4.2 JMM 的工作原理4.3 实现机制 5.…

Leetcode面试经典150题-39.组合总数进阶:40.组合总和II

本题是扩展题,真实考过,看这个题之前先看一下39题 Leetcode面试经典150题-39.组合总数-CSDN博客 给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的每个数…

Docker:解决开发运维问题的开源容器化平台

云计算de小白 Docker是一个开源的容器化平台,可以将应用程序及其依赖的环境打包成轻量级、可移植的容器。 Docker为什么这么受欢迎呢?原因很简单:Docker可以解决不同环境一致运行的问题,而且占用资源少,速度快。 所以好的东西…

链式队列操作

文章目录 🍊自我介绍🍊概述🍊链式队列代码linkstack.clinkstack.hmain.c 你的点赞评论就是对博主最大的鼓励 当然喜欢的小伙伴可以:点赞关注评论收藏(一键四连)哦~ 🍊自我介绍 Hello,大家好&…