STM32F4XX之串口

news2024/10/7 17:23:11

一、标准串口(UART)介绍

1、通信协议相关概念

1.1同步通信和异步通信

(1)同步通信:两个器件之间共用一个时钟线,要发送的数据在时钟的作用下一位一位发送出去。

(2)异步通信:指两个器件之间没有时钟线连接,器件接受/发送数据时使用各自的时钟,以不同的时钟频率进行通信。

1.2串行与并行通信

(1)串行通信:只有一根数据线,各个数据位通过数据线按照顺序一位一位的传输。

优点:稳定性高、简单、成本低

缺点:速度慢

(2)并行通信:有多根数据线,各个数据位同时传输。

优点:速度快。

缺点:稳定性不高、设计复杂、成本高。(占用引脚资源多)

1.3单工、半双工、全双工通信

(1)单工:数据只能由设备A到设备B,不能从设备B到设备A,(任何时候只能是一个方向,如遥控器)。

(2)半双工:设备A发送数据给设备B或者设备B发送数据给设备A。(数据可以在两个方向上传输。同一时刻,数据只能在一个方向传输,传输方向可切换的单工通信;接收端和发送端,可以使用一个端口(扩展)。如对讲机)。

(3)全双工:设备A发送数据给设备B的同时,设备B也可以发送数据给设备A。(允许数据同时在两个方向上传输,发送接收互补影响,所以需要独立的接收端和发送端)。

2、标准串口(UART)概念及其作用

2.1概念:串口也称串行通信接口,是一种MCU与其他器件通信的通信协议。

2.2作用:主要用于芯片与芯片之间、模块与芯片之间、模块与模块之间按照这种通信协议进行数据交换。如:STM32F4XX 和 GSM ,WIFE.北斗.语音,5G模块等。

2.2.1标准UART的协议类型及拓扑接口(接口标准)

底层:接口规范

标准UART的协议类型:异步串行全双工。(没有时钟线,一条发送数据线,一条接收数据线)

RXD:数据接收管脚;R = receive接受

TXD:数据发送管脚;T = transmit发送

注意:地线在硬件上一定要接,否则数据不正常。

2.2.2标准UART的数据帧格式

数据帧格式:将要发送的真正的信息和其它通信必须的信号封装成一包数据,这一包数据包含以下几个内容。

标准UART中一帧数据:1位起始位+(5~8)数据位+1位校验位+(0.5~2)位停止位。

空闲电平:数据线不传输数据时的状态,该状态为高电平。

起始位:该状态为低电平,占用一个bit,代表通信开始。
数据位:真正传输的数据,占用5~8bit。
校验位:为了检测数据传输的正确与否。占用1bit。

(一般不用)奇偶校验位:奇校验:1000 1100  0  
偶校验:1110 0000  1
停止位:该状态为高电平,占用0.5~2bit,代表通信结束。

2.2.3标准串口速率控制
什么是波特率?波特率的作用是什么?
(1)波特率的作用和概念: 当接收和发送器件的时钟频率不一致时,为了让数据可以正确的收发,所以双方要规定好一个合适的频率进行通信,规定的这个频率称之为波特率,波特率又叫比特率。 
(2)波特率:单位时间内传输的二进制代码的有效位数,其常用单位为每秒比特数bit/s(bps== bit per second)。
(3)常用的波特率:115200、38400、9600,每秒能传输多少位数据。
总结:标准UART的四要素:波特率(通讯速率),数据位长度,校验位,停止位长度。

二、串口的概述

串口是模块是芯片内部的一个片内外设。

STM32F407单片机内部共有6个串口

1.USART介绍

名词解析:USART :Universal Synchronous/Asynchronous ReceiverTransmitters

U:通用的        S:同步        A:异步        R:接受        T:发送
通用同步异步收发器 (USART) 能够灵活地与外部设备进行全双工数据交换,满足外部设备对工业标准 NRZ 异步串行数据格式的要求。 

2.UART框图分析

2.1管脚部分

TX:发送数据管脚

