STM32 USART串口通信实战指南:从寄存器配置到代码调试的避坑技巧

知识点【通信的分类】

1、通信分类

(1)串行/并行

  • 串行

    工作方式:

    在串行通信中,数据位按照顺序依次传输,也就是说,每一位数据都依次发送或者接收。

    优点:

    相对简单,不容易出现数据冲突。由于只有一个通信通道,线路的布线较为简单。

    缺点:

    速度相对较慢,因为每次只能传输一位数据。不适合大量数据的快速传输。

    典型应用:

    USB,UART,光纤通信

  • 并行

    工作方式:

    在并行通信中,多个数据位同时传输。每个位都有自己的通道,可以独立传输,从而在同一时刻传输多个位。

    优点:

    速度相对较快,尤其适合大量数据的快速传输。适用于需要同时处理多个数据位的情况。

    缺点:

    复杂度较高,占用引脚资源多。容易出现数据同步问题

    典型应用:

    适用于短距离传输,长距离传输成本高

(2)同步/异步

  • 同步

    工作方式:

    在同步通信中,数据的发送和接收都是在预定的时钟信号下进行的。数据的发送方和接收方需要共享相同的时钟源,以确保数据的同步。

    优点:

    数据传输的时序清晰,易于管理和理解。适用于需要实时性和精准同步的应用。

    缺点:

    高频时钟衰弱较快,通信过程易发生信号畸变,相位偏移,因此传输距离不宜过长

    典型应用:

    I2C,HDMI,CPU和内存接口等

  • 异步

    工作方式:

    在异步通信中,数据段发送和接受不依赖于共享时钟信号。每个数据块之间有一定的间隔,从而不需要严格的时序同步。通信设备会使用起始位和停止位来标识数据块的开始和结束。

    优点:

    较为灵活,不需要精准度的时钟同步。传输媒介简单,传输距离长。

    缺点:

    在高速传输和长距离通信时,由于没有同步的时钟,可能会出现数据失真。接收端解码复杂性增加,可靠性较差。

    典型应用:

    UART,USB1.1,USB2.0,光纤通信

(3)单工/半双工/全双工

  • 单工

    工作方式:

    单工通信是一种单向通信模式,数据只能在一个方向上传输。通常,一个设备是发送者,而另一个设备是接收者。

    特点:

    通信双方只能在一个特定的方向上传输信息,其中一个设备全能发送,而另一个只能接收。

    典型应用:

    无线电广播,电视广播等

  • 半双工

    工作方式:

    半双工通信是一种双向通信方式,但是通信双方不能同时进行数据传输。在任意时刻,一个设备可以发送,而另一个设备可以接受,但不能同时进行。

    特点:

    数据传输时双向的,但是不能同时发送,需要在发送和接受之间切换。

    典型应用:

    对讲机,传统的无线电通信等。

  • 全双工

    工作方式:

    全双工通信是一种双向通信模式,其中通信的双方能够同时进行发送和接收操作,允许双方同时传输数据。

    特点:

    双方可以在同一时间内同时发送和接收数据,实现真正的双向通信

    典型应用:

    电话通话,互联网语音通话,典型的计算机网络通信等。

以上部分源自

        原文链接:https://blog.csdn.net/m0_58427556/article/details/135302591

2、UART/USART介绍

(1)定义

UART( Universal Asynchronous Receiver-Transmitter)是一种采用 全双工异步串行通信方式的 通用异步收发传输器

它在发送数据时并行数据转换为串行数据来传输,在接收数据时将收到的串行数据转换为并行数据

(2)波特率

波特率是指每秒传输的位数,是通信双方事先约定好的。

通信双方必须使用相同的波特率才能正常通信, 单位:bps(位/秒)。常用的波特率有9600,19200,38400等。

(3)数据帧

数据帧的格式包括起始位,数据位,奇偶校验位(可选),停止位 的组合

3、物理层分析

USRT至少需要两条数据线,发送线:TX,接受线:RX。TX用于发送数据,RX用于接收数据

4、CH340 (USB信号转串口)

CH340是USB 转串口芯片

5、USB与串口信号的区别

1、USB信号

差分信号传输:USB使用D+和D-两条差分线传输数据,通过电压差表示逻辑“0”和“1”抗干扰能力强,适合高速传输

同步传输:支持全双工模式,且内置时钟同步机制,无需外部时钟信号。

支持热拔插

通过USB集线器(Hub)可扩展连接多个设备动态分配带宽

2、串口信号

单端信号传输:传统串口(RS232)采用单线电压变化(如+3V~+15V表示逻辑“0”,-3V~-15V表示逻辑“1”)传输数据,抗干扰能力较弱

异步通信:依赖发送端和接收端约定的波特率,无统一时钟信号,数据帧以起始位、数据位、校验位和停止位组成

不支持热拔插

原生串口通常仅支持点对点通信,扩展需通过串口扩展卡

3、使用场景

USB信号:高速传输,短距离传输

串口信号:低速传输,远距离支持

