当前位置: 首页 > news >正文

ASRPRO系列语音模块(第十天)

在这里插入图片描述


👨‍💻个人主页:@开发者-削好皮的Pineapple!

👨‍💻 hello 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅!

👨‍💻 本文由 削好皮的Pineapple! 原创

👨‍💻 收录于专栏:C语言到基于STM32 的智能矿探小车


请添加图片描述

请添加图片描述

文章目录

    • 🎶一、语音模块编程环境搭建与配置
    • 🎶二、语音模块与矿探小车控制系统的通信集成
      • (一)GPIO引脚直连方案
      • (二)串口通信方案(推荐用于矿探小车多指令控制)
        • 结束语🥇


前言

  • 本文聚焦矿探小车语音控制功能的实现,详细记录ASRPRO语音模块与STM32单片机的集成过程,包括编程环境搭建与通信方式调试,为小车智能化控制提供关键技术参考。

🎶一、语音模块编程环境搭建与配置


  • 矿探小车采用ASRPRO系列语音模块实现语音交互,配套编程工具为天问BLOCK界面化编程软件,具体搭建步骤如下:
    1. 解压twenBlock.zip压缩包,双击安装包并按提示操作,安装路径需设置为纯英文目录,避免中文路径导致的兼容问题。
    2. 安装完成后需联网注册账号,勾选“记录密码”可简化后续登录流程。
  • 模块程序开发流程:完成语音识别模型配置后,依次点击“生成模型”与“编译下载”,即可将程序烧录至ASRPRO模块。

在这里插入图片描述


🎶二、语音模块与矿探小车控制系统的通信集成


(一)GPIO引脚直连方案

  • 适用于简单单指令控制,以“开灯”指令为例:
    • 硬件连接:ASRPRO的PA0引脚(指令触发时输出高电平)与STM32的PC7引脚相连。
    • STM32配置:将PC7引脚设置为浮空输入模式,用于检测ASRPRO输出的电平信号。
    • 控制逻辑代码:
      if(GPIO_READINPUTDATE(GPIOC,GPIO_PIN_7) == 1)
      {//执行矿探小车灯光开启操作car_light_on(); 
      }
      
  • 局限性:仅支持单一指令,扩展多指令需增加引脚数量,布线复杂度提升。
    在这里插入图片描述
    在这里插入图片描述

(二)串口通信方案(推荐用于矿探小车多指令控制)

  • 利用ASRPRO的串口0实现与STM32的双向通信,支持多指令扩展:
    • 硬件连接:
      ASRPRO串口0STM32串口(USART1/2/3)
      VCCVCC(3.3V/5V,需匹配模块电压)
      GNDGND
      PB5(TX)RX(接收引脚)
      PB6(RX)TX(发送引脚)
    • 控制逻辑代码示例(支持小车前进、开灯等多指令):
      if(recv == 'A')
      {//矿探小车前进控制car_move_forward();
      }
      else if(recv == 'B')
      {//矿探小车灯光开启car_light_on();
      }
      //可扩展后退('C')、转向('D'/'E')等指令
      
  • 优势:通过字符编码区分多指令,无需增加硬件引脚,适配矿探小车复杂运动控制需求。