RX:接收数据管脚

2.2数据发送/接收部分

 CPU定义一个8位或者9位的数据并写入到数据寄存器(DR)
1发送数据’A’: USART->DR= ’A’;

(cpu)读取接收数据寄存器(DR)里的值。(人为)
2接受数据:int a= USART->DR;

串口通讯流程

2.3波特率设置

USART 通过小数波特率发生器提供了多种波特率。

2.4控制部分及寄存器分析

三、UART相关寄存器介绍

状态寄存器 (USART_SR)

位 7 TXE:发送数据寄存器为空 (Transmit data register empty) 
当 TDR 寄存器的内容已传输到移位寄存器时,该位由硬件置 1。
如果 USART_CR1 寄存器 中 TXEIE 位 = 1,则会生成中断。通过对 USART_DR 寄存器执行写入操作将该位清零。
 0:数据未传输到移位寄存器 
 1:数据传输到移位寄存器 
位 6 TC:发送完成 (Transmission complete) 
如果已完成对包含数据的帧的发送并且 TXE 置 1,则该位由硬件置 1。如果 USART_CR1 寄存器中 TCIE = 1,则会生成中断。该位由软件序列清零(读取 USART_SR 寄存器,然后写入 USART_DR 寄存器)。TC 位也可以通过向该位写入‘0’来清零。建议仅在多缓冲区通信时使用此清零序列。 
 0:传送未完成
 1:传送已完成 
位 5 RXNE:读取数据寄存器不为空 (Read data register not empty) 
当 RDR 移位寄存器的内容已传输到 USART_DR 寄存器时,该位由硬件置 1。如果 USART_CR1 寄存器中 RXNEIE = 1,则会生成中断。通过对 USART_DR 寄存器执行读入操作将该位清零。RXNE 标志也可以通过向该位写入零来清零。建议仅在多缓冲区通信时使用此清零序列。
0:未接收到数据 
1:已准备好读取接收到的数据 
位 4 IDLE:检测到空闲线路 (IDLE line detected) 
检测到空闲线路时,该位由硬件置 1。如果 USART_CR1 寄存器中 IDLEIE = 1,则会生成中 断。该位由软件序列清零(读入 USART_SR 寄存器,然后读入 USART_DR 寄存器)。 
0:未检测到空闲线路
1:检测到空闲线路 
注意:直到 RXNE 位本身已置 1 时(即,当出现新的空闲线路时)IDLE 位才会被再次置 1。 

2.数据寄存器 (USART_DR)
位 8:0 DR[8:0]:数据值 
    包含接收到数据字符或已发送的数据字符,具体取决于所执行的操作是“读取”操作还是“写入”操作。
因为数据寄存器包含两个寄存器,一个用于发送 (TDR),一个用于接收 (RDR),因此它具有双重功能(读和写)。
3.波特率寄存器 (USART_BRR)

位 31:16 保留,必须保持复位值 
    位 15:4 DIV_Mantissa[11:0]:USARTDIV 的尾数 
        这 12 个位用于定义 USART 除数 (USARTDIV) 的尾数 
    位 3:0 DIV_Fraction[3:0]:USARTDIV 的小数 
    这 4 个位用于定义 USART 除数 (USARTDIV) 的小数。当 OVER8 = 1 时,不考虑 DIV_Fraction3 
位,且必须将该位保持清零。
注意: 如果 TE 或 RE 位分别被禁止,则波特计数器会停止计数。
4.控制寄存器 1 (USART_CR1)

