【STM32嵌入式系统设计与开发---拓展】——1_11_1串口通信(USART)

发布于:2024-07-27 ⋅ 阅读:(41) ⋅ 点赞:(0)

1、一般我们都怎么进行通信的?

(1)串行通行(Serial Communication)

UART(Universal Asynchronous Receiver/Transmitter):实现方式:使用微控制器的UART模块,通过配置波特率、数据位、停止位和奇偶校验来进行通信。
应用场景:微控制器之间的通信,调试信息输出等。

SPI(Serial Peripheral Interface)
实现方式:配置主设备和从设备的SPI模块,设置时钟极性、时钟相位和数据传输速率。
应用场景:传感器、显示器、存储器等外设通信。

I2C(Inter-Integrated Circuit)
实现方式:配置I2C主从设备的地址,设置数据传输速率,并处理数据传输中的ACK/NACK信号。
应用场景:短距离设备间通信,如EEPROM、传感器等。

(2)并行通信

并口(Parallel Port)
实现方式:使用数据总线和控制信号线,传输多个数据位。通常在计算机和打印机等设备中使用。
应用场景:早期计算机与打印机、扫描仪等外围设备通信。

(3)无线网络通信

Bluetooth
实现方式:使用蓝牙模块(如HC-05、HM-10),进行配对和数据传输。
应用场景:短距离无线通信,如无线耳机、键盘、鼠标等。

Wi-Fi
实现方式:使用Wi-Fi模块(如ESP8266、ESP32),配置SSID和密码,通过TCP/IP协议进行数据传输。

Zigbee
实现方式:使用Zigbee模块(如XBee),配置网络ID和通道,通过Zigbee协议进行数据传输。
应用场景:低功耗无线通信,智能家居、传感器网络。

(4)网络通信

以太网(Ethernet)
实现方式:使用以太网模块(如ENC28J60、W5500),配置IP地址、子网掩码和网关,通过TCP/IP协议进行数据传输。

应用场景:有线局域网、工业自动化系统。
光纤通信(Fiber Optic Communication)
实现方式:使用光纤收发模块,通过光纤传输数据,适用于高速和长距离通信。
应用场景:高速数据传输、远距离通信。

(5)现场总线通信

Modbus
实现方式:使用Modbus协议库,通过串口、以太网等接口进行主从通信。
应用场景:工业自动化和控制系统。

Profibus
实现方式:使用Profibus接口卡和协议栈,配置站地址和波特率。
应用场景:工厂自动化和过程控制。

2、串口通信之间对比?

在这里插入图片描述

3、通信类型有哪些?异步/同步/半双工/全双工又是什么?

在这里插入图片描述

4、怎么理解在串口通信?

串口是一种应用十分广泛的通讯接口,串口成本低、容易使用、通信线路简单,可实现两个设备的互相通信
单片机的串口可以使单片机与单片机、单片机与电脑、单片机与各式各样的模块互相通信,极大地扩展了单片机的应用范围,
增强了单片机系统的硬件实力
简单双向串口通信有两根通信线(发送端TX和接收端RX)
TX与RX要交叉连接
当只需单向的数据传输时,可以只接一根通信线
当电平标准不一致时,需要加电平转换芯片

在这里插入图片描述

5、使用的时候需要配置什么?

波特率:串口通信的速率
起始位:标志一个数据帧的开始,固定为低电平
数据位:数据帧的有效载荷,1为高电平,0为低电平,低位先行
校验位:用于数据验证,根据数据位计算得来
停止位:用于数据帧间隔,固定为高电平

在这里插入图片描述
在这里插入图片描述

/*********************************************************************
 @Function  : USART1初始化
 @Parameter : bound : 波特率 
 @Return    : N/A
**********************************************************************/   	
void usart1_init(uint32_t bound)
{	
	GPIO_InitTypeDef GPIO_InitStructure; // 定义一个 GPIO 初始化结构体
	USART_InitTypeDef USART_InitStructure; // 定义一个 USART 初始化结构体
	
  /*时钟使能*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE); // 使能 USART1 和 GPIOA 的时钟
	
	/*引脚复用*/  //PA9->TXD 
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;         // 配置 GPIOA 的引脚 9 为 USART1 的 TX 引脚
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 设置引脚速度为 50 MHz
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;   // 设置引脚模式为复用推挽输出
	GPIO_Init(GPIOA, &GPIO_InitStructure);            // 初始化 GPIOA 引脚 9
	
	/*引脚复用*/  //PA10->RXD
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;            // 配置 GPIOA 的引脚 10 为 USART1 的 RX 引脚
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 设置引脚模式为浮空输入
	GPIO_Init(GPIOA, &GPIO_InitStructure);                // 初始化 GPIOA 引脚 10 
	
  /*USART设置*/
	USART_InitStructure.USART_BaudRate = bound;                 // 设置 USART 波特率
	USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 设置 USART 字长为 8 位
	USART_InitStructure.USART_StopBits = USART_StopBits_1;      // 设置停止位为 1 位
	USART_InitStructure.USART_Parity = USART_Parity_No;         // 设置无奇偶校验
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 设置无硬件流控制
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // 设置 USART 模式为接收和发送模式
  USART_Init(USART1, &USART_InitStructure);                         // 初始化 USART1
	
  USART_Cmd(USART1, ENABLE);                                       // 使能 USART1                  
}

