一、介绍
主控与外设之间的通讯,数据收发交换
串口:
二、硬件
电平标准:
串口参数及时序:
三、USART(通用同步|异步收发器)
四、流程
if在某时刻给TDR写入了0x55这个数据,在寄存器里就是二进制存储,01010101,然后硬件会进行检测是否有数据正在移位,如果没有那么01010101就会全部移动到发送移位寄存器,准备发送同时会产生一个标志位TXE(发送寄存器空,如果检查这个标志位为1,那么就可以在TDR进行下一个写入了,)然后,发送控制器就会控制移位寄存器向右移位,然后一位一位地,把数据输出到TX引脚进行发送。
接收同样类似,会产生一个标志位USARTRXNE (RX Not Empty),接收数据寄存器非空,检测到RXNE置1之后,就可以把数据读走了
停止位
波特率发生器:
五、实战
1、硬件
2、软件打通 发送
1第一步,开启时钟,把需要用的USART和GPIO的时钟打开
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); // 使能USART1时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 使能GPIOA时钟
2第一步,GPIO初始化,把TX配置成复用输出,RX配置成输入
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; // GPIOA的引脚9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // GPIO速度50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure);
3第三步,配置USART,直接使用一个结构体
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 9600; // 波特率9600
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 无硬件流控
USART_InitStructure.USART_Mode = USART_Mode_Tx; // 仅发送模式
USART_InitStructure.USART_Parity = USART_Parity_No; // 无奇偶校验
USART_InitStructure.USART_StopBits = USART_StopBits_1; // 1个停止位
USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 8位数据位
USART_Init(USART1, &USART_InitStructure); // 初始化USART1
4发送功能直接开启UART就结束了,如果需要接收那么还需要添加中断
USART_Cmd(USART1, ENABLE);
5发送字节函数
void Serial_SendByte(uint8_t Byte)
{
USART_SendData(USART1, Byte); // 发送一个字节
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); // 等待发送完成
}
6发送数组函数(传递数组需要使用指针)
void Serial_SendArray(uint8_t *Array, uint16_t Length)
{
uint16_t i;
for (i = 0; i < Length; i++)
{
Serial_SendByte(Array[i]); // 逐个发送数组中的字节
}
}
7发送字符串等
.h
#ifndef __SERIAL_H
#define __SERIAL_H
#include <stdio.h>
void Serial_Init(void);
void Serial_SendByte(uint8_t Byte);
void Serial_SendArray(uint8_t *Array, uint16_t Length);
void Serial_SendString(char *String);
void Serial_SendNumber(uint32_t Number, uint8_t Length);
void Serial_Printf(char *format, ...);
#endif
.c
#include "stm32f10x.h" // 包含STM32F10x系列微控制器的头文件
#include <stdio.h>
#include <stdarg.h>
void Serial_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); // 使能USART1时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 使能GPIOA时钟
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; // GPIOA的引脚9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // GPIO速度50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化GPIOA
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 9600; // 波特率9600
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 无硬件流控
USART_InitStructure.USART_Mode = USART_Mode_Tx; // 仅发送模式
USART_InitStructure.USART_Parity = USART_Parity_No; // 无奇偶校验
USART_InitStructure.USART_StopBits = USART_StopBits_1; // 1个停止位
USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 8位数据位
USART_Init(USART1, &USART_InitStructure); // 初始化USART1
USART_Cmd(USART1, ENABLE); // 使能USART1
}
void Serial_SendByte(uint8_t Byte)
{
USART_SendData(USART1, Byte); // 发送一个字节
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); // 等待发送完成
}
void Serial_SendArray(uint8_t *Array, uint16_t Length)
{
uint16_t i;
for (i = 0; i < Length; i++)
{
Serial_SendByte(Array[i]); // 逐个发送数组中的字节
}
}
void Serial_SendString(char *String)
{
uint8_t i;
for (i = 0; String[i] != '\0'; i++)
{
Serial_SendByte(String[i]); // 逐个发送字符串中的字符
}
}
uint32_t Serial_Pow(uint32_t X, uint32_t Y)
{
uint32_t Result = 1;
while (Y--)
{
Result *= X; // 计算X的Y次方
}
return Result;
}
void Serial_SendNumber(uint32_t Number, uint8_t Length)
{
uint8_t i;
for (i = 0; i < Length; i++)
{
Serial_SendByte(Number / Serial_Pow(10, Length - i - 1) % 10 + '0'); // 逐位发送数字的每一位
}
}
int fputc(int ch, FILE *f)
{
Serial_SendByte(ch); // 将字符发送到串口
return ch;
}
void Serial_Printf(char *format, ...)
{
char String[100];
va_list arg;
va_start(arg, format);
vsprintf(String, format, arg); // 使用可变参数格式化字符串
va_end(arg);
Serial_SendString(String); // 发送格式化后的字符串
}
main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "Serial.h"
int main(void)
{
OLED_Init();
Serial_Init();
Serial_SendByte(0x41);
uint8_t MyArray[] = {0x42, 0x43, 0x44, 0x45};
Serial_SendArray(MyArray, 4);
Serial_SendString("\r\nNum1=");
Serial_SendNumber(111, 3);
printf("\r\nNum2=%d", 222);
char String[100];
sprintf(String, "\r\nNum3=%d", 333);
Serial_SendString(String);
Serial_Printf("\r\nNum4=%d", 444);
Serial_Printf("\r\n");
while (1)
{
}
}
3、发送加接收
库文件要改的部分:新加一个发送口的GPIO,后把UART的模式上添加RX模式
1查询模式:
查询的流程是,在主函数里不断判断RXNE标志位,如果置1了,就说明收到数据了,再调用ReceiveData,读取DR寄存器,这样就行了
在主函数里一直查询:
if (Serial_GetRxFlag() == 1)
{
RxData = Serial_GetRxData();
Serial_SendByte(RxData);
OLED_ShowHexNum(1, 8, RxData, 2);
}
2中断模式:
实质:开启RXNE标志位到NVIC的输出,然后配置NVIC就可,然后在中断函数里边写内容就行,
4、数据包发送
作用:把一个个单独的数据给打包起来,方便进行多字节数据通信
当数据里出现包头包尾时,可以限制数据的范围,避免误判,或者固定包长限制数据长度
为自己规定
HEX数据包
优点:传输最直接,解析数据非常简单
缺点:就是灵活性不足、载荷容易和包头包尾重复
文本数据包
优点是,数据直观易理解,非常灵活 ,比较适合一些输入指令进行人机交互的场合
缺点是:解析效率低
收发流程
HEX
文本
5、数据包发送实验
hex
文本:
- HEX数据包:
.c
#include "stm32f10x.h" // 设备头文件
#include <stdio.h>
#include <stdarg.h>
uint8_t Serial_TxPacket[4]; // 串口发送数据包数组,长度为4
uint8_t Serial_RxPacket[4]; // 串口接收数据包数组,长度为4
uint8_t Serial_RxFlag; // 串口接收标志位
void Serial_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); // 使能USART1时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 使能GPIOA时钟
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; // TX引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 输入上拉
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; // RX引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 9600; // 波特率设置为9600
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 无硬件流控制
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; // 发送和接收模式
USART_InitStructure.USART_Parity = USART_Parity_No; // 无奇偶校验
USART_InitStructure.USART_StopBits = USART_StopBits_1; // 1个停止位
USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 数据位长度为8位
USART_Init(USART1, &USART_InitStructure);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // 使能USART1接收中断
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; // USART1中断
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // 使能中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 抢占优先级1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // 子优先级1
NVIC_Init(&NVIC_InitStructure);
USART_Cmd(USART1, ENABLE); // 使能USART1
}
void Serial_SendByte(uint8_t Byte)
{
USART_SendData(USART1, Byte);
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); // 等待发送完成
}
void Serial_SendArray(uint8_t *Array, uint16_t Length)
{
uint16_t i;
for (i = 0; i < Length; i++)
{
Serial_SendByte(Array[i]); // 逐个发送数组中的字节
}
}
void Serial_SendString(char *String)
{
uint8_t i;
for (i = 0; String[i] != '\0'; i++)
{
Serial_SendByte(String[i]); // 逐个发送字符串中的字符
}
}
uint32_t Serial_Pow(uint32_t X, uint32_t Y)
{
uint32_t Result = 1;
while (Y--)
{
Result *= X; // 计算 X 的 Y 次方
}
return Result;
}
void Serial_SendNumber(uint32_t Number, uint8_t Length)
{
uint8_t i;
for (i = 0; i < Length; i++)
{
Serial_SendByte(Number / Serial_Pow(10, Length - i - 1) % 10 + '0'); // 逐位发送数字的每一位
}
}
int fputc(int ch, FILE *f)
{
Serial_SendByte(ch); // 发送字符到串口
return ch;
}
void Serial_Printf(char *format, ...)
{
char String[100];
va_list arg;
va_start(arg, format);
vsprintf(String, format, arg); // 格式化字符串
va_end(arg);
Serial_SendString(String); // 发送格式化后的字符串
}
void Serial_SendPacket(void)
{
Serial_SendByte(0xFF); // 发送起始字节
Serial_SendArray(Serial_TxPacket, 4); // 发送数据包数组
Serial_SendByte(0xFE); // 发送结束字节
}
uint8_t Serial_GetRxFlag(void)
{
if (Serial_RxFlag == 1)
{
Serial_RxFlag = 0;
return 1; // 返回接收标志位并清零
}
return 0;
}
void USART1_IRQHandler(void)
{
static uint8_t RxState = 0;
static uint8_t pRxPacket = 0;
if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
{
uint8_t RxData = USART_ReceiveData(USART1); // 读取接收到的数据
if (RxState == 0)
{
if (RxData == 0xFF)
{
RxState = 1; // 进入数据包接收状态
pRxPacket = 0; // 重置接收包计数器
}
}
else if (RxState == 1)
{
Serial_RxPacket[pRxPacket] = RxData; // 存储接收到的数据到数据包数组
pRxPacket++;
if (pRxPacket >= 4)
{
RxState = 2; // 数据包接收完成
}
}
else if (RxState == 2)
{
if (RxData == 0xFE)
{
RxState = 0; // 结束字节接收,重置状态为初始状态
Serial_RxFlag = 1; // 设置接收标志位
}
}
USART_ClearITPendingBit(USART1, USART_IT_RXNE); // 清除接收中断标志位
}
}
.h
#ifndef __SERIAL_H
#define __SERIAL_H
#include <stdio.h>
extern uint8_t Serial_TxPacket[]; // 声明发送数据包数组
extern uint8_t Serial_RxPacket[]; // 声明接收数据包数组
void Serial_Init(void); // 初始化串口
void Serial_SendByte(uint8_t Byte); // 发送单个字节
void Serial_SendArray(uint8_t *Array, uint16_t Length); // 发送字节数组
void Serial_SendString(char *String); // 发送字符串
void Serial_SendNumber(uint32_t Number, uint8_t Length); // 发送数字
void Serial_Printf(char *format, ...); // 格式化发送字符串
void Serial_SendPacket(void); // 发送数据包
uint8_t Serial_GetRxFlag(void); // 获取接收标志位
#endif
main.c
#include "stm32f10x.h" // 引入STM32F10x芯片的设备头文件
#include "Delay.h" // 引入延时函数的头文件
#include "OLED.h" // 引入OLED显示屏的头文件
#include "Serial.h" // 引入串口通信的头文件
#include "Key.h" // 引入按键的头文件
uint8_t KeyNum; // 定义一个按键编号变量
int main(void)
{
OLED_Init(); // 初始化OLED显示屏
Key_Init(); // 初始化按键
Serial_Init(); // 初始化串口通信
OLED_ShowString(1, 1, "TxPacket"); // 在OLED上显示字符串 "TxPacket"
OLED_ShowString(3, 1, "RxPacket"); // 在OLED上显示字符串 "RxPacket"
Serial_TxPacket[0] = 0x01; // 初始化发送数据包数组
Serial_TxPacket[1] = 0x02;
Serial_TxPacket[2] = 0x03;
Serial_TxPacket[3] = 0x04;
while (1)
{
KeyNum = Key_GetNum(); // 获取按键编号
if (KeyNum == 1)
{
Serial_TxPacket[0]++; // 按键1按下,递增数据包内容
Serial_TxPacket[1]++;
Serial_TxPacket[2]++;
Serial_TxPacket[3]++;
Serial_SendPacket(); // 发送数据包
// 在OLED上显示发送数据包内容的十六进制值
OLED_ShowHexNum(2, 1, Serial_TxPacket[0], 2);
OLED_ShowHexNum(2, 4, Serial_TxPacket[1], 2);
OLED_ShowHexNum(2, 7, Serial_TxPacket[2], 2);
OLED_ShowHexNum(2, 10, Serial_TxPacket[3], 2);
}
if (Serial_GetRxFlag() == 1)
{
// 在OLED上显示接收数据包内容的十六进制值
OLED_ShowHexNum(4, 1, Serial_RxPacket[0], 2);
OLED_ShowHexNum(4, 4, Serial_RxPacket[1], 2);
OLED_ShowHexNum(4, 7, Serial_RxPacket[2], 2);
OLED_ShowHexNum(4, 10, Serial_RxPacket[3], 2);
}
}
}
这个主程序初始化了OLED显示屏、按键、串口通信,并在一个无限循环中检测按键状态和串口接收状态,根据按键状态递增发送数据包内容,并在OLED上显示发送和接收的数据包内容。
文本数据包:
.c
#include "stm32f10x.h" // 引入STM32F10x芯片的设备头文件
#include <stdio.h> // 引入标准输入输出头文件
#include <stdarg.h> // 引入可变参数头文件
char Serial_RxPacket[100]; // 存储接收到的消息的数组,最大长度为100,注意足够大以容纳可能的消息
uint8_t Serial_RxFlag; // 标志位,用于指示是否接收到完整的消息
void Serial_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); // 使能USART1时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 使能GPIOA时钟
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; // USART1_TX引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // GPIO速度为50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; // USART1_RX引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // GPIO速度为50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 9600; // 波特率9600
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 无硬件流控制
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; // 发送和接收模式
USART_InitStructure.USART_Parity = USART_Parity_No; // 无奇偶校验
USART_InitStructure.USART_StopBits = USART_StopBits_1; // 1个停止位
USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 8位数据位
USART_Init(USART1, &USART_InitStructure);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // 使能USART1接收中断
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 配置中断分组为优先级2
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; // USART1中断
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // 使能中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 抢占优先级1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // 子优先级1
NVIC_Init(&NVIC_InitStructure);
USART_Cmd(USART1, ENABLE); // 使能USART1
}
void Serial_SendByte(uint8_t Byte)
{
USART_SendData(USART1, Byte);
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); // 等待发送完成
}
void Serial_SendArray(uint8_t *Array, uint16_t Length)
{
uint16_t i;
for (i = 0; i < Length; i ++)
{
Serial_SendByte(Array[i]);
}
}
void Serial_SendString(char *String)
{
uint8_t i;
for (i = 0; String[i] != '\0'; i ++)
{
Serial_SendByte(String[i]);
}
}
uint32_t Serial_Pow(uint32_t X, uint32_t Y)
{
uint32_t Result = 1;
while (Y --)
{
Result *= X;
}
return Result;
}
void Serial_SendNumber(uint32_t Number, uint8_t Length)
{
uint8_t i;
for (i = 0; i < Length; i ++)
{
Serial_SendByte(Number / Serial_Pow(10, Length - i - 1) % 10 + '0');
}
}
int fputc(int ch, FILE *f)
{
Serial_SendByte(ch);
return ch;
}
void Serial_Printf(char *format, ...)
{
char String[100];
va_list arg;
va_start(arg, format);
vsprintf(String, format, arg);
va_end(arg);
Serial_SendString(String);
}
void USART1_IRQHandler(void)
{
static uint8_t RxState = 0;
static uint8_t pRxPacket = 0;
if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
{
uint8_t RxData = USART_ReceiveData(USART1);
if (RxState == 0)
{
if (RxData == '@' && Serial_RxFlag == 0) // 判断是否接收到消息的起始符 '@',并且接收标志位为0
{
RxState = 1;
pRxPacket = 0;
}
}
else if (RxState == 1)
{
if (RxData == '\r') // 判断是否接收到消息的结束符 '\r'
{
RxState = 2;
}
else
{
Serial_RxPacket[pRxPacket] = RxData;
pRxPacket ++;
}
}
else if (RxState == 2)
{
if (RxData == '\n') // 判断是否接收到消息的结束符 '\n'
{
RxState = 0;
Serial_RxPacket[pRxPacket] = '\0'; // 添加字符串结束符
Serial_RxFlag = 1; // 设置接收标志位
}
}
USART_ClearITPendingBit(USART1, USART_IT_RXNE); // 清除接收中断标志位
}
}
.h
#ifndef __SERIAL_H
#define __SERIAL_H
#include <stdio.h>
extern char Serial_RxPacket[]; // 外部声明接收消息的数组
extern uint8_t Serial_RxFlag; // 外部声明接收标志位
void Serial_Init(void); // 串口初始化函数声明
void Serial_SendByte(uint8_t Byte); // 发送单个字节函数声明
void Serial_SendArray(uint8_t *Array, uint16_t Length); // 发送字节数组函数声明
void Serial_SendString(char *String); // 发送字符串函数声明
void Serial_SendNumber(uint32_t Number, uint8_t Length); // 发送数字函数声明
void Serial_Printf(char *format, ...); // 格式化输出并发送函数声明
#endif
main.c
#include "stm32f10x.h" // 引入STM32F10x芯片的设备头文件
#include "Delay.h"
#include "OLED.h"
#include "Serial.h"
#include "LED.h"
#include "string.h"
int main(void)
{
OLED_Init(); // OLED屏幕初始化
LED_Init(); // LED初始化
Serial_Init(); // 串口初始化
OLED_ShowString(1, 1, "TxPacket"); // OLED显示发送数据提示
OLED_ShowString(3, 1, "RxPacket"); // OLED显示接收数据提示
while (1)
{
if (Serial_RxFlag == 1) // 如果接收到完整的消息
{
OLED_ShowString(4, 1, " "); // 清空之前的显示
OLED_ShowString(4, 1, Serial_RxPacket); // 在OLED上显示接收到的消息
if (strcmp(Serial_RxPacket, "LED_ON") == 0) // 如果接收到的消息是"LED_ON"
{
LED1_ON(); // 打开LED1
Serial_SendString("LED_ON_OK\r\n"); // 发送成功响应
OLED_ShowString(2, 1, " "); // 清空之前的显示
OLED_ShowString(2, 1, "LED_ON_OK"); // 在OLED上显示LED打开成功
}
else if (strcmp(Serial_RxPacket, "LED_OFF") == 0) // 如果接收到的消息是"LED_OFF"
{
LED1_OFF(); // 关闭LED1
Serial_SendString("LED_OFF_OK\r\n"); // 发送成功响应
OLED_ShowString(2, 1, " "); // 清空之前的显示
OLED_ShowString(2, 1, "LED_OFF_OK"); // 在OLED上显示LED关闭成功
}
else
{
Serial_SendString("ERROR_COMMAND\r\n"); // 发送错误响应
OLED_ShowString(2, 1, " "); // 清空之前的显示
OLED_ShowString(2, 1, "ERROR_COMMAND"); // 在OLED上显示错误命令
}
Serial_RxFlag = 0; // 清除接收标志位,准备接收下一条消息
}
}
}