位 15 OVER8:过采样模式 (Oversampling mode) 
0:16 倍过采样 
1:8 倍过采样
//过采样就是为得到一个信号真实情况,需要用一个比这个信号频率高的采样信号去检测,也就是将串口接收的速度提高了,16倍就是采样速度提高16倍,即会采样更多 的点来确定数据的正确性但为了得到越高频率采样信号越也困难,运算和功耗等等也会增加,所以一般选择合适就好。
位 13 UE:USART 使能 (USART enable) 
该位清零后,USART 预分频器和输出将停止,并会结束当前字节传输以降低功耗。此位由软件置 1 和清零。 
0:禁止 USART 预分频器和输出 
1:使能 USART
注意:串口全部配置好,最后打开此位
位 12 M:字长 (Word length)
该位决定了字长。该位由软件置 1 或清零。 
0:1 起始位,8 数据位,n 停止位 
1:1 起始位,9 数据位,n 停止位
位 3 TE:发送器使能 (Transmitter enable) 
该位使能发送器。该位由软件置 1 和清零。 
0:禁止发送器 
1:使能发送器
位 2 RE:接收器使能 (Receiver enable) 
该位使能接收器。该位由软件置 1 和清零。 
0:禁止接收器 
1:使能接收器并开始搜索起始位
5.控制寄存器 2 (USART_CR2)

位 13:12 STOP:停止位 (STOP bit) 
这些位用于编程停止位。 
00:1 个停止位 
01:0.5 个停止位 
10:2 个停止位 
11:1.5 个停止位

6.外设时钟使能寄存器
USART是学习STM32F407ZGT6的第一个外设,这个外设如果要正常工作需要开启相应的时钟(打开开关)。USART外设接在哪条总线上。《STM32F407ZGT6数据手册》第二章节芯片框架中有。开启RCC相关寄存器配置。
(1).RCC APB1 外设时钟使能寄存器 (RCC_APB1ENR)

位 20 UART5EN:UART5 时钟使能 (UART5 clock enable) 
 由软件置 1 和清零。 
 0:禁止 UART5 时钟 
 1:使能 UART5 时钟 
 位 19 UART4EN:UART4 时钟使能 (UART4 clock enable) 
 由软件置 1 和清零。 
 0:禁止 UART4 时钟 
 1:使能 UART4 时钟 
 位 18 USART3EN:USART3 时钟使能 (USART3 clock enable) 
 由软件置 1 和清零。 
 0:禁止 USART3 时钟 
 1:使能 USART3 时钟 
 位 17 USART2EN:USART2 时钟使能 (USART2 clock enable) 
 由软件置 1 和清零。 
 0:禁止 USART2 时钟 
 1:使能 USART2 时钟
 (2)RCC APB2 外设时钟使能寄存器 (RCC_APB2ENR)
位 5 USART6EN:USART6 时钟使能 (USART6 clock enable)
 由软件置 1 和清零。 
0:禁止 USART6 时钟 
1:使能 USART6 时钟位 
4 USART1EN:USART1 时钟使能 (USART1 clock enable)
 由软件置 1 和清零。 
0:禁止 USART1 时钟 
1:使能 USART1 时钟
四、硬件分析

五、软件分析

 配置GPIO口
1. 打开GPIOA的时钟
2. 配置PA9和PA10为复用模式
3. 推挽类型
4. 不需要上下拉
5. 速度2M
6. 复用到哪里?
配置USART
1. 打开USART1外设时钟
2. 配置CR1寄存器(16倍过采样,8位字长,接收器和发送器使能,无奇偶校验)
3. 配置停止位(CR2)
4. 配置波特率(BRR)
5. 使能USART1
6. 发送数据出去(DR)
 

#include "usart1.h"

