这里写目录标题
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输出的那些文字,都发到我们用来开发的电脑屏幕上显示,也能通过电脑键盘给程序输入东西。
可等程序真正装到单片机里运行的时候,单片机可没法跟开发用的电脑连着了,这时候要是还开着这个“后门”,程序就会找不到地方去显示输出或者接收输入,就会乱套。所以得把这个模式关掉