推挽输出和复用推挽输出怎么选?

复用推挽输出用于当一个 GPIO 引脚需要执行特定外设功能(如串口通信的发送引脚)时,使引脚能够在高低电平之间切换并与外设模块共享;在 USART 通信中,TX 引脚配置为复用推挽输出是因为它需要由串口模块驱动以发送数据,实现串口通信功能

推挽输出(Push-Pull Output):用于简单的数字输出,比如控制一个 LED 的亮灭。它只是在高电平和低电平之间切换。

复用推挽输出(Alternate Function Push-Pull Output):用于引脚需要执行特定功能(比如串口通信)的情况。除了在高低电平之间切换,还能和外设模块(比如串口、I2C、SPI)共享,引脚不再只是普通的输入输出,而是用来传输数据。

为什么用浮空输入?

浮空输入的优势包括:
可以检测到微弱的信号:由于浮空输入的端口阻抗很大,类似于电压表内阻很大的情况,这样可以更灵敏地检测到外部信号的变化。
适用于多种标准通讯协议:例如 IIC、USART 等总线设备,在这些应用中,浮空输入有助于保证数据传输的准确性和稳定性。

串口定义的结构体?

/**
@brief USART 初始化结构体定义
*/
typedef struct
{
uint32_t USART_BaudRate; /* 此成员配置 USART 通信波特率。 */

uint16_t USART_StopBits; /* 指定传输的停止位数量。*/
*/
uint16_t USART_Parity; /*!< 指定奇偶校验模式。 */
uint16_t USART_Mode; /* 指定接收或发送模式是启用还是禁用。 */
uint16_t USART_HardwareFlowControl; /* 指定硬件流控制模式是启用还是禁用。*/
} USART_InitTypeDef;

6、为什么能够printf();?

将printf重定向到USART1(串口1)–这样我们就能通过串口1将信息打印到上位机(串口助手)

//加入以下代码,支持printf函数,而不需要选择use MicroLIB	  
#if 1
#pragma import(__use_no_semihosting)             
/*********************************************************************
 @Function  : 标准库需要的支持函数 
 @Parameter : N/A
 @Return    : N/A
**********************************************************************/              
struct __FILE 
{ 
	int handle; 
}; 

FILE __stdout;   

/*********************************************************************
 @Function  : 定义_sys_exit()以避免使用半主机模式
 @Parameter : X :
 @Return    : N/A
**********************************************************************/   
void _sys_exit(int x) 
{ 
	x = x; 
} 

/*********************************************************************
 @Function  : 重定义fputc函数
 @Parameter : ch :入口数据
							 f :入口指针
 @Return    : ch :入口数据
**********************************************************************/
int fputc(int ch, FILE *f)
{      
	while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
    USART1->DR = (u8) ch;      
	return ch;
}
#endif 

一预处理、二定义、三个函数?


1预、#pragmaimport(__use_no_semihosting),确保不从C库中使用半主机函数
2定、定义:__FILE结构体,避免HAL库某些情况下报错
定义: FILE_stdout,避免编译报错实现
3函数、_sys_exit和fputc(int ch, FILE *f)等三个函数


A[开始] --> B{是否调用 printf 函数}
B -->|是| C[进入 fputc 函数]
C --> D{串口是否发送完毕}
D -->|否| C
D -->|是| E[返回 printf 函数]
E --> F[继续程序执行]
B -->|否| F
graph TD
A[开始] --> B{是否调用 printf 函数}
B -->|是| C[进入 fputc 函数]
C --> D{串口是否发送完毕}
D -->|否| C
D -->|是| E[返回 printf 函数]
E --> F[继续程序执行]
B -->|否| F

半主机模式又是什么?

半主机模式就是在开发ARM单片机程序的时候,让程序能借用电脑(就是开发用的那台电脑)的屏幕来显示输出内容,比如用printf函数输出的东西能在电脑屏幕上看到,还能通过电脑的键盘给程序输入内容。
但真正把程序放到嵌入式设备里运行的时候,设备可没法直接用电脑的这些输入输出功能了,所以就得把这个模式关掉。不然程序可能会因为找不到电脑的帮忙而出问题。

半主机模式就好比是在开发单片机程序时,开了个“后门”,能让程序把要输出的东西,比如像用printf输出的那些文字,都发到我们用来开发的电脑屏幕上显示,也能通过电脑键盘给程序输入东西。
可等程序真正装到单片机里运行的时候,单片机可没法跟开发用的电脑连着了,这时候要是还开着这个“后门”,程序就会找不到地方去显示输出或者接收输入,就会乱套。所以得把这个模式关掉


网站公告

今日签到

点亮在社区的每一天
去签到