/************************************
函数功能:USART1初始化
函数形参:u32 baud -- 波特率
函数返回值:void
函数说明:
	PA9 -- 复用到USART1_TX
	PA10 -- 复用到USART1_RX
作者:
日期:
************************************/
void Usart1_Init(u32 baud)
{
	float USARTDIV = 0;
	u16 DIV_Man = 0;
	u16 DIV_Fra = 0;
	
//	一.配置GPIO口
	//1.打开GPIOA的时钟
	RCC->AHB1ENR |= 0X1 << 0;
	
	//2.配置PA9和PA10为复用模式
	GPIOA->MODER &= ~(0XF << 9 *2);
	GPIOA->MODER |= 0XA << 9*2;
	
	//3.复用到哪里?往复用高位寄存器的9号和10号管脚写7
	GPIOA->AFR[1] &= ~(0XFF << 4);
	GPIOA->AFR[1] |= (0X77 << 4);
	
//	二.配置USART
	//1.打开USART1外设时钟
	RCC->APB2ENR |= 0X1 << 4;
	
	//2.配置CR1寄存器
	USART1->CR1 = 0;
	/*
		16倍过采样
		1 起始位, 8 数据位, n 停止位
		无奇偶校验
	*/
	USART1->CR1 |= 0X3 << 2;//接收器和发送器都使能了
	
	//3.配置1个停止位(CR2)
	USART1->CR2 &= ~(0X3 << 12);
	
	//4.配置波特率(BRR)
	USARTDIV = FPCLK / baud / 16;
	DIV_Man = USARTDIV;
	DIV_Fra = (USARTDIV - DIV_Man) *16;
	USART1->BRR = DIV_Man << 4 | DIV_Fra;
	
	//5.使能USART1
	USART1->CR1 |= 0X1 << 13;
	
}

/************************************
函数功能:使用USART发送字符串
函数形参:u8 *str
函数返回值:void
函数说明:
		可以通过USART1的DR寄存器发送数据到电脑上
作者:
日期:
************************************/
void Send_String(u8 *str)
{
	while(*str != 0)
	{
		if(USART1->SR & (0X1 << 7))
		{
			USART1->DR = *str;
			str++;//只有成功发出去才进行偏移
		}
	}
}

RECEVICE rec_str = {0};
/************************************
函数功能:接受一个字符串
函数形参:void
函数返回值:void
函数说明:
		要有一个接收电脑传过来数据的数组
		当前数组的长度
        有一个接收完成的标志位
		利用一个特定的字符来判断什么时候接受完数据
作者:
日期:
************************************/
void Receive_String(void)
{
	if(USART1->SR & (0X1 << 5))//判断什么时候接受到数据
	{
		if(USART1->DR != '\n')
		{
			rec_str.rec_buff[rec_str.len++] = USART1->DR;
		}
		else
		{
			rec_str.rec_buff[rec_str.len++] = USART1->DR;
			rec_str.rec_buff[rec_str.len] = '\0';
			rec_str.len = 0;//让下一次存储的字符串又从0号元素下标开始
			rec_str.flag = 1;//接收完成标志位可以让别人知道接收完整个字符串
		}	
	}	
}

//printf支持
#pragma import(__use_no_semihosting_swi) //取消半主机状态

struct __FILE { int handle; /* Add whatever you need here */ };
FILE __stdout;

int fputc(int ch, FILE *f) {
	while((USART1->SR &(0X01<<7))==0);
		USART1->DR=ch;
  return (ch);
}
int ferror(FILE *f) {
  /* Your implementation of ferror */
  return EOF;
}


void _ttywrch(int ch) {
  while((USART1->SR &(0X01<<7))==0);
		USART1->DR=ch;
}


void _sys_exit(int return_code) {
label:  goto label;  /* endless loop */
}
#ifndef __USART_H_
#define __USART_H_

#include "stm32f4xx.h"
#include "io_bit.h"
#include "stdio.h"

#define FPCLK 84000000
#define BUFFSIZE 256

typedef struct{
	u8 rec_buff[BUFFSIZE];//定义一个接收数据的数组
	u8 len; //当前接收到的数据的长度
	u8 flag;//表示当前接收到的数据已经是一个字符串的形式了
}RECEVICE;
extern RECEVICE rec_str;

void Usart1_Init(u32 baud);
void Send_String(u8 *str);
void Receive_String(void);
#endif

int main(void)
{
	Usart1_Init(9600);
	printf("111");
	while(1)
	{
		Receive_String();//不断的接收数据
		if(rec_str.flag == 1)
		{
			rec_str.flag = 0;//首先把标志位清零
			printf("接收到的字符串:%s\r\n",rec_str.rec_buff);
			memset(rec_str.rec_buff,0,sizeof(rec_str.rec_buff));
		}
	}
}

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

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

