非凡网站建设,温州网凝科技有限公司,外贸网络推广信,华美天一建筑公司网站目录 前言#xff1a; STM32串口通信基础知识#xff1a;
1#xff0c;STM32里的串口通信
2#xff0c;串口的发送和接收
串口发送#xff1a;
串口接收#xff1a;
串口在STM32中的配置#xff1a;
1. RCC开启USART、串口TX/RX所对应的GPIO口
2. 初始化GPIO口
…目录 前言 STM32串口通信基础知识
1STM32里的串口通信
2串口的发送和接收
串口发送
串口接收
串口在STM32中的配置
1. RCC开启USART、串口TX/RX所对应的GPIO口
2. 初始化GPIO口
3. 串口初始化
4. 串口使能
5. 串口发送数据
串口接收的两种实现方式
1轮询方式
2中断方式
查询RXNE标志位 使用中断
实战演练
1. 初始化LED灯相应的GPIO口
2. 初始化USART3
3. 实现发送功能
4. 实现接收字符串功能
1通过轮询的方式检查是否接收到了特定的字符串
2通过中断的方式实现USART3接收特定的字符串
1. 配置NVIC以使能USART3中断
2. 在USART3初始化函数中开启接收中断
3. 编写USART3的中断服务函数来处理接收到的字节
5. 主函数
总结 前言
本文在于记录自己最近做项目过程中遇到的问题和总结各种情况下串口通信在STM32的实际使用方面占有很大的比重本文主要对串口的发送和接受做了一个详细的总结和规划同时也对串口通信做一个简要的总结。 STM32串口通信基础知识
1STM32里的串口通信
在STM32里串口通信是USART,STM32可以通过串口和其他设备进行传输并行数据是全双工异步时钟控制设备之间是点对点的传输。对应的STM32引脚分别是RX和TX端。STM32的串口资源有USART1、USART2、USART3.
串口的几个重要的参数: 波特率串口通信的速率空闲一般为高电平起始位标志一个数据帧的开始固定为低电平。当数据开始发送时产生一个下降沿。(空闲–起始位)数据位发送数据帧1为高电平0为低电平。低位先行。 比如 发送数据帧0x0F 在数据帧里就是低位线性 即 1111 0000校验位用于数据验证根据数据位的计算得来。有奇校验偶校验和无校验。停止位用于数据的间隔固定为高电平。数据帧发送完成后产生一个上升沿。(数据传输–停止位) 下方就是一个字节数据的传输过程从图中可以看出串口发送的数据一般都是以数据帧的形式进行传输每个数据帧都由起始位数据位停止位组成 且停止位可变。 2串口的发送和接收
USART是STM32内部集成的硬件外设可以根据数据寄存器的一个字节数据自动生成数据帧时序从TX引脚发送出去也可以自动接收RX引脚的数据帧时序拼接成一个字节数据存放在数据寄存器里。
当配置好USART的电路之后直接读取数据寄存器就可以自动发送数据和接收数据了。在发送和接收的模块有4个重要的寄存器 发送数据寄存器TDR发送移位寄存器把一个字节的数据一位一位的移出去接收数据寄存器RDR接收移位寄存器把一个字节的数据 下方为串口的发送和接收图解 串口发送
在配置串口的各个参数时可以选择发送数据帧的数据位的大小可选8位或9位。
串口发送数据实际上就是对发送数据寄存器TDR进行写操作。
1. 当串口发送数据时会检测发送移位寄存器是不是有数据正在移位如果没有移位那么这个数据就会立刻转移到发送移位寄存器里。准备发送。
2. 当数据移动到移位寄存器时会产生一个TXE发送寄存器空标志位该位描述如下。当TXE被置1那么就可以在TDR写入下一个数据了。即发送下一个数据。 3. 发送移位寄存器在发送器控制的控制下向右移位一位一位的把数据传输到TX引脚。
4. 数据移位完成后新的数据就会再次从TDR转移到发送移位寄存器里来依次重复1-3的过程。通过读取TXE标志位来判断是否发送下一个数据。 串口接收
数据从RX引脚通向接收移位寄存器在接收控制的控制下一位一位的读取RX的电平把第一位放在最高位然后右移移位八次之后就可以接收一个字节了。当一个字节数据移位完成之后这一个字节的数据就会整体的移到接收数据寄存器RDR里来。在转移时会置RXNE接收标志位即RDR寄存器非空下方为该位的描述。当被置1后就说明数据可以被读出。 下图即为串口接收的工作流程 串口在STM32中的配置
1. RCC开启USART、串口TX/RX所对应的GPIO口
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE); //开启USART2的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); //开启GPIOA的时钟2. 初始化GPIO口
这里注意哈根据自己的需求来配置GPIO口发送和接收是都需要还是只需要其中一个。然后对应的根据引脚定义表来初始化对应的GPIO口。
USART3对应的引脚 USART2对应的引脚 USART1对应的引脚 这里根据手册来看RX引脚模式配置成浮空输入或者上拉输入。TX引脚模式配置成复用推挽输出。 GPIO_InitTypeDef GPIO_InitStructure;// USART3 TX - PB10GPIO_InitStructure.GPIO_Pin GPIO_Pin_10;GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz;GPIO_Init(GPIOB, GPIO_InitStructure); // USART3 RX - PB11GPIO_InitStructure.GPIO_Pin GPIO_Pin_11;GPIO_InitStructure.GPIO_Mode GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOB, GPIO_InitStructure); 3. 串口初始化
注意哈USART_Init()这个函数是用来配置串口的相关参数的。 USART_BaudRate 串口通信使用的波特率 一般是9600或者是115200这里我们给9600USART_HardwareFlowControl 是否选择硬件流触发一般这个我们也不选所以选择无硬件流触发。USART_Mode 这个参数要注意了哈串口的模式发送模式还是接收模式还是两者都有这里使用收发模式USART_Parity 校验位可以选择奇偶校验和不校验。没有需求就直接无校验USART_StopBits 停止位 有1、0.5、2位我们这里选1位停止位USART_WordLength 数据位 有8位和9位可以选择 //串口初始化USART_InitTypeDef USART_InitStruct;USART_StructInit(USART_InitStruct); //初始默认值USART_InitStruct.USART_BaudRate9600;USART_InitStruct.USART_HardwareFlowControlUSART_HardwareFlowControl_None; //不使用硬件流触发USART_InitStruct.USART_ModeUSART_Mode_Rx|USART_Mode_Tx; //收发模式TX 发送模式 RX 接收模式 USART_InitStruct.USART_ParityUSART_Parity_No; //不选择校验USART_InitStruct.USART_StopBitsUSART_StopBits_1; //停止位1位USART_InitStruct.USART_WordLengthUSART_WordLength_8b; //数据位8位USART_Init(USART3,USART_InitStruct);4. 串口使能
//串口使能USART_Cmd(USART3,ENABLE);5. 串口发送数据
注意哈我们要判断TXE标志位的状态。0数据还没有被转移到移位寄存器1,数据已经被转移到移位寄存器。当TXE标志位为1时就说明可以发送下一个数据了。详细过程可看上面串口发送的解释。
//串口3发送一个字节
void Usart3_SendByte(u8 val)
{USART_SendData(USART3, val);//0 表示数据还未转移到移位寄存器 循环等待 1 数据已经被转移到了移位寄存器可以发送数据while (USART_GetFlagStatus(USART3, USART_FLAG_TC) RESET); //等待发送完成,不需要手动清零 再次写入TDR时会自动清零
}经过上述五步的配置单片机就可以通过串口发送数据了。 串口接收的两种实现方式 串口接收通常可以通过轮询Polling和中断Interrupt两种方式来实现。 轮询方式就是通过不断的查询RXNE标志位通过判断RXNE位的状态来确定数据是否接收。中断方式就是通过配置接收输出控制通道配置NVIC在中断服务子函数里进行数据的接收。 1轮询方式
在轮询方式中程序通过不断地查询串口接收缓冲区是否有数据到达。当检测到数据到达时程序立即读取接收缓冲区中的数据。
优点 实现简单易于理解。可以直接在接收到数据后立即进行处理。适合于数据传输量不大且CPU负荷较轻的场合。 缺点 需要不断地轮询串口接收缓冲区占用 CPU 资源。无法及时响应其他任务或事件。效率较低可能会错过一些数据。 实现步骤 配置串口设置串口的波特率、数据位数、停止位等参数。 轮询状态寄存器不断检查USART的状态寄存器判断接收缓冲区是否有新数据。 读取数据一旦发现有新数据立即从数据寄存器读取数据。
示例代码
// 定义一个函数用于轮询方式接收 USART 数据
void USART_Receive_Polling(void) {// 进入一个无限循环while(1) {// 检查接收缓冲区是否有数据if(USART_GetFlagStatus(USART3, USART_FLAG_RXNE) SET) {// 如果接收缓冲区有数据// 从接收缓冲区读取数据uint8_t data USART_ReceiveData(USART3);// 处理接收到的数据// 这里可以添加代码来解析和处理接收到的数据}// 如果接收缓冲区无数据则继续轮询// 可以添加延时以降低 CPU 占用率// delay_ms(10);}
}2中断方式
在中断方式中程序允许 MCU 在接收到数据时触发串口接收中断并在中断服务函数中处理接收到的数据。当接收缓冲区有新数据时硬件自动产生一个中断CPU响应这个中断并执行中断服务程序来处理接收到的数据。
优点 采用了中断机制不需要不断地轮询串口接收缓冲区减少了 CPU 的占用率。效率高可以及时响应其他任务或事件提高了系统的实时性。适合于数据量大或实时性要求高的应用 缺点 实现相对复杂需要编写中断服务函数。在中断服务函数中对数据的处理需要考虑中断嵌套、优先级等问题需要谨慎设计。 实现步骤 配置串口同轮询方式。 使能中断在串口初始化中使能USART的接收中断。 编写中断服务程序实现USART的中断服务函数该函数会在接收到新数据时被调用。 数据处理在中断服务程序中读取接收到的数据并进行相应的处理。
示例代码
// USART3中断处理函数
void USART3_IRQHandler(void) {// 检查 USART3 接收中断标志位是否被设置if(USART_GetITStatus(USART3, USART_IT_RXNE) ! RESET) {// 如果接收缓冲区非空// 从接收缓冲区读取数据uint8_t data USART_ReceiveData(USART3);// 处理接收到的数据// 在这里可以添加代码来处理接收到的数据}
}// 使 USART3 接收中断
void USART_Receive_Interrupt(void) {// 使能串口接收中断USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);// 配置 USART3 中断优先级NVIC_InitTypeDef NVIC_InitStructure;// 设置中断通道为 USART3NVIC_InitStructure.NVIC_IRQChannel USART3_IRQn;// 设置中断抢占优先级为0NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 0;// 设置中断响应优先级为0NVIC_InitStructure.NVIC_IRQChannelSubPriority 0;// 使能中断通道NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE;// 初始化 NVICNVIC_Init(NVIC_InitStructure);// 进入一个无限循环等待中断服务函数处理接收到的数据while(1) {// 在中断服务函数中处理接收到的数据}
} 查询RXNE标志位
这里我们还是来看一看RXNE标志位的描述 上图描述为0时数据没有收到为1时收到了数据数据可以从RDR里读出
所以在主程序里不断读取RXNE标志位如果为1表示数据可以读出
uint8_t RX_Data; // 定义一个全局变量 RX_Data用于存储接收到的数据int main() // 主函数入口
{ Serial_Init(); // 初始化串口Serial_SendByte(0x16); // 向串口发送一个字节数据 0x16while(1) // 进入一个无限循环{if(USART_GetFlagStatus(USART2, USART_FLAG_RXNE) SET) // 检查 USART2 接收缓冲区是否有数据0RESET 循环等待 1SET 可以接收数据{RX_Data USART_ReceiveData(USART2); // 如果接收缓冲区有数据则从中读取数据并存储到 RX_Data 中Serial_SendByte(RX_Data); // 将接收到的数据发送回串口}}
}if(USART_GetFlagStatus(USART2, USART_FLAG_RXNE) SET) // 检查 USART2 接收缓冲区是否有数据0RESET 循环等待 1SET 可以接收数据 下图为程序现象pc向单片机发送数据0x15单片机接收数据0x15并且把接收到的数据作为数据发送到pc在pc上显示0x15。 使用中断 通过配置串口的接收作为中断源开启中断输出控制配置NVIC。开启中断通道。 // 开启 USART2 接收中断
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);// 配置 NVICNested Vectored Interrupt Controller嵌套向量中断控制器// 设置 NVIC 分组优先级选择分组 2
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 定义一个 NVIC_InitTypeDef 结构体变量用于配置中断控制器
NVIC_InitTypeDef NVIC_InitStruct;// 设置中断通道为 USART2即选择 USART2 的中断通道
NVIC_InitStruct.NVIC_IRQChannel USART2_IRQn;// 使能中断通道
NVIC_InitStruct.NVIC_IRQChannelCmd ENABLE;// 设置抢占优先级为 1
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority 1;// 设置子优先级为 1
NVIC_InitStruct.NVIC_IRQChannelSubPriority 1;// 将配置好的 NVIC_InitStruct 结构体变量传入 NVIC_Init 函数中对 NVIC 进行配置
NVIC_Init(NVIC_InitStruct);中断服务子函数 中断服务子函数写好后就可以在中断里读取接收到的数据了。 当接收到数据后触发接收中断主程序暂停执行。接收完数据后主程序回复执行。当接收到数据时就触发中断。 void USART2_IRQHandler(void)
{// 检查 USART2 接收缓冲区是否有数据if(USART_GetITStatus(USART2, USART_IT_RXNE) SET) // RXNE 标志位为1 表示可以接收数据{// 从接收缓冲区读取数据并存储到 RX_Data 中RX_Data USART_ReceiveData(USART2);// 设置标志位 Flag 为 1表示已接收到数据Flag 1;// 清除 USART2 接收中断标志位 RXNEUSART_ClearITPendingBit(USART2, USART_IT_RXNE); // 清除 RXNE 标志位}
}主程序测试 uint8_t RX_Data; // 定义一个全局变量 RX_Data用于存储接收到的数据
uint8_t Flag; // 定义一个全局变量 Flag用于表示是否接收到数据的标志位int main() // 主函数入口
{Serial_Init(); // 初始化串口Serial_SendByte(0x16); // 向串口发送一个字节数据 0x16while(1) // 进入一个无限循环{if(Flag 1) // 如果接收到数据的标志位为 1{Serial_SendByte(RX_Data); // 向串口发送接收到的数据这里可以改为自己需要的逻辑}}
}void USART2_IRQHandler(void) // USART2 中断服务函数
{if(USART_GetITStatus(USART2, USART_IT_RXNE) SET) // 如果 USART2 接收到数据{RX_Data USART_ReceiveData(USART2); // 从接收缓冲区读取数据并存储到 RX_Data 中Flag 1; // 设置接收到数据的标志位 Flag 为 1USART_ClearITPendingBit(USART2, USART_IT_RXNE); // 清除 USART2 的接收中断标志位 RXNE准备接收下一次数据}
}下图为程序现象可以看到串口确实收到了数据只是我把接收到的数据0xFE放在了while循环里这说明数据接收是成功的使用中断是可行的。 实战演练
要求使用stm32f103C8T6使用标准库硬件方面使用到了一个LED灯要求在PC端串口助手发送led on单片机的usart3接收到PC端发送的led on时打开LED灯同时向PC端发送“已打开”
为了实现提出的要求你需要按照以下步骤进行编程和硬件配置 硬件连接 LED 灯连接到单片机的一个 GPIO 端口比如 PA0。USART3 需要连接到 PC 通过串口或者通过串口转USB模块。 软件实现使用STM32标准库 以下提供一个粗略的实现示例
首先确保你已经在项目中正确配置了 STM32F103 的标准库以及正确设置系统时钟。
1. 初始化LED灯相应的GPIO口
void LED_Init(void) {GPIO_InitTypeDef GPIO_InitStructure; // 定义一个 GPIO_InitTypeDef 结构体变量用于配置 GPIORCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 开启 GPIOA 时钟GPIO_InitStructure.GPIO_Pin GPIO_Pin_0; // 设置要初始化的引脚为 PA0GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP; // 设置引脚工作模式为推挽输出GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; // 设置引脚的输出速度为 50MHzGPIO_Init(GPIOA, GPIO_InitStructure); // 初始化 GPIOA 的 PA0 引脚GPIO_SetBits(GPIOA, GPIO_Pin_0); // 将 PA0 引脚输出高电平默认关闭 LED
}2. 初始化USART3
void USART3_Init(void) {GPIO_InitTypeDef GPIO_InitStructure; // 定义一个 GPIO_InitTypeDef 结构体变量用于配置 GPIOUSART_InitTypeDef USART_InitStructure; // 定义一个 USART_InitTypeDef 结构体变量用于配置 USARTRCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // 打开 GPIOB 的时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); // 打开 USART3 的时钟// 配置 USART3 的 TX 引脚为复用推挽输出模式GPIO_InitStructure.GPIO_Pin GPIO_Pin_10; // 设置要初始化的引脚为 PB10GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP; // 设置引脚工作模式为复用推挽输出GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; // 设置引脚的输出速度为 50MHzGPIO_Init(GPIOB, GPIO_InitStructure); // 初始化 GPIOB 的 PB10 引脚// 配置 USART3 的 RX 引脚为浮空输入模式GPIO_InitStructure.GPIO_Pin GPIO_Pin_11; // 设置要初始化的引脚为 PB11GPIO_InitStructure.GPIO_Mode GPIO_Mode_IN_FLOATING; // 设置引脚工作模式为浮空输入GPIO_Init(GPIOB, GPIO_InitStructure); // 初始化 GPIOB 的 PB11 引脚// 配置 USART3 的通信参数USART_InitStructure.USART_BaudRate 9600; // 设置波特率为 9600USART_InitStructure.USART_WordLength USART_WordLength_8b; // 设置数据位长度为 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(USART3, USART_InitStructure); // 初始化 USART3USART_Cmd(USART3, ENABLE); // 使能 USART3
}3. 实现发送功能
void USART3_SendChar(char ch) {// 发送字符数据 ch 到 USART3USART_SendData(USART3, (uint8_t) ch);// 等待发送完成while (USART_GetFlagStatus(USART3, USART_FLAG_TC) RESET);
}4. 实现接收字符串功能
此部分可以通过中断或者轮询的方式实现。
1通过轮询的方式检查是否接收到了特定的字符串
void checkReceive(void) {uint8_t data; // 定义一个无符号 8 位整数型变量 data用于存储接收到的数据char buffer[8]; // 定义一个长度为 8 的字符数组 buffer用于存储接收到的数据int i 0; // 定义一个整型变量 i用于索引 buffer 数组// 进入一个循环循环条件是 i 小于 7while (i 7) {// 检查 USART3 接收缓冲区是否非空即是否有数据可读if (USART_GetFlagStatus(USART3, USART_FLAG_RXNE) ! RESET) {// 如果接收缓冲区非空则读取接收到的数据并存储到 data 变量中data (uint8_t)USART_ReceiveData(USART3);// 将读取到的数据存储到 buffer 数组中并将索引 i 自增buffer[i] data;}}// 在 buffer 数组末尾添加字符串结束标志 \0buffer[i] \0;// 比较 buffer 数组中的内容是否为 led onif (strcmp(buffer, led on) 0) {// 如果接收到的数据是 led on则执行以下操作// 打开 LED 灯即将 GPIOA 的 PA0 引脚输出低电平GPIO_ResetBits(GPIOA, GPIO_Pin_0);// 定义一个指向字符串常量 已打开 的指针 msgchar *msg 已打开;// 进入一个循环循环条件是指针 msg 指向的字符不为空字符 \0while (*msg) {// 发送指针 msg 指向的字符到 USART3然后指针 msg 自增USART3_SendChar(*msg);}}
}注意这里并没有添加中断服务程序也没有实现字符缓存区的溢出处理此外发送和接收字符的精确处理逻辑可能需要根据实际需求调整。实际项目中还可能需要考虑debounce消抖和更加复杂的串口命令解析。
务必确保单片机的时钟配置正确并且USART3的引脚与你连接的外设相匹配。在进行硬件连线时也要确保正确连接。 2通过中断的方式实现USART3接收特定的字符串
要通过中断方式实现USART3接收字符串我们需要做几件事情 配置NVIC以使能USART3中断。在USART3初始化函数中开启接收中断。编写USART3的中断服务函数来处理接收到的字节。 这种实现方式相比轮询可以有效减少CPU的负担特别是在数据不频繁接收时。
1. 配置NVIC以使能USART3中断
在USART3_Init函数中初始化USART3后你应该使能中断
NVIC_InitTypeDef NVIC_InitStructure; // 定义一个 NVIC_InitTypeDef 结构体变量用于配置 NVIC 中断控制器// 设置 NVIC 优先级分组为 2
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断源为 USART3
NVIC_InitStructure.NVIC_IRQChannel USART3_IRQn;
// 设置抢占优先级为 1
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 1;
// 设置子优先级为 1
NVIC_InitStructure.NVIC_IRQChannelSubPriority 1;
// 使能中断通道
NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE;
// 初始化 NVIC
NVIC_Init(NVIC_InitStructure);// 使能 USART3 接收中断
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);2. 在USART3初始化函数中开启接收中断
已经在上面的步骤中通过调用USART_ITConfig来实现了。
3. 编写USART3的中断服务函数来处理接收到的字节
你要定义一个缓冲区来存储接收到的字符并在接收到整个字符串后进行处理
#define BUFFER_SIZE 100 // 定义缓冲区大小为 100
char buffer[BUFFER_SIZE]; // 声明一个大小为 BUFFER_SIZE 的字符数组作为接收缓冲区
volatile unsigned int buffer_index 0; // 声明一个无符号整数变量用于表示当前缓冲区的索引位置使用 volatile 关键字声明表示在中断中可能被改变需要及时更新void USART3_IRQHandler(void) { // 定义 USART3 的中断服务函数// 检查是否接收到数据if (USART_GetITStatus(USART3, USART_IT_RXNE) ! RESET) { // 如果接收到 USART3 的接收中断标志位char data (char)USART_ReceiveData(USART3); // 读取接收到的数据并转换为字符类型// 简单的字符串终止判断例如以换行结束if (data ! \n buffer_index BUFFER_SIZE - 1) { // 如果接收到的字符不是换行且缓冲区索引未超过最大长度减一buffer[buffer_index] data; // 将接收到的字符存入缓冲区中并更新索引} else { buffer[buffer_index] \0; // 确保字符串结束即在缓冲区最后添加 \0 表示字符串结束// 检查接收到的命令if (strcmp(buffer, led on) 0) { // 如果接收到的命令是 led onGPIO_ResetBits(GPIOA, GPIO_Pin_0); // 点亮 LEDchar *msg 已打开\n; // 定义一个指向字符串的指针表示要发送的消息while (*msg) { // 循环发送消息中的每一个字符直到遇到 \0 表示字符串结束USART3_SendChar(*msg); // 发送字符并将指针移向下一个字符}}// 重置索引准备下一次接收buffer_index 0; // 将缓冲区索引重置为 0准备接收下一条命令}USART_ClearITPendingBit(USART3, USART_IT_RXNE); // 清除接收中断标志位准备下一次接收中断}
}这个示例代码会在接收到一串字符后处理这串字符。如果接收到的字符串是led on加上换行符\n它将点亮LED并通过USART3发送回已打开\n。
注意实际上你可能需要添加更多的错误处理和缓冲区管理来处理可能出现的错误和异常情况比如缓冲区溢出。
此外为了让上述代码正常工作请确保你的USART3接收中断已经正确配置并且你的系统时钟设置支持你的串口通信需求。你可能还需要根据你的具体硬件连接调整GPIO端口初始化和LED操作的代码。 5. 主函数
在主函数里初始化LED和USART3然后不断检查串口接收
int main(void) {SystemInit(); // 调用 SystemInit() 函数初始化系统时钟这通常是启动代码中的一部分用于初始化系统的时钟和基本的硬件设置。LED_Init(); // 调用 LED_Init() 函数初始化 LED准备控制 LED 灯的状态。USART3_Init(); // 调用 USART3_Init() 函数初始化 USART3配置 USART3 的通信参数和引脚连接等。while (1) {checkReceive(); // 循环调用 checkReceive() 函数用于检查是否接收到特定命令并根据接收到的命令执行相应的操作。}
}总结
本文大致总结了串口的发送和接收。
串口的配置使用查询或者中断来接收数据。
串口的使用会很常用到所以在这里对串口做一个总结也算是对之前知识的一个回顾和总结加强印象。 参考链接
https://gitcode.csdn.net/65e6e6b81a836825ed787581.html?dp_tokeneyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MjgwNDA1NSwiZXhwIjoxNzEwNjEwNTI5LCJpYXQiOjE3MTAwMDU3MjksInVzZXJuYW1lIjoid2VpeGluXzUxMDI4NTg0In0.1Eac2jHw_Iz7Nc6l36BNEre9cCLz_gXA_Lz_OQnvtLc