串口通信方式 基础知识、printf重定向、串口中断接收、串口发送接收控制LED灯
文章目录
- 串口USART
- 1. 常见的通信方式
- 1.1 串行通信和并行通信
- 1.2 全双工,半双工和单工通信
- 1.3 同步通信和异步通信
- 1.4 通信速率
- 1.5 常见的通信协议
- 2. 串口基础知识
- 2.1 电平特性
- 2.2 串口传输协议
- 2.3 STM32F103的USART资源
- 2.4 STM32F103的UART框图
- 2.4.1 端口引脚
- 2.4.2 数据寄存器单元
- 2.4.3 发送接收控制单元
- 2.4.4 波特率发生器
- 2.4.5 UART框图配置步骤
- 3. 实现串口发送
- 3.1 发送字符和字符串
- 3.2 TXE 和 TC
- 4. printf重定向
- 5. 实现串口中断接收
- 6. 串口发送接收控制LED灯
串口USART
1. 常见的通信方式
1.1 串行通信和并行通信
串行通信:速度较并行慢,但是占用的硬件资源少,通常只需要时钟线,一两根数据线还有片选线即可。

并行通信:速度快,但是需要很多根数据线、地址线等。

1.2 全双工,半双工和单工通信
全双工:同一时刻双方可以互相发送数据、接收数据

半双工:同一时刻只能有一方可以给另外一方发送数据,即此发彼收,此收彼发

单工:只能由发送方数据发送给接收方

1.3 同步通信和异步通信
- 同步通信和异步通信都是针对串行通信而言
- 异步通信
- 1.数据是以字符为单位组成字符帧传输的。
- 2.字符帧由发送端一帧一帧的发送,每帧数据均是低位在前,高位在后,通过传输线被接收端一帧一帧的接收。
- 3.发送端和接收端可以有各自独立的时钟来控制数据的发送和接收,这两个时钟各自独立,互不同步。
- 4.接收端依靠字符帧格式来判断发送端是何时开始和结束发送的。
- 5.字符帧也叫做数据帧,由起始位,数据位,奇偶校验位,停止位等部分组成,是异步通信的一个重要指标。
- 6.同步通信的另一个重要指标是波特率 (表示每秒钟传输的符号数量,单位是 波特)。
- 同步通信
- 1.同步是指在约定的通信速率下,发送端和接收端的时钟信号始终保持一致,保证通信双方在发送和接收数据时具有完全一致的定时关系。
- 2.同步通信把许多字符组成一个信息帧,每帧的开始用同步字符来表示。
- 3.在绝大多数场合下,发送端和接收端,采用的都是同一个时钟,所以在传送数据的同时还要发送时钟信号,以便接收端可以使用时钟信号来确定每一个信息位。
- 4.同步通信一次通信只能传送一帧信息。
1.4 通信速率
对于同步通信,通信速率由时钟信号决定,时钟信号越快,传输速度越快。
对于异步通信来说,需要收发双方提前统一通信速率,这也就是我们串口调试时,波特率不对显示乱码的原因。
1、比特率:系统在单位时间内传输的比特率个数 (二进制0或1) ,通常用Rb表示,单位是比特 (bit/s),缩写为bps。
2、波特率:系统在单位时间内传输的码元个数,通常用RB来表示,单位是波特 (Bd)
3、码元有N个状态时,比特率与波特率的关系式:Rb = RB × log2 N (比特率 = 波特率 × 每符号比特数)
1.5 常见的通信协议
在嵌入式中,有众多的通信协议,往往从性能,成本,稳定性,易用性等角度考虑选择合适的协议。

2. 串口基础知识
2.1 电平特性


2.2 串口传输协议

参数概念:
- 波特率:一般选波特率都会有9600,19200,115200等选项,其实意思就是每秒传输的码元数。
- 起始位:先发出一个逻辑 0 的信号,表示传输数据的开始。
- 数据位:可以是5~8位逻辑 “0” 或“1”,先传输Bit0,再传输bit1,以此类推。
- 校验位:数据位加上这一位之后,使得 1 的位数应为偶数(偶校验)或者奇数(奇校验),以此来校验数据传送的正确性,校验位是可选的,可以不传输。
- 停止位:它是一个字符数据的结束标志,数据线变回逻辑“1”。
2.3 STM32F103的USART资源
- STM32103有三个通用同步异步收发器USART,两个通用异步收发器UART,USART也可以当作UART使用。
- 通常使用的是UART功能,USART在某些场合会使用到,选择通信方式使用场合决定。
- 可以通过电平转化芯片变为RS232/RS485电平。