相关文章

Java基础(第一部):IDEA的下载和安装(步骤图) 项目结构的介绍 项目、模块、类的创建。第一个代码的实现

文章目录 IDEA1.1 IDEA概述1.2 IDEA的下载和安装1.2.1 下载1.2.2 安装 1.3 IDEA中层级结构介绍1.3.1 结构分类1.3.2 结构介绍project&#xff08;项目、工程&#xff09;module&#xff08;模块&#xff09;package&#xff08;包&#xff09;class&#xff08;类&#xff09; …

数据结构与算法-树

树 &#x1f388;1.树和二叉树&#x1f388;2.树&#x1f52d;2.1树的定义&#x1f52d;2.2树的4种表示方法&#x1f52d;2.3树的基本术语&#x1f52d;2.4树的抽象数据类型定义 &#x1f388;3.二叉树&#x1f52d;3.1二叉树的定义&#x1f52d;3.2二叉树的抽象数据类型定义&a…

MySQL 性能分析

MySQL 性能分析 对 mysql 进行性能分析&#xff0c;主要就是提升查询的效率&#xff0c;其中索引占主导地位。对 mysql 进行性能分析主要有如下几种方式&#xff1a; 方式一&#xff1a;查看 sql 执行频次 show global status like ‘Com_______’; // global 表示全局 show s…

力扣每日一题49:字母异位词分组

题目描述&#xff1a; 给你一个字符串数组&#xff0c;请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。 字母异位词 是由重新排列源单词的所有字母得到的一个新单词。 示例 1: 输入: strs ["eat", "tea", "tan", "ate&quo…

国产低功耗MCU芯片:Si24R03

Si24R03集成了基于RISC-V核的低功耗MCU和工作在2.4GHz ISM频段的无线收发器模块&#xff0c;是一款高度集成的低功耗SOC片。 应用领域&#xff1a; 1、物联网 2、智N门锁 3、电机控制 4、消费电子 5、工业控制 其无线收发器模块是专为低功耗无线场合设计&#xff0c;在关…

微信小程序开发的OA会议之会议,投票,个人中心的页面搭建及模板

目录 一.自定义组件 1.1.创建 1.2.定义 1.3.编写 1.4.使用 二.会议 2.1.数据 2.2.显示 2.3. 样式 三.个人中心 3.1.页面 3.2.样式 四.投票 4.1.引用 4.2.数据 4.3.页面 4.4.样式 好啦今天就到这里了&#xff0c;希望能帮到你哦&#xff01;&#xff01;&…

UGUI交互组件Dropdown

一.Dropdown的应用 Dropdown控件官方翻译为下拉选单&#xff0c;游戏中有一定程度的使用&#xff0c;其优势是用户体验优秀&#xff0c;节省界面空间&#xff0c;下图为某游戏的实际应用 二.Dropdown对象的结构 对象说明Label当前选中的选项Arrow向下或向上箭头表示展开方向Te…

Ubuntu服务器配置qq邮箱发送信息

效果&#xff1a; 此处设置的是自己给自己发送&#xff0c;配合linux的cron实现定时触发发送事件的效果 实现过程&#xff1a; 安装邮箱客户端Postfix sudo apt-get install postfix配置Postfix&#xff1a;编辑Postfix的主要配置文件 /etc/postfix/main.cf&#xff0c;并在…

uni-app:js实现数组中的相关处理

一、查询数组中&#xff0c;某一项中的某个数据为指定值的项&#xff08;find() 方法&#xff09; 使用分析 使用数组的 find() 方法来查询 id 为 0 的那一项数据。这个方法会返回满足条件的第一个元素&#xff0c;如果找不到符合条件的元素&#xff0c;则返回 undefined。使用…

跨路由器路由设置

1781的eth0网口地址设置为192.168.3.45并接入192.168.3.0网段里&#xff1b; 1781的eth1网口地址设置为10.0.9.20并接入10.0.0.0网段里&#xff0c;并且连接在网关地址为10.0.9.1的路由上。 192.168.1.140的摄像头接在网关为10.0.9.1的路由器上 现在的需求是1781网关在访问19…

