STM32串口通信

news2024/12/24 11:31:36

数据通信的基础概念

在单片机的应用中,数据通信是必不可少的一部分,比如:单片机和上位机、单片机和外 围器件之间,它们都有数据通信的需求。由于设备之间的电气特性、传输速率、可靠性要求各 不相同,于是就有了各种通信类型、通信协议,我们最常的有:USART、IIC、SPI、CAN、USB 等。

1. 数据通信方式

按数据通信方式分类,可分为串行通信和并行通信两种。串行和并行的对比如下图所示:

串行通信的基本特征是数据逐位顺序依次传输,优点是传输线少、布线成本低、灵活度高 等优点,一般用于近距离人机交互,特殊处理后也可以用于远距离,缺点就是传输速率低。

而并行通信是数据各位可以通过多条线同时传输,优点是传输速率高,缺点就是布线成本 高,抗干扰能力差因而适用于短距离、高速率的通信。

2. 数据传输方向

根据数据传输方向,通信又可分为全双工、半双工和单工通信。全双工、半双工和单工通 信的比较如下图所示:

单工是指数据传输仅能沿一个方向,不能实现反方向传输,如校园广播。

半双工是指数据传输可以沿着两个方向,但是需要分时进行,如对讲机。

全双工是指数据可以同时进行双向传输,日常的打电话属于这种情形。

这里注意全双工和半双工通信的区别:半双工通信是共用一条线路实现双向通信,而全双 工是利用两条线路,一条用于发送数据,另一条用于接收数据。

3.同步通讯与异步通讯

根据通讯的数据同步方式,又分为同步和异步两种,可以根据通讯过程中是否有使用到时钟信号 进行简单的区分。

同步通信要求通信双方共用同一时钟信号,在总线上保持统一的时序和周期完成信息传输。 优点:可以实现高速率、大容量的数据传输,以及点对多点传输。缺点:要求发送时钟和接收 时钟保持严格同步,收发双方时钟允许的误差较小,同时硬件复杂。

异步通信不需要时钟信号,而是在数据信号中加入开始位和停止位等一些同步信号,以便 使接收端能够正确地将每一个字符接收下来,某些通信中还需要双方约定传输速率。优点:没 有时钟信号硬件简单,双方时钟可允许一定误差。缺点:通信速率较低,只适用点对点传输。

4. 通信速率

衡量通讯性能的一个非常重要的参数就是通讯速率,通常以比特率(Bitrate)来表示,即每秒钟传 输的二进制位数,单位为比特每秒(bit/s)。容易与比特率混淆的概念是“波特率”(Baudrate),它 表示每秒钟传输了多少个码元。而码元是通讯信号调制的概念,通讯中常用时间间隔相同的符号 来表示一个二进制数字,这样的信号称为码元。如常见的通讯传输中,用0V表示数字0,5V表 示数字1,那么一个码元可以表示两种状态0和1,所以一个码元等于一个二进制比特位,此时 波特率的大小与比特率一致;如果在通讯传输中,有0V、2V、4V以及6V分别表示二进制数00、 01、10、11,那么每个码元可以表示四种状态,即两个二进制比特位,所以码元数是二进制比特 位数的一半,这个时候的波特率为比特率的一半。

串口通信协议简介

通用同步异步收发器(Universal Synchronous Asynchronous Receiver and Transmitter) 是一个串行通 信设备,可以灵活地与外部设备进行全双工数据交换。有别于USART还有一个UART(Universal Asynchronous Receiver and Transmitter),它是在 USART 基础上裁剪掉了同步通信功能,只有异步 通信。简单区分同步和异步就是看通信时需不需要对外提供时钟输出,我们平时用的串口通信基 本都是UART。

USART 功能框图

 ① USART信号引脚

TX:发送数据输出引脚

RX:接收数据输入引脚

SCLK:发送器时钟输出,适用于同步传输

SW_RX:数据接收引脚,属于内部引脚,用于智能卡模式

