USART(只有USART1使用APB2总线其他是APB1)
- 串行通信(Serial Communication)
串行通信是一种逐位地传输数据的方式,其中每个数据位依次传输,一个接一个。特点如下:
传输方式: 数据位按照顺序一个接一个地通过单一的通信线路传输。
线路要求: 通常只需要使用少量的通信线路(如一根或几根),这样可以节省硬件成本和空间。
速度和距离: 相对于并行通信,串行通信的速度可能较慢,但可以通过提高通信速率来弥补这一点。此外,串行通信的传输距离一般较远。
典型应用: 常见于远距离通信、网络通信、以太网、串口通信(如RS-232、UART)、USB等。
- 并行通信(Parallel Communication)
并行通信是一种同时传输多位数据的方式,即每个数据位使用单独的通信线路。特点如下:
传输方式: 多个数据位同时传输,每个数据位有自己的通信线路。
线路要求: 需要多条并行线路来传输每个数据位,因此需要更多的硬件资源。
速度和距离: 并行通信通常比串行通信快,因为每个时钟周期可以传输多个数据位。但同时也受到线路长度和同步等问题的限制,通常用于较短距离的高速通信。
典型应用: 常见于计算机内部的数据传输,如CPU与内存之间的数据传输、并行接口(如并行打印口、SCSI接口)等。
- 单工、半双工与全双工通信
单工通信(Simplex)
单工通信是指数据只能单向传输的通信方式,即数据在通信的过程中只能单向流动。特点如下:
传输方向: 只能由一个设备发送数据,另一端只能接收数据,不能进行数据发送。**
通信示例: 典型的例子包括广播电台和电视信号的传输。接收器只能接收信号,而不能发送信号。
优点与局限: 简单且成本较低,因为只需要单向通信的硬件设施。但是,通信受到发送和接收方能否同步接收和发送数据的限制,灵活性较低。
半双工通信(Half-duplex)
半双工通信允许数据在两个方向上进行传输,但不能同时进行,必须在发送和接收之间切换。特点如下:
传输方向: 数据可以在两个方向上进行传输,但同一时刻只能单向进行。
通信示例: 一些对讲机和无线电通信系统属于半双工通信。每次只能有一方说话,另一方必须倾听,不能同时说话。
优点与局限: 比单工通信灵活,因为可以在两个方向上传输数据。但是通信效率较低,因为必须在发送和接收之间切换,不能同时进行数据传输。
全双工通信(Full-duplex)
全双工通信允许数据在两个方向上同时进行传输,发送和接收可以同时进行而不互相干扰。特点如下:
传输方向: 可以同时进行数据的发送和接收,允许双方同时进行数据交换。
通信示例: 计算机网络中的大多数数据通信属于全双工通信,如以太网、Wi-Fi网络等。两端的设备可以同时发送和接收数据包。
优点与局限: 通信效率高,因为可以同时进行发送和接收,提高了数据传输的吞吐量。但是相比半双工和单工通信,需要更复杂的硬件和协议支持。
- 比特率(通常以每秒传输的位数(或比特数)来衡量)bps
- 波特率(看码元)通常等于比特率
- 奇偶校验
- 1/0校验
- AFIO
在STM32微控制器中,AFIO(Alternate Function I/O)功能模块用于管理和配置芯片上的引脚复用功能。AFIO模块可以帮助配置引脚的功能,使其可以复用为多种不同的外设功能,例如串口、SPI、I2C等。因此,需要在以下情况下打开串口复用端口时钟和AFIO功能:
1.配置引脚复用功能:当需要将某个引脚配置为串口通信的功能时,需要使用AFIO功能来确保该引脚正确地映射到串口的输入输出线路。打开串口复用端口时钟和AFIO功能可以让你在初始化串口之前正确地配置这些引脚,确保串口能够正常工作。
2.选择正确的引脚映射:不同型号的STM32微控制器有不同的引脚映射和功能配置选项。AFIO模块可以帮助你选择和配置正确的引脚映射,以使得串口功能能够与硬件正确匹配。因此,在初始化串口之前,通常需要打开AFIO的时钟来进行必要的引脚配置。
3.管理外设功能:AFIO模块不仅仅用于串口,还用于配置和管理其他外设的引脚复用功能。因此,打开串口复用端口时钟和AFIO功能可以使得整个外设管理系统能够正常工作,确保外设功能在引脚和硬件层面上正确配置和匹配。
综上所述,打开串口复用端口时钟和AFIO功能是为了在STM32微控制器上正确配置和管理引脚的复用功能,以确保串口通信和其他外设功能能够正常初始化和操作。
在STM32标准外设库中,要正确地打开AFIO时钟和串口(或其他外设)的时钟,并配置引脚复用功能,通常需要遵循以下步骤。以下示例假设你要初始化 USART1,并配置其引脚复用功能。
步骤:
1.打开串口(USART1)的时钟:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
这条语句会使能 USART1 外设的时钟。具体的宏定义 RCC_APB2Periph_USART1 可能会根据你的具体微控制器型号有所不同,需要查看对应的头文件来确定。
2.打开AFIO时钟:
在标准外设库中,AFIO时钟通常在RCC(Reset and Clock Control)寄存器组中控制。例如:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
这条语句会使能 AFIO 的时钟,以便后续可以配置引脚的复用功能。
3.配置引脚复用功能:
配置引脚复用功能是通过 GPIO_InitTypeDef 结构体来完成的。例如,如果要将 USART1 的 TX 引脚映射到 GPIOA 的 Pin 9 上,代码如下:
GPIO_InitTypeDef GPIO_InitStructure;
// 打开 GPIOA 的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// 配置 TX 引脚为复用推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 将引脚映射到 USART1
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
这里使用了 GPIO_PinAFConfig 函数将 GPIOA 的 Pin 9 映射到 USART1 的 TX 引脚,使用了 GPIOModeAF_PP 模式来设置为复用推挽输出。
4.初始化 USART1:
最后,使用标准外设库提供的函数初始化 USART1。例如,配置波特率、数据位、停止位等参数。
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_Init(USART1, &USART_InitStructure);
// 使能 USART1
USART_Cmd(USART1, ENABLE)
- 传输字符串
#include "stm32f10x.h"
// 函数原型
void USART1_SendString(char *str);
int main(void) {
// 初始化 USART1
USART_InitTypeDef USART_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
// 使能 USART1 时钟和 GPIOA 时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
// 配置 USART1 TX 引脚为复用推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 初始化 USART1
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_Mode = USART_Mode_Tx;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_Init(USART1, &USART_InitStructure);
// 使能 USART1
USART_Cmd(USART1, ENABLE);
// 示例:发送字符串 "Hello, World!"
USART1_SendString("Hello, World!");
while (1) {
// 主循环
}
}
// 发送字符串函数的实现
void USART1_SendString(char *str) {
while (*str) {
// 等待发送缓冲区空闲
while (USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
// 发送字符到 USART 数据寄存器
USART_SendData(USART1, *str++);
}
}
nvic中断
- 抢占优先级和响应优先级
- 在STM32的中断控制中,每个中断都有两个相关的优先级:抢占优先级(Preemption Priority)和响应优先级(Subpriority)。这两个优先级共同决定了中断服务程序(ISR)的执行顺序和中断嵌套的处理方式。
抢占优先级(Preemption Priority)
抢占优先级决定了中断间的优先级,即当一个具有更高抢占优先级的中断发生时,它可以抢占正在执行的具有较低抢占优先级的中断。在STM32中,抢占优先级的数值越小,优先级越高(0为最高)。
1.应用场景:当一个高优先级的中断发生时,可以立即中断当前正在执行的低优先级中断的执行,执行高优先级中断的服务程序。
响应优先级(Subpriority)
响应优先级决定了在同一个抢占优先级内,不同中断的执行顺序。当同一抢占优先级内发生多个中断时,响应优先级越低(数值越小),中断服务程序越先执行。在STM32中,响应优先级的数值越小,优先级越高(0为最高)。
2.应用场景:在同一抢占优先级的多个中断同时触发时,根据响应优先级确定这些中断的执行顺序。
设置方法
在STM32中,通过以下方式设置中断的优先级:
void NVIC_Configuration(void) {
NVIC_InitTypeDef NVIC_InitStructure;
// 配置中断分组
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
// 配置EXTI Line0中断
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01; // 抢占优先级 1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01; // 响应优先级 1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
在上面的示例中,NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 和 NVIC_InitStructure.NVIC_IRQChannelSubPriority 分别设置了抢占优先级和响应优先级。如果有多个中断,可以根据实际需求调整这两个优先级来达到预期的中断处理顺序。
- 相同的pin不能同时触发中断