#include "stm32f4xx.h"
#include "uart.h"
#include "car.h"
#include "led.h"
#include <stdio.h>// 全局变量定义
u8 recv; // USART2接收数据(命令指示)
u8 rdata; // USART3接收数据(MQ2传感器数据)
u8 asr_cmd; // 新增:ASRPRO接收的指令
u8 mq2_response[9]; // 存储MQ2模块响应数据帧
u16 smoke_concentration; // 存储烟雾浓度值(百分比)
volatile uint8_t mq2_response_index = 0; // 记录MQ2响应帧索引
static uint8_t is_sending = 0; // 发送状态标志,防止数据冲突
uint8_t request_smoke_data = 0; // 请求烟雾数据标志// 向MQ2模块发送请求数据帧(固定帧)
void send_mq2_request(void) {int i;u8 request_data[9] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79};for (i = 0; i < 9; i++) {while (USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET);USART_SendData(USART3, request_data[i]);}
}// 解析MQ2数据接收逻辑,包括帧格式和校验位验证
void parse_mq2_response(void) {u8 checksum = 0;u16 raw_value;int i;// 1. 验证帧头格式,MQ2响应帧头为FF 86if (mq2_response[0] != 0xFF || mq2_response[1] != 0x86) {smoke_concentration = 0; // 帧格式错误,返回0return;}// 2. 计算校验和,确保数据有效性for (i = 0; i < 8; i++) {checksum += mq2_response[i];}checksum = 0xFF - (checksum % 0xFF);if (checksum != mq2_response[8]) {smoke_concentration = 0; // 校验失败,返回0return;}// 3. 提取有效数据,浓度值在第2和3字节raw_value = (mq2_response[2] << 8) | mq2_response[3]; // 合并字节// 4. 根据公式进行实际浓度转换if (raw_value > 5000) {smoke_concentration = 100;} else {smoke_concentration = (raw_value * 100) / 5000;}
}// 修改字符串发送逻辑,确保数据完整发送
void send_smoke_concentration_to_bluetooth(void) {char buffer[20];int i;uint32_t timeout;if (is_sending) return; // 避免冲突,直接退出is_sending = 1;// 格式化字符串,确保格式正确snprintf(buffer, sizeof(buffer), "Smoke: %d%%\n", smoke_concentration);// 暂时关闭串口接收中断,防止冲突USART_ITConfig(USART2, USART_IT_RXNE, DISABLE);USART_ITConfig(USART3, USART_IT_RXNE, DISABLE);// 发送字符串,添加超时机制for (i = 0; buffer[i] != '\0'; i++) {timeout = 0;// 等待发送缓冲区为空,超时值设置为500000while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET) {if (timeout++ > 500000) { // 简单的超时处理is_sending = 0;// 恢复中断并退出USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);return;}}USART_SendData(USART2, buffer[i]);}// 发送完成,恢复中断USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);is_sending = 0;
}// 新增:ASRPRO通信串口初始化
void USART1_Init(void) {GPIO_InitTypeDef GPIO_InitStruct;USART_InitTypeDef USART_InitStruct;NVIC_InitTypeDef NVIC_InitStruct;// 使能GPIOA和USART1时钟RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);// 配置USART1 Tx (PA9)和Rx (PA10)引脚GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;GPIO_Init(GPIOA, &GPIO_InitStruct);GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;GPIO_Init(GPIOA, &GPIO_InitStruct);// 将PA9和PA10复用为USART1功能GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);// 配置USART1参数USART_InitStruct.USART_BaudRate = 9600; // 与ASRPRO通信波特率USART_InitStruct.USART_WordLength = USART_WordLength_8b;USART_InitStruct.USART_StopBits = USART_StopBits_1;USART_InitStruct.USART_Parity = USART_Parity_No;USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;USART_Init(USART1, &USART_InitStruct);// 使能USART1接收中断USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);// 配置NVIC中断NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; // 优先级高于USART2和USART3NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;NVIC_Init(&NVIC_InitStruct);// 使能USART1USART_Cmd(USART1, ENABLE);
}// 串口初始化函数(固定帧)
void uart_init(int bond) {// 原始代码不变,确保USART2和USART3配置正确GPIO_InitTypeDef  GPIO_InitStruct;USART_InitTypeDef USART_InitStruct;NVIC_InitTypeDef  NVIC_InitStruct;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2 | RCC_APB1Periph_USART3, ENABLE);GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;// USART2 (PA2=TX, PA3=RX)GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2;GPIO_Init(GPIOA, &GPIO_InitStruct);GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3;GPIO_Init(GPIOA, &GPIO_InitStruct);// USART3 (PB10=TX, PB11=RX)GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;GPIO_Init(GPIOB, &GPIO_InitStruct);GPIO_InitStruct.GPIO_Pin = GPIO_Pin_11;GPIO_Init(GPIOB, &GPIO_InitStruct);GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2);GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2);GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_USART3);GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_USART3);USART_InitStruct.USART_BaudRate = bond;USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;USART_InitStruct.USART_Parity = USART_Parity_No;USART_InitStruct.USART_StopBits = USART_StopBits_1;USART_InitStruct.USART_WordLength = USART_WordLength_8b;USART_Init(USART2, &USART_InitStruct);USART_Init(USART3, &USART_InitStruct);USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;NVIC_InitStruct.NVIC_IRQChannel = USART2_IRQn;NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;NVIC_Init(&NVIC_InitStruct);NVIC_InitStruct.NVIC_IRQChannel = USART3_IRQn;NVIC_InitStruct.NVIC_IRQChannelSubPriority = 3;NVIC_Init(&NVIC_InitStruct);USART_Cmd(USART2, ENABLE);USART_Cmd(USART3, ENABLE);// 初始化USART1用于ASRPRO通信USART1_Init();
}// 新增:ASRPRO通信中断处理
void USART3_IRQHandler(void) {if (USART_GetITStatus(USART3, USART_IT_RXNE) == SET) {asr_cmd = USART_ReceiveData(USART3);// 解析ASRPRO发送的指令switch (asr_cmd) {case 'A':// 开灯led_ctrl(D1,ON);break;case 'F':// 小车前进car_up();break;case 'B':// 小车后退car_back();break;case 'L':// 小车左转car_left();break;case 'R':// 小车右转car_right();break;case 'S':// 小车停止car_stop();break;case 'G':// 请求烟雾浓度request_smoke_data = 1;break;default:// 未知指令break;}USART_ClearITPendingBit(USART3, USART_IT_RXNE);}
}// 中断处理函数(固定帧)
void USART2_IRQHandler(void) {if (USART_GetITStatus(USART2, USART_IT_RXNE) == SET) {recv = USART_ReceiveData(USART2);USART_ClearITPendingBit(USART2, USART_IT_RXNE);// 检测特定指令触发烟雾浓度请求if (recv == 'S' || recv == 's') { // 当接收到 'S' 或 's' 时请求数据request_smoke_data = 1;}}
}//void USART3_IRQHandler(void) {
//    if (USART_GetITStatus(USART3, USART_IT_RXNE) == SET) {
//        rdata = USART_ReceiveData(USART3);
//        mq2_response[mq2_response_index++] = rdata;
//        // 接收到9字节后开始处理
//        if (mq2_response_index == 9) {
//            mq2_response_index = 0;
//            parse_mq2_response();
//            send_smoke_concentration_to_bluetooth(); // 发送浓度数据
//            request_smoke_data = 0; // 重置请求标志
//        }
//        USART_ClearITPendingBit(USART3, USART_IT_RXNE);
//    }
//}
#ifndef __UART_H__
#define __UART_H__
#include "stm32f4xx.h"void uart_init(int bond);
void USART1_Init(void);  // 新增:ASRPRO通信串口初始化
void USART2_IRQHandler(void);
void USART3_IRQHandler(void);
void USART1_IRQHandler(void);  // 新增:ASRPRO通信中断处理
void send_mq2_request(void);
void send_smoke_concentration_to_bluetooth(void);extern u8 recv;  // USART2接收数据(命令)
extern u8 rdata; // USART3接收数据(MQ2传感器数据)
extern u8 asr_cmd; // 新增:ASRPRO接收的指令
extern uint8_t request_smoke_data; // 请求烟雾数据标志
#endif
#include "stm32f4xx.h"
#include "exit.h"
#include "car.h"
#include "delay.h"
#include "remote.h"
#include "uart.h"
#include "led.h"extern uint8_t request_smoke_data;int main(void) {// 系统初始化SystemInit();// 外设初始化car_init();        // 初始化小车控制remote_Init();     // 初始化遥控器delay_init();      // 初始化延时函数led_init();        // 初始化LEDuart_init(9600);   // 初始化串口,波特率9600//car_up();// 系统启动提示// USART2_SendString("系统已启动,等待指令...\r\n");// USART1_IRQHandler();while(1) {// 当请求标志被设置时发送MQ2请求if (request_smoke_data) {send_mq2_request();// 等待一段时间以确保数据接收完成delay_ms(500);}// 其他可能的主循环任务// ...// 低功耗延时,减少CPU占用delay_ms(10);}
}

且记录且珍惜,又不想记录了。

结束语🥇

🔥 订阅专栏持续学习:C语言到基于STM32的智能矿探小车
💬 欢迎点赞、收藏、留言讨论,后续将分享语音模块与蓝牙模块的协同控制方案,进一步提升矿探小车的操作便捷性!


文章转载自:
http://assonate.elldm.cn
http://centrifugate.elldm.cn
http://cecrops.elldm.cn
http://cephalochordate.elldm.cn
http://brooklynese.elldm.cn
http://chilian.elldm.cn
http://calabar.elldm.cn
http://athrocytosis.elldm.cn
http://assuming.elldm.cn
http://catbird.elldm.cn
http://apres.elldm.cn
http://based.elldm.cn
http://beshow.elldm.cn
http://brier.elldm.cn
http://chestful.elldm.cn
http://banderillero.elldm.cn
http://bathypelagic.elldm.cn
http://angelhood.elldm.cn
http://adsl.elldm.cn
http://awedness.elldm.cn
http://carless.elldm.cn
http://ani.elldm.cn
http://assify.elldm.cn
http://accompanier.elldm.cn
http://chronical.elldm.cn
http://blockbuster.elldm.cn
http://cellophane.elldm.cn
http://agglomeration.elldm.cn
http://antisickling.elldm.cn
http://causalgic.elldm.cn
http://www.dtcms.com/a/281120.html

相关文章:

  • AI 增强大前端数据加密与隐私保护:技术实现与合规遵
  • Python 程序设计讲义(2):Python 概述
  • pc浏览器页面语音播报功能
  • 多路文件IO的几个模型
  • K-means 聚类在肺炎患者分型中的应用(简单示例)
  • 轻轻松松带你进行-负载均衡LVS实战
  • 随机奖励能提升Qwen数学表现?本质是数据污染
  • brupsuite使用中遇到的一些问题(bp启动后浏览器无法连接)/如何导入证书
  • YCQ340汽油机气缸体总成设计cad【8张】设计说明书
  • 模拟C++简易配置系统(模板类 + 全局管理)
  • 一区 Top (HPJ) | WGAS+WGCNA分析文章套路
  • 零基础学软件测试:超详细软件测试基础理论知识讲解
  • 【实时Linux实战系列】使用系统调用实现实时同步
  • Java项目:基于SSM框架实现的学生档案管理系统【ssm+B/S架构+源码+数据库+毕业论文+开题报告】
  • 智能体技术深度解析:从概念到企业级搭建指南
  • 自学java,什么书比较好?
  • MaxKB使用笔记【持续ing】
  • LeetCode 1888. 使二进制字符串字符交替的最少反转次数
  • 维基框架发布 1.0.11 至中央仓,深化国产化 DevOps 生态整合
  • 3-Nodejs-使用fs文件系统模块
  • kotlin的自学笔记1
  • 文心一言开源版部署及多维度测评实例
  • Listener(监听器)
  • 拓扑排序一>可达性统计
  • [WUSTCTF2020]朴实无华
  • Vue 3的核心机制-解析事件流、DOM更新、数据请求、DOM操作规范及组件库DOM操作的解决方案
  • 日记_7.14_实际开发的进步
  • 使用Spring Cloud LoadBalancer报错java.lang.IllegalStateException
  • Wordpress登录数据库连接失败的问题
  • Web攻防-PHP反序列化字符逃逸增多减少成员变量属性解析不敏感Wakeup绕过