IrDA_RDI:IrDA模式下的数据输入

IrDA_TDO:IrDA 模式下的数据输出

nRTS:发送请求,若是低电平,表示USART准备好接收数据

nCTS:清除发送,若是高电平,在当前数据传输结束时阻断下一次的数据发送

 ② 数据寄存器

USART_DR包含了已发送或接收到的数据。由于它本身就是两个寄存器组成的,一个专门 给发送用的(TDR),一个专门给接收用的(RDR),该寄存器具备读和写的功能。TDR寄存器 提供了内部总线和输出移位寄存器之间的并行接口。RDR寄存器提供了输入移位寄存器和内部 总线之间的并行接口。当进行数据发送操作时,往USART_DR中写入数据会自动存储在TDR 内;当进行读取操作时,向USART_DR读取数据会自动提去RDR数据。

USART数据寄存器(USART_DR)低9位数据有效,其他数据位保留。USART_DR的第 9 位数据是否有效跟USART_CR1的M位设置有关,当M位为0表示8位数据字长;当M位 为1时表示9位数据字长,一般使用8位数据字长。

当使能校验位(USART_CR1中PCE位被置位)进行发送时,写到 MSB 的值(根据数据的 长度不同,MSB 是第7位或者第8位)会被后来的校验位取代。

③ 控制器

USART 有专门控制发送的发送器、控制接收的接收器,还有唤醒单元、中断控制等等。使用 USART 之前需要向USART_CR1寄存器的UE位置1使能USART,UE位用来开启供给给串口 的时钟。 发送或者接收数据字长可选8位或9位,由USART_CR1的M位控制。

发送器

在发送数据时,编程的时候有几个比较重要的标志位我们来总结下。

接收器

在接收数据时,编程的时候有几个比较重要的标志位我们来总结下。

④ 时钟与波特率

中断控制

USART 初始化结构体详解

1) USART_BaudRate:波特率设置。一般设置为2400、9600、19200、115200。标准库函数会根据 设定值计算得到USARTDIV值,从而设置USART_BRR寄存器值。

2) USART_WordLength:数据帧字长,可选8位或9位。它设定USART_CR1寄存器的M位的值。 如果没有使能奇偶校验控制,一般使用8数据位;如果使能了奇偶校验则一般设置为9数据位。

3) USART_StopBits:停止位设置,可选0.5个、1个、1.5个和2个停止位,它设定USART_CR2 寄存器的STOP[1:0]位的值,一般我们选择1个停止位。

4) USART_Parity:奇偶校验控制选择,可选USART_Parity_No(无校验)、USART_Parity_Even(偶 校验)以及USART_Parity_Odd(奇校验),它设定USART_CR1寄存器的PCE位和PS位的值。

5) USART_Mode:USART模式选择,有USART_Mode_Rx和USART_Mode_Tx,允许使用逻辑或 运算选择两个,它设定USART_CR1寄存器的RE位和TE位。

6) USART_HardwareFlowControl:硬件流控制选择,只有在硬件流控制模式才有效,可选有使能 RTS、使能CTS、同时使能RTS和CTS、不使能硬件流。

Usart.c

#include "Usart.h"


void Usart_Init(void)
{
	
	GPIO_InitTypeDef GPIO_InitStruct;
	USART_InitTypeDef  USART_InitStruct;
	 //打开串口GPIO的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	
	//将USARTTx的GPIO配置为推挽复用模式
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;  
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
	GPIO_InitStruct.GPIO_Speed =  GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	 // 将 USART Rx 的 GPIO 配置为浮空输入模式
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;  //浮空输入模式
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStruct.GPIO_Speed =  GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	
	// 配置串口的工作参数
	// 配置波特率
	USART_InitStruct.USART_BaudRate = 115200;
	// 配置硬件流控制
	USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	 // 配置工作模式,收发一起
	USART_InitStruct.USART_Mode =  USART_Mode_Rx | USART_Mode_Tx;
	 // 配置校验位
	USART_InitStruct.USART_Parity = USART_Parity_No;
	 // 配置停止位
	USART_InitStruct.USART_StopBits = USART_StopBits_1;
	// 配置 针数据字长
	USART_InitStruct.USART_WordLength = USART_WordLength_8b;
	 // 完成串口的初始化配置
	USART_Init(USART1,&USART_InitStruct);
	// 串口中断优先级配置
	NVIC_Configuration();
	
	 //配置指定的USART中断
	USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
	
	// 使能串口
	USART_Cmd(USART1,ENABLE);
}