CardView设置任意角为圆角

注意&#xff1a;material:1.1.0以上版本在RadiusCardView节点下一定要添加 android:theme“style/Theme.MaterialComponents”&#xff0c;不然会报错&#xff0c;另外&#xff0c;由于是重写自MaterialCardView&#xff0c;所以一定要导入material包&#xff1a; implementat…

2022年京东双11食品饮料品类数据回顾

2022年双11&#xff0c;根据京东官方发布的数据显示&#xff0c;京东百货中&#xff0c;京东新百货的589个品类10025个品牌成交额同比增长100%。而在食品饮料行业中&#xff0c;也有一些在大促期间成交额同比涨幅超过100%的品牌。 下面&#xff0c;结合鲸参谋平台提供的数据&am…

达梦mysql数据迁移出现datetime兼容问题

迁移工具无法连接mysql 这里需要指定驱动即可 数据迁移datetime数据无法导入 原因是时间中间带有T&#xff0c;达梦不支持这个格式的时间 解决办法也很简单&#xff0c;换最新的达梦驱动。 驱动安装文件里边就有&#xff0c;不用再去下载了。

【lesson13】进程地址空间收尾

文章目录 进程地址空间存在的原因原因一原因二原因三 重新理解什么是挂起&#xff1f; 进程地址空间存在的原因 原因一 凡是非法访问或者映射&#xff0c;OS都会识别到&#xff0c;并终止该进程。 例子&#xff1a; 我们会发现我们定义的字符串常量只有只读权限&#xff0c;…

Hadoop3教程(三十):(生产调优篇)纠删码

文章目录 &#xff08;155&#xff09;纠删码原理纠删码原理纠删码相关命令纠删码策略解释 &#xff08;156&#xff09;纠删码案例实操参考文献 &#xff08;155&#xff09;纠删码原理 纠删码原理 默认情况下&#xff0c;一个文件在HDFS里会保留3个副本&#xff0c;以此提高…

2023年【北京市安全员-A证】考试报名及北京市安全员-A证考试资料

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 北京市安全员-A证考试报名根据新北京市安全员-A证考试大纲要求&#xff0c;安全生产模拟考试一点通将北京市安全员-A证模拟考试试题进行汇编&#xff0c;组成一套北京市安全员-A证全真模拟考试试题&#xff0c;学员可…

【大揭秘】美团面试题:ConcurrentHashMap和Hashtable有什么区别?一文解析!

正文 亲爱的小伙伴们&#xff0c;大家好&#xff01;我是小米&#xff0c;一个热爱技术分享的程序员&#xff0c;今天我为大家带来了一篇有关美团面试题的热门话题&#xff1a;ConcurrentHashMap 和 Hashtable 有什么区别。这个问题在Java面试中常常被拿来考察对多线程编程的理…

基于TCP的RPC服务

TCP服务器上的RPC&#xff0c;通过创建一个服务器进程监听传入的tcp连接&#xff0c;并允许用户 通过此TCP流执行RPC命令 -module(tr_server). -author("chen"). -behaviour(gen_server).%% API -export([start_link/1,start_link/0,get_count/0,stop/0 ]).-export(…

基于金豺优化的BP神经网络(分类应用) - 附代码

基于金豺优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码 文章目录 基于金豺优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码1.鸢尾花iris数据介绍2.数据集整理3.金豺优化BP神经网络3.1 BP神经网络参数设置3.2 金豺算法应用 4.测试结果&#xff1a;5.M…

TUI界面容器管理工具Oxker

什么是 Oxker &#xff1f; Oxker 是一个基于文本的用户界面&#xff0c;用于查看 Docker 容器的信息和统计数据。一目了然&#xff0c;Oxker 提供了容器列表、其当前状态、对系统资源&#xff08;CPU、内存&#xff09;的影响、容器 ID、镜像名称、大小等。该应用程序还提供用…