2.4 STM32F103的UART框图

2.4.1 端口引脚


- TX:数据发送端口
- RX:数据接收端口
- SW_RX:在单线和智能卡模式下接收数据,属于内部端口,没有实际的外部引脚
- RTS:在硬件流控制下用于指示设备准备好可以接收数据了,低电平表示可以接收数据
- CTS:在硬件流控制下用于指示设备 接收方准备好接收数据,允许发送方开始发送,如果是高电平那么在本次数据发送完成后会阻塞下一次的传输,只有在低电平的时候才允许下一次传输。
- CK:同步时钟端口,在同步通信模式下使用,用于输出同步时钟信号。
2.4.2 数据寄存器单元

- TDR:发送数据寄存器
- RDR:接收数据寄存器
- 在UART外设中只有一个寄存器USART_DR,是一个双向寄存器,取决于CPU是读这个寄存器还是写这个寄存器;如果是读就是RDR,如果是写就是TDR。
2.4.3 发送接收控制单元

- CR1/CR2/CR3:控制寄存器,控制各种使能,比如UART使能、收发中断使能、DMA使能等等。
- SR 状态寄存器:用来表明UART的收发状态和错误状态等等。
- GTPR:Smartcard和IrDA模式下专用的寄存器
2.4.4 波特率发生器