static void NVIC_Configuration(void)
{
	
	NVIC_InitTypeDef NVIC_InitStructure;
	 /* 嵌套向量中断控制器组选择 */
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	 /* 配置 USART 为中断源 */
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	 /*使能中断*/
	NVIC_InitStructure.NVIC_IRQChannelCmd =ENABLE;
	 /* 抢断优先级为 1 */
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	/*子优先级为2*/
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
	/*初始化配置NVIC */
	NVIC_Init(&NVIC_InitStructure);

}


//发送一个字节
void Usart_SendByte(USART_TypeDef *pUSARTx, uint8_t ch)
{
	/* 发送一个字节数据到 USART */
	USART_SendData(pUSARTx,ch);
	 /* 等待发送数据寄存器为空 */
	while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TXE) == RESET);

}


//发送两个字节
void Usart_SendHalfWore(USART_TypeDef *pUSARTx,uint16_t data)
{

	uint8_t temp_h,temp_l;
	temp_h = (data&0xff00)>>8;
	temp_l = data&0xff;
	/* 发送一个字节数据到 USART */
	USART_SendData(pUSARTx,temp_h);
	 /* 等待发送数据寄存器为空 */
	while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TXE) == RESET);
	
	USART_SendData(pUSARTx,temp_l);
	 /* 等待发送数据寄存器为空 */
	while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TXE) == RESET);
	
}


/*发送8位数据的数组*/
void Usart_SendArray(USART_TypeDef *pUSARTx,uint8_t *arry,uint8_t num)
{

	uint8_t i;
	for(i=0;i<num;i++) 
	{
		Usart_SendByte(pUSARTx,arry[i]);
	
	}
	while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC) == RESET);

}


//发送一个字符串
void Usart_SendString(USART_TypeDef *pUSARTx,uint8_t *String)
{
	uint8_t i = 0;
	do
	{
		Usart_SendByte(pUSARTx,*(String+i));
		i++;
	
	}while(*(String+i) != '\0');
	
	while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC) == RESET);
}




//中断函数无返回值无参数
void USART1_IRQHandler(void)
{
	uint8_t Temp;
	
	if(USART_GetITStatus(USART1,USART_IT_RXNE) != RESET)
	{
	
		Temp = USART_ReceiveData(USART1);
		USART_SendData(USART1,Temp);
	}


}

Usart.h

#ifndef __USART_H
#define __USART_H

#include "stm32f10x.h"                  // Device header
#include "stdio.h"


void Usart_Init(void);
static void NVIC_Configuration(void);
void Usart_SendByte(USART_TypeDef *pUSARTx, uint8_t ch);
void Usart_SendHalfWore(USART_TypeDef *pUSARTx,uint16_t data);

void Usart_SendArray(USART_TypeDef *pUSARTx,uint8_t *arry,uint8_t num);
void Usart_SendString(USART_TypeDef *pUSARTx,uint8_t *String);
	
#endif

main函数

#include "stm32f10x.h"                  // Device header
#include "Usart.h"



int main(void)
{
	
	uint8_t arry[10] = {0,1,2,3,4,5,6,7,8,9};
	uint8_t arr[] = "huang shi jiang\n";
	/* 初始化 USART 配置模式为 115200 8-N-1,中断接收 */
	Usart_Init();
	//Usart_SendByte(USART1,'A');
	
	//Usart_SendHalfWore(USART1,0xff55);
	
	//Usart_SendArray(USART1,arry,10);
	Usart_SendString(USART1,arr);
	
	while(1)	
	{
	
	}

}

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

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

