前言:
最近在做一个智能家居的项目,需要实现语音控制的功能,于是我选用了ASRPRO模块与STM32通信,这个模块最大的好处在于有配套的编程软件和语音库,不用自己训练且编程简单(少儿编程的程度)。ASRPRO的代码架构在这不多说,总之在收到语音后它会通过串口发送一串命令给STM32,STM32收到后通过串口中断的方式进行一系列操作。但没想到在这块看起来很简单的地方翻车了(太丢人了。。。),经过求助之后终于解决了,在这里浅浅记录一下自己的翻车过程及解决方案。
问题引入
代码这里偷了一下懒,直接问了GPT,可以直接看我这篇文章:GPT对话代码库——基于STM32F103 1,标志位切换模式 & 2,串口的接受和发送
基础的就不多说了,主要讲一下核心问题,先放一下代码
#define BUFFER_SIZE 100 // 定义缓冲区大小为100
char buffer[BUFFER_SIZE]; // 定义一个缓冲区数组用于存储接收到的数据
volatile unsigned int buffer_index = 0; // 声明一个用于记录缓冲区当前索引的变量,使用 volatile 关键字修饰以确保在中断中的可见性
void USART3_IRQHandler(void) {
// 检查是否接收到数据
if (USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) {
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 on"
GPIO_ResetBits(GPIOA, GPIO_Pin_0); // 点亮LED
char *msg = "已打开\n"; // 定义提示消息
while (*msg) { // 循环发送消息中的每个字符
USART3_SendChar(*msg++); // 通过串口发送字符
}
}
// 重置索引,准备下一次接收
buffer_index = 0; // 重置缓冲区索引,准备接收下一条指令
}
USART_ClearITPendingBit(USART3, USART_IT_RXNE); // 清除接收中断标志位
}
}
按照我原本的想法是先通过 USART3 接收中断判断是否接收到数据,然后读取接收到的数据并存储到缓冲区中。当接收到换行符或者缓冲区已满时,将缓冲区末尾添加字符串结束符'\0',然后检查接收到的命令,如果是"led on"则点亮LED,并通过串口发送提示消息"已打开\n",最后重置缓冲区索引,准备接收下一条指令。乍一看没啥毛病,但发现虽然buffer[]这个数组接收到了来自data的信息,最后经过仿真调试发现是在代码实现的时候给自己埋了雷。
strcmp这个函数用于比较两个字符串是否相等,函数原型:
int strcmp(const char *str1, const char *str2);
strcmp函数接受两个参数,分别是要比较的两个字符串 str1
和 str2
。它会按照字典顺序逐个比较两个字符