- fPCLK:外设总线时钟,USART1在APB1,最高可取72MHZ,剩下四个在APB2,最高可取36MHZ
- USARTDIV:USART/UART时钟分频器
- DIV_Mantissa:BBR寄存器的高12bit,用于存放波特率设置的整数部分
- DIV_Fraction:BRR寄存器的低4bit,用于存放波特率设置值的小数部分,每一位对应的精度是1/2的四次方 = 0.0625
- 波特率计算公式:baudrate = fPCLK / USARTDIV * 16
1、假设fPCLK = 72MHZ,baudrate = 115200, 那么USARTDIV=72MHZ/16/115200 =39.0625, 则DIV_Mantissa = 39<<4 = 0x270,DIV_Fraction=0.0625/0.0625=1, 因此BRR= 0X271
2、假设fPCLK = 72MHZ, baudrate = 9600, 那么USARTDIV=72MHZ/9600 = 468.75, 则DIV_Mantissa = 468<<4=0x1D40, DIV_Fraction=0.75/0.0625=12=0xC, 因而BRR=0X1D4C
2.4.5 UART框图配置步骤
- 选择需要使用的USART/UART (根据地址映射表得到地址)
- 根据需要的波特率设置BRR寄存器
- 根据需求配置控制寄存器中的停止位和校验位
- 根据需求配置同步时钟使能位
- 使能USART的发送和接收位
- 根据需求使能发送和接收的中断位
- 使能RCC中的选中的USART/UART的时钟
- 使能USART/UART
- 写USART_DR寄存器发送数据,读USART_DR寄存器接收数据
3. 实现串口发送
3.1 发送字符和字符串
软件流程设计
- 初始化系统
- 初始化GPIO、串口外设时钟
- 初始化串口引脚 (A9 数据发送, A10 数据接收)
- 初始化串口外设
- 串口发送
// USART.h 头文件
#ifndef USART_H
#define USART_H
void My_Usart_Init(void);
void My_Usart_Send_Byte(USART_TypeDef* USARTx, uint16_t Data);
void My_Usart_Send_String(USART_TypeDef* USARTx, char *str);
#endif
// USART.c 源文件
#include "stm32f10x.h"
#include "USART.h"
// 定义 USART 串口函数
void My_Usart_Init(void){
GPIO_InitTypeDef GPIO_InitStruct;
USART_InitTypeDef USART_InitStruct; // 定义 USART 结构体
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);
USART_Cmd(USART1, ENABLE); // 串口时钟使能
// GPIOA9 TX 输出数据发送
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// GPIOA10 RX 输入 数据接收
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// 串口 USART1 初始化
USART_InitStruct.USART_BaudRate = 115200; // 波特率
USART_InitStruct.USART_WordLength = USART_WordLength_8b; // 串口数据的字节长度
USART_InitStruct.USART_StopBits = USART_StopBits_1; // 停止位
USART_InitStruct.USART_Parity = USART_Parity_No; // 奇偶校验位
USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; // 发送 接收模式
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 硬件流控制
USART_Init(USART1, &USART_InitStruct); // 初始化 USART1 结构体
}
// USART 串口发送一个字节函数
void My_Usart_Send_Byte(USART_TypeDef* USARTx, uint16_t Data){
USART_SendData(USARTx, Data);
// 等待传输完成(TC标志置位), 发送移位寄存器为空(影子寄存器)
while(USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET);
}
// USART串口发送字符串函数
void My_Usart_Send_String(USART_TypeDef* USARTx, char *str){
uint16_t i = 0;
while(*(str+i) != ' '){
My_Usart_Send_Byte(USARTx, *(str+i));
i++;
};
// 所有字节已在 My_Usart_Send_Byte 中等待 TC, 此处无需再等
}
// main.c
#include "stm32f10x.h"
#include "main.h"
#include "USART.h"
void delay(uint16_t time)
{
uint16_t i=0;
while(time--)
{
i = 12000;
while(i--);
}
}
int main()
{
My_Usart_Init();
My_Usart_Send_Byte(USART1, 'A');
My_Usart_Send_Byte(USART1, 'B');
My_Usart_Send_Byte(USART1, 'C');
My_Usart_Send_String(USART1, "ZhangSan
");
while(1)
{
}
}
库函数实现串口发送
串口USART结构体:
typedef struct {
uint32_tUSART_BaudRate; // 设置 USART 的波特率
uint16_tUSART_WordLength; // 设置数据帧中的数据位长度
uint16_tUSART_StopBits; // 设置停止位的数量
uint16_tUSART_Parity; // 设置奇偶校验方式
uint16_tUSART_Mode; // 设置 USART 的工作模式 (发送/接收使能)
uint16_tUSART_HardwareFlowControl; // 设置硬件流控制 (RTS/CTS 信号)
} USART_InitTypeDef;
串口USART相关库函数:
voidUSART_DeInit(USART_TypeDef*USARTx);
voidUSART_Init(USART_TypeDef*USARTx, USART_InitTypeDef*
USART_InitStruct);
voidUSART_StructInit(USART_InitTypeDef*USART_InitStruct);
voidUSART_ClockInit(USART_TypeDef*USARTx, USART_ClockInitTypeDef*
USART_ClockInitStruct);
voidUSART_ClockStructInit(USART_ClockInitTypeDef*
USART_ClockInitStruct);
voidUSART_Cmd(USART_TypeDef*USARTx, FunctionalStateNewState);
voidUSART_ITConfig(USART_TypeDef*USARTx, uint16_tUSART_IT,
FunctionalStateNewState);
voidUSART_DMACmd(USART_TypeDef*USARTx, uint16_tUSART_DMAReq,
FunctionalStateNewState);
voidUSART_SetAddress(USART_TypeDef*USARTx, uint8_tUSART_Address);
voidUSART_WakeUpConfig(USART_TypeDef*USARTx, uint16_tUSART_WakeUp);voidUSART_ReceiverWakeUpCmd(USART_TypeDef*USARTx, FunctionalState
NewState);
voidUSART_LINBreakDetectLengthConfig(USART_TypeDef*USARTx, uint16_t
USART_LINBreakDetectLength);
voidUSART_LINCmd(USART_TypeDef*USARTx, FunctionalStateNewState);
voidUSART_SendData(USART_TypeDef*USARTx, uint16_tData);
uint16_tUSART_ReceiveData(USART_TypeDef*USARTx);
voidUSART_SendBreak(USART_TypeDef*USARTx);
voidUSART_SetGuardTime(USART_TypeDef*USARTx, uint8_t
USART_GuardTime);
voidUSART_SetPrescaler(USART_TypeDef*USARTx, uint8_t
USART_Prescaler);
voidUSART_SmartCardCmd(USART_TypeDef*USARTx, FunctionalState
NewState);
voidUSART_SmartCardNACKCmd(USART_TypeDef*USARTx, FunctionalState
NewState);
voidUSART_HalfDuplexCmd(USART_TypeDef*USARTx, FunctionalState
NewState);
voidUSART_OverSampling8Cmd(USART_TypeDef*USARTx, FunctionalState
NewState);
voidUSART_OneBitMethodCmd(USART_TypeDef*USARTx, FunctionalState
NewState);
voidUSART_IrDAConfig(USART_TypeDef*USARTx, uint16_tUSART_IrDAMode);voidUSART_IrDACmd(USART_TypeDef*USARTx, FunctionalStateNewState);
FlagStatusUSART_GetFlagStatus(USART_TypeDef*USARTx, uint16_t
USART_FLAG);
voidUSART_ClearFlag(USART_TypeDef*USARTx, uint16_tUSART_FLAG);
ITStatusUSART_GetITStatus(USART_TypeDef*USARTx, uint16_tUSART_IT);
voidUSART_ClearITPendingBit(USART_TypeDef*USARTx, uint16_t
USART_IT);
3.2 TXE 和 TC
| 标志位 | 含义 | 何时置位 |
|---|---|---|
USART_FLAG_TXE | 发送数据寄存器为空 | 数据从 DR 移入移位寄存器后立即置位(数据尚未完全发出!) |
USART_FLAG_TC | 传输完成 | 整个帧(包括停止位)真正发送完毕 |
| 场景 | 使用 TXE | 使用 TC |
|---|---|---|
| 发送速度 | 更快(可提前写入下一字节) | 稍慢(需等完整帧) |
| 数据可靠性 | ❌ 可能丢尾字节 | ✅ 保证物理层发送完成 |
| 适用场合 | 高速连续发送(如 DMA 或中断缓冲) | 单字节/调试输出/可靠传输 |
4. printf重定向
C语言里面的printf函数默认输出设备是显示器,如果要实现printf函数输出在串口或LCD显示屏上,必须要重定义标准库函数里面调用的I/O输出设备相关的函数,比如printf输出串口,需要将 fputc 里面的输出指向串口。
1、配置勾选

2、printf 重定向
// USATR.c 源文件
#include "stm32f10x.h"
#include "USART.h"
#include "stdio.h"
// 定义 USART 串口函数
void My_Usart_Init(void){
GPIO_InitTypeDef GPIO_InitStruct;
USART_InitTypeDef USART_InitStruct; // 定义 USART 结构体
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);
USART_Cmd(USART1, ENABLE); // 串口时钟使能
// GPIOA9 TX 输出数据发送
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// GPIOA10 RX 输入 数据接收
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// 串口 USART1 初始化
USART_InitStruct.USART_BaudRate = 115200; // 波特率
USART_InitStruct.USART_WordLength = USART_WordLength_8b; // 串口数据的字节长度
USART_InitStruct.USART_StopBits = USART_StopBits_1; // 停止位
USART_InitStruct.USART_Parity = USART_Parity_No; // 奇偶校验位
USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; // 发送 接收模式
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 硬件流控制
USART_Init(USART1, &USART_InitStruct); // 初始化 USART1 结构体
}
// printf 重定向
int fputc(int ch, FILE *p){
USART_SendData(USART1, (u8)ch);
// 等待整个帧发送完成 (包括停止位)
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
return ch;
}
// main.c
#include "stm32f10x.h"
#include "main.h"
#include "USART.h"
#include "stdio.h"
int main()
{
My_Usart_Init();
while(1)
{
printf("Hello World
");
}
}
5. 实现串口中断接收
软件流程设计
- 初始化系统
- 初始化GPIO、串口时钟
- 初始化GPIO、串口引脚
- 初始化串口中断接收外设、NVIC嵌套中断控制器
- 编写串口中断函数
// USATR.c 源文件
#include "stm32f10x.h"
#include "USART.h"
#include "stdio.h"
// 定义 USART 串口函数
void My_Usart_Init(void){
GPIO_InitTypeDef GPIO_InitStruct; // 定义 GPIO 结构体
USART_InitTypeDef USART_InitStruct; // 定义 USART 结构体
NVIC_InitTypeDef NVIC_InitStruct; // 定义 NVIC 结构体
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);
USART_Cmd(USART1, ENABLE); // 串口时钟使能
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 优先级分组配置
// GPIOA9 TX 输出数据发送
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// GPIOA10 RX 输入 数据接收
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// 串口 USART1 初始化
USART_InitStruct.USART_BaudRate = 115200; // 波特率
USART_InitStruct.USART_WordLength = USART_WordLength_8b; // 串口数据的字节长度
USART_InitStruct.USART_StopBits = USART_StopBits_1; // 停止位
USART_InitStruct.USART_Parity = USART_Parity_No; // 奇偶校验位
USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; // 发送 接收模式
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 硬件流控制
USART_Init(USART1, &USART_InitStruct); // 初始化 USART1 结构体
// 串行通信中断配置
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // 接收数据寄存器不为空发生中断
// NVIC 初始化
NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn; // 初始化串口中断线1
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
}
// printf 重定向
int fputc(int ch, FILE *p){
USART_SendData(USART1, (u8)ch);
// 等待整个帧发送完成 (包括停止位)
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
return ch;
}
// 串口中断函数, 只要满足完整中断条件, 自动执行函数
// "中断配置条件" 必须同时包含 USART配置 + NVIC使能
void USART1_IRQHandler(void){
char str;
// 如果检查到串口中断线(USART1)发生了中断请求
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET){
str = USART_ReceiveData(USART1); // 串口数据接收
printf("receive date: %c
", str);
// 清除串口中断线(USART1)的中断挂起标志位, 方便下次还能运行函数
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}
}
// main.c
#include "stm32f10x.h"
#include "main.h"
#include "USART.h"
int main()
{
My_Usart_Init();
while(1)
{
}
}
6. 串口发送接收控制LED灯
// USATR.c 源文件
#include "stm32f10x.h"
#include "USART.h"
#include "stdio.h"
// 定义 USART 串口函数
void My_Usart_Init(void){
GPIO_InitTypeDef GPIO_InitStruct; // 定义 GPIO 结构体
USART_InitTypeDef USART_InitStruct; // 定义 USART 结构体
NVIC_InitTypeDef NVIC_InitStruct; // 定义 NVIC 结构体
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);
USART_Cmd(USART1, ENABLE); // 串口时钟使能
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 优先级分组配置
// GPIOA9 TX 输出数据发送
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// GPIOA10 RX 输入 数据接收
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// 串口 USART1 初始化
USART_InitStruct.USART_BaudRate = 115200; // 波特率
USART_InitStruct.USART_WordLength = USART_WordLength_8b; // 串口数据的字节长度
USART_InitStruct.USART_StopBits = USART_StopBits_1; // 停止位
USART_InitStruct.USART_Parity = USART_Parity_No; // 奇偶校验位
USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; // 发送 接收模式
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 硬件流控制
USART_Init(USART1, &USART_InitStruct); // 初始化 USART1 结构体
// 串行通信中断配置
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // 接收数据寄存器不为空发生中断
// NVIC 初始化
NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn; // 初始化串口中断线1
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
}
// printf 重定向
int fputc(int ch, FILE *p){
USART_SendData(USART1, (u8)ch);
// 等待整个帧发送完成 (包括停止位)
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
return ch;
}
// 串口中断函数, 只要满足完整中断条件, 自动执行函数
// "中断配置条件" 必须同时包含 USART配置 + NVIC使能
void USART1_IRQHandler(void){
char str;
// 如果检查到串口中断线(USART1)发生了中断请求
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET){
str = USART_ReceiveData(USART1); // 串口数据接收
printf("receive date: %c
", str);
// 清除串口中断线(USART1)的中断挂起标志位, 方便下次还能运行函数
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}
}
// 串口中断函数, 只要满足完整中断条件, 自动执行函数
void USART1_IRQHandler(void){
char str = 0;
// 判断是否发生中断
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET){
str = USART_ReceiveData(USART1); // 串口数据接收
printf("receive date: %c
", str);
// 串口接收到字符 0 开灯
if(str == '0'){
GPIO_ResetBits(GPIOA, GPIO_Pin_1);
printf("LED IS ON
");
}
// 串口接收到字符 1 关灯
if(str == '1'){
GPIO_SetBits(GPIOA, GPIO_Pin_1);
printf("LED IS OFF
");
}
// 清除串口中断线的挂起标志位, 方便函数下次运行
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}
}
// main.c
#include "stm32f10x.h"
#include "main.h"
#include "USART.h"
#include "LED.h"
int main()
{
My_Usart_Init();
LED_Init();
while(1)
{
}
}