相关文章

基于布谷鸟算法的无人机航迹规划-附代码

基于布谷鸟算法的无人机航迹规划 文章目录 基于布谷鸟算法的无人机航迹规划1.布谷鸟搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要&#xff1a;本文主要介绍利用布谷鸟算法来优化无人机航迹规划。 1.布谷鸟…

[Python进阶] 消息框、弹窗:pymsgbox.alert

6.18 消息框、弹窗&#xff1a;pymsgbox.alert 作用&#xff1a; 显示带有文本和单个OK按钮的简单消息框。返回所单击按钮的文本。 参数&#xff1a; text “”, 消息框标题 title “”, 消息框内容 button pymsgbox.OK_TEXT, 消息框自带的按钮&#xff0c;默认为&#xff…

@TableField(fill = FieldFill.INSERT)这个注解的作用

TableField 是 MyBatis-Plus提供的一个注解&#xff0c;用于标注实体类的属性与数据库表的字段之间的映射关系。当你在一个实体类的属性上使用 TableField(fill FieldFill.INSERT) 注解时&#xff0c;你告诉 MyBatis-Plus 在插入记录时自动填充这个字段。 FieldFill.INSERT 是一…

Docker 网络管理及资源控制

目录 1 Docker 网络 1.1 Docker 网络实现原理 1.2 Docker 的网络模式 1.3 网络模式详解 1.3.1 host模式 1.3.2 container模式 1.3.3 none模式 1.3.4 bridge模式 1.3.5 自定义网络 1.4 创建自定义网络 2 资源控制 2.1 CPU 资源控制 2.2 对内存使用的限制 2.3 对磁盘…

如何在【逻辑回归】中优化控制正则化程度的超参数C

一.逻辑回归基本介绍 逻辑回归也称作logistic回归&#xff0c;是一种广义的线性回归分析模型&#xff0c;主要是用来解决二分类问题&#xff08;也可以解决多分类问题&#xff09;。通过训练集来训练模型&#xff0c;并在训练结束后对测试集进行分类。 通过激活函数&…

我该如何入门Python机器学习?

我是在研一的时候开始学习机器学习的。相对于题主来说&#xff0c;我更是一窍不通&#xff0c;Python都没有一点点基础。总结一下我在学习Python的过程&#xff0c;以及自己在学习机器学习过程中的用到的优质资源&#xff0c;也总结一下我的学习心得。 一、怎么学习Python&…

开放式耳机百元价位怎么选、公认最好的百元开放式耳机

开放式耳机采用挂耳式的佩戴方式&#xff0c;不需封闭耳道&#xff0c;这一创新设计允许我们欣赏音乐的同时保持对周围环境的感知&#xff0c;从而在户外运动、通勤或其他活动中提供更安全的体验。而且&#xff0c;在预算有限的情况下&#xff0c;我们可以在百元价位范围内找到…

JS中Map对象与object的区别

若想了解Map对象可以阅读本人这篇ES6初步了解Map Map对象与object有什么区别&#xff1f;让我为大家介绍一下吧&#xff01; 共同点 二者都是以key-value的形式对数据进行存储 const obj {name:"zs",age:18}console.log(obj)let m new Map()m.set("name&quo…

shell算数运算指令、shell的if分支结构使用场景及相关代码

1.shell算数运算的指令 (( )) $[ ] let expr expr的字符串运算 例子&#xff1a; 2.shell的if分支结构 例子&#xff1a;

【C++】C++入门(上)--命名空间 输入输出 缺省参数 函数重载

目录 一 命名空间 1 命名空间的定义 2 命名空间的使用 二 C输入和输出 1 输出 2 输入 三 缺省参数 1 缺省参数概念 2 缺省参数分类 (1) 全缺省参数 (2)半缺省参数 四 函数重载 1 函数重载概念 2 分类 1 参数类型不同 2 参数个数不同 3 参数类型顺序不同 3 C为什…