RS485,采用差分信号,传输距离可达1200米(无中继)

知识点1【USART寄存器介绍】

这里我只介绍 我们实现串口通信用到的寄存器

1、状态寄存器

位7:TXE发送数据寄存器空

当检测到 发送数据寄存器为空 即 数据转送到移位寄存器的时候,移位寄存器发送数据,并将TXE置1。如果TXEIE为1,会产生中断,中断向TDR中写入数据,并将TXE置0。

位5:RXNE读数据寄存器非空

当检测到 接收数据寄存器非空 即从移位寄存器中读取数据的时候,移位寄存器会接收数据的同时,硬件将RXNE置1。如果TXEIE为1,会产生中断。中断从TDR中读数据,并将RXNE置0。

2、数据寄存器

包含了发送或接受寄存器,发送:TDR,接收:RDR

TDR寄存器提供了内部总线和输出移位寄存器之间的并行接口。

RDR寄存器提供了输入移位寄存器和内部总线之间的并行接口。

3、波特比率寄存器

波特率比率寄存器(USARTDIV)的配置 被分为小数和整数两部分

Mantissa是 整数部分

Fraction是 小数部分

我们需要根据要配置的波特率计算出 USARTDIV ,然后按照下面例题进行配置。

4、控制寄存器

1、控制寄存器1

位13:USART使能

位12:字长

0:一个起始位,8个数据位,n个停止位

1:一个起始位,9个数据位,n个停止位

起始位:1bit的电平

停止位:1bit的电平

多出来的这个位,可被用于校验或者地址标识

位10:校验控制使能

位3:发送时能

位2:接收使能

补充:校验——奇偶校验

偶校验:检测有效数据 + 校验位1 的个数是否为偶数

奇校验:检测有效数据 + 校验位1 的个数是否为奇数

2、控制寄存器2

这里我们只需要配置12,13口

这两个是负责停止位的位数的

还有控制寄存器3,我们这里用不到,不详细介绍

知识点2【配置引脚】

我们先看原理图

可以看到,我们需要配置TX,RX引脚

配置输入输出的模式是什么?

PA9:复用推挽输出

PA10:浮空输入

知识点3【配置流程】

1、初始化函数

1、时钟配置

2、引脚模式设置

3、配置停止位长

4、配置位长

5、使能

2、发送数据函数

3、重定向fputc

由于printf内部是由fputc为基础的,因此我们可以重定向fputc以修改printf的功能

知识点4【代码演示】

#include "stm32f10x.h"   // 相当于51单片机中的  #include <reg51.h>
#include "stdio.h"

void usart_init(u32 baud);
void usart_recv();
int fputc(int c, FILE * stream);
int main(void)
{
	usart_init(9600);
	
	printf("串口开启完毕\\n");
	while(1)
	{
		usart_recv();
	}
}
void usart_init(u32 baud)
{
	float div = 0.0f;
	u32 div_mantissa = 0;
	u32 div_fraction = 0;
	
	//初始化时钟 usart1 在APB2
	RCC->APB2ENR |= (0x01 << 14);
	RCC->APB2ENR |= (0x01 << 2);
	
	//初始化端口 usart1 的TX引脚是PA9,RX引脚是PA10
	//输出引脚模式 复用推挽输出
	//输入引脚模式 浮空输入
	GPIOA->CRH &= ~(0x0F << 4);
	GPIOA->CRH |= (0x09 << 4);
	
	GPIOA->CRH &= ~(0x0F << 8);
	GPIOA->CRH |= (0x04 << 8);
	
	//配置总位长
	USART1->CR1 &= ~(0x01 << 12);
	
	//配置停止位长
	USART1->CR2 &= ~(0x03 << 12);
	
	USART1->CR1 &= ~(0x01 << 10);

	//波特率配置
	div = 72000000/(baud*16);
	div_mantissa = (u32)div;
	div_fraction = (u32)((div - (float)div_mantissa)*16 + 0.5f);
	USART1->BRR = div_mantissa << 4 | div_fraction;

	
	//使能
	USART1->CR1 |= (0x01 << 2);
	USART1->CR1 |= (0x01 << 3);
	USART1->CR1 |= (0x01 << 13);
}

void usart_recv()
{
	u8 c = 0;
	while((USART1->SR & (0x01 << 5)) == 0);
	c = USART1->DR;
	
	while((USART1->SR & (0x01 << 7)) == 0);
	USART1->DR = c;
}

int fputc(int c, FILE * stream)
{
	while(!(USART1->SR &(0X01<<7)));
	USART1->DR=c;
	return c;
	
}

代码运行结果

所犯错误:

代码错误1

USART1**->**BRR是→而不是_

代码错误2

波特率忘记配置

代码错误3

波特率公式错误,忘记16

结束

代码重在练习!

代码重在练习!

代码重在练习!

今天的分享就到此结束了,希望对你有所帮助,如果你喜欢我的分享,请点赞收藏加关注,谢谢大家!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值