Python中json的用法

python 中 json的用法 一、JSON 的介绍二、json和python的转换1&#xff09; python 的字典或列表转换为json2) json转换为python的字典或列表 一、JSON 的介绍 Json本质上一个带有特定格式的字符串&#xff0c;json是一种在各个编程语言中流通的数据格式&#xff0c;负责不同…

Android底层摸索改BUG(二):Android系统移除预置APP

首先我先提供以下博主博文&#xff0c;对相关知识点可以提供理解、解决、思考的 Android 系统如何预装第三方应用以及常见问题汇集android Android.mk属性说明及预置系统app操作说明系Android 中去除系统原生apk的方法 取消预置APK方法一&#xff1a; 其实就是上面的链接3&a…

基于springboot实现休闲娱乐代理售票平台系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现休闲娱乐代理售票平台系统演示 摘要 网络的广泛应用给生活带来了十分的便利。所以把休闲娱乐代理售票管理与现在网络相结合&#xff0c;利用java技术建设休闲娱乐代理售票系统&#xff0c;实现休闲娱乐代理售票的信息化。则对于进一步提高休闲娱乐代理售票管…

1817_ChibiOS的RT线程

全部学习汇总&#xff1a; GreyZhang/g_ChibiOS: I found a new RTOS called ChibiOS and it seems interesting! (github.com) 1. 关于线程&#xff0c;有几个概念需要弄清楚&#xff1a;声明、生命循环、延迟、线程引用、线程队列、线程时间、优先级管理、调度。 2. 两个声明…

CS224W2.2——传统基于特征的方法(边层级特征)

在这篇中&#xff0c;我们介绍了链接预测的重要任务&#xff0c;以及如何提取链接级特征来更好地解决这类问题。这在我们需要预测缺失的边或预测将来会出现的边的情况下很有用。我们将讨论的链路级功能包括基于距离的功能&#xff0c;以及本地和全局邻域重叠。 文章目录 1. 边层…

1818_ChibiOS的计数信号量

全部学习汇总&#xff1a; GreyZhang/g_ChibiOS: I found a new RTOS called ChibiOS and it seems interesting! (github.com) 之前见过计数信号量&#xff0c;也是在FreeRTOS中看到的。也看到过这样的功能在驱动设计中的应用&#xff0c;但是当时没有理解这个使用的方式。 1.…

接口自动化测试 —— JMeter断言基本使用!

断言 断言&#xff1a;就是让程序判断预期结果和实际结果是否一致 注意&#xff1a;请求发起成功了&#xff0c;不代表着一定符合预期的结果。 JMeter中常用断言 响应断言 JSON断言 持续时间断言 响应断言 步骤&#xff1a;&#xff1a;线程组——HTTP取样器——断言—…

File相关方法2

一.获取当前目录下所有一级文件名称 1.代码 package org.example;import java.io.File;public class day03 {public static void main(String[] args) {//获取当前目录下所有一级文件名称final File f1 new File("d:/temp");final String[] name f1.list();for (…

【博士每天一篇文献-算法】Gradient Episodic Memory for Continual Learning

阅读时间&#xff1a;2023-10-26 1 介绍 年份&#xff1a;2017 作者&#xff1a;David Lopez-Paz, Marc’Aurelio Ranzato 期刊&#xff1a;Part of Advances in Neural Information Processing Systems 30 (NIPS 2017) 引用量&#xff1a;2044 针对持续学习中灾难性遗忘问题…

怎么在电脑上多屏播放和实时视频输入,ProVideoPlayer 功能介绍

ProVideoPlayer for mac简称pvp2&#xff0c;是一款Mac系统的多屏播放软件&#xff0c;可将视频映射&#xff08;包括播放和实时视频输入&#xff09;并实时控制到一个或多个输出端&#xff0c;实现包括实时效果、调度、网络同步和内容管理等多种效果&#xff0c;provideoplaye…