JQ8900语音模块串口控制与移植实战:基于TI MSPM0开发板的语音播报驱动开发

发布时间:2026/6/10 16:29:02

JQ8900语音模块串口控制与移植实战:基于TI MSPM0开发板的语音播报驱动开发 JQ8900语音模块串口控制与移植实战基于TI MSPM0开发板的语音播报驱动开发最近在做一个智能小项目需要加入语音提示功能比如“温度过高”、“欢迎光临”这样的语音播报。找了一圈发现JQ8900这个语音模块挺合适价格便宜、控制简单最关键的是它内置了功放直接就能驱动喇叭省了不少事。但网上的资料大多是针对STM32或者Arduino的怎么把它接到TI的MSPM0开发板上用起来还是有点门槛。今天我就把自己在TI MSPM0开发板上折腾JQ8900模块的过程整理出来从硬件连接到软件配置再到代码移植和调试手把手带你走一遍。如果你也在用MSPM0系列芯片比如立创的开发板想快速给项目加上语音功能这篇教程应该能帮到你。1. JQ8900语音模块初探它是什么怎么用在动手写代码之前咱们先得搞清楚要驱动的对象。JQ8900是一个集成了MP3解码、音频功放和存储的语音播报模块。你可以把它理解成一个“会说话的U盘”。核心特点供电灵活工作电压范围是2.8V到5.5V这意味着它既可以用3.3V系统供电也能兼容5V系统。模块引脚的输出电平是3.3V和咱们的MSPM0开发板正好匹配直接连接就行不用担心电平转换。控制简单主要通过串口UART来控制。它支持三种模式单独IO控制每个语音文件对应一个引脚拉低就播放适合按键触发。一线串行控制用一根数据线通过特定的脉冲时序来发送指令节省引脚。两线串口控制就是标准的UART串口发送固定的指令帧最常用也最灵活。我们这次就采用这种方式。语音更新超方便这是它最大的亮点模块内部有一个SPI Flash来存储语音文件。你只需要用USB线把模块连到电脑上电脑会把它识别成一个U盘。直接把你的MP3或WAV音频文件拖进去按规则命名比如00001.mp3、00002.mp3就完成了更新完全不需要专用的烧录软件。注意模块出厂时自带10首测试语音。自己添加语音时注意文件不要太大避免SPI Flash空间不够。通信参数关键 使用两线串口控制时模块的默认通信参数是波特率9600数据位8位停止位1位校验位无这些参数在初始化我们的MSPM0串口时必须完全一致否则模块就“听不懂”我们发的指令了。2. 硬件连接与SysConfig引脚配置硬件连接很简单就是串口线对接。我使用的是TI MSPM0开发板上的串口1UART1。接线示意图MSPM0开发板引脚JQ8900模块引脚说明PA10(UART1_RX)TX开发板接收连接模块的发送端PA11(UART1_TX)RX开发板发送连接模块的接收端GNDGND共地确保电平参考一致3.3VVCC供电确保在2.8V-5.5V范围内接好线后我们需要在代码层面告诉芯片PA10和PA11这两个引脚要用作串口功能。TI的MSPM0 SDK推荐使用图形化的SysConfig工具来配置非常直观能避免手动配置寄存器出错。SysConfig配置步骤打开工程在你的CCS或IAR工程里找到并双击empty.syscfg文件或其他类似的.syscfg文件。启动工具在打开的界面中点击Tools菜单然后选择SYSCONFIG工具。添加UART外设在左侧的组件列表中找到或搜索“UART”点击ADD按钮添加一个UART实例。配置UART参数在右侧属性面板中选择具体的UART模块例如UART1。将RX Pin设置为PA10TX Pin设置为PA11。将Baud Rate设置为9600Data Length设置为8 bitsStop Bits设置为1Parity Type设置为None。这必须和JQ8900模块的默认参数严格对应。配置GPIO可选如果你后续想用一线串行模式可能需要配置一个普通的GPIO引脚。同样在组件列表中添加“GPIO”并指定一个引脚如PA0将其方向设置为输出。保存并生成代码点击保存按钮。这时可能会弹出一个警告框提示将覆盖现有引脚配置一定要选择Yes to All。编译保存后点击编译。有时第一次编译可能会报一些无关紧要的警告可以先忽略。完成这些步骤后SysConfig工具会自动在工程中生成一个ti_msp_dl_config.h文件里面就定义好了我们刚才配置的UART1引脚和参数。这个文件通常已经被包含在board.h里了所以我们后续编程时直接包含board.h头文件就行非常方便。3. 驱动代码移植与解析硬件和引脚配置好后接下来就是编写驱动代码了。我们需要创建两个文件bsp_jq8900.c和bsp_jq8900.h注意原始文章里文件名写的是bsp_syn6288这里我们根据模块名更正为jq8900。3.1 头文件定义 (bsp_jq8900.h)头文件主要进行宏定义和函数声明。#ifndef _BSP_JQ8900_H_ #define _BSP_JQ8900_H_ #include board.h // 包含SysConfig生成的配置 // 是否开启串口调试用于打印JQ8900返回的数据如果需要 #define DEBUG 1 #define JQ8900_RX_LEN_MAX 250 // 串口接收缓冲区最大长度 // 一线串行控制模式下的宏定义如果使用此模式 // 假设你用PA0引脚控制这里需要根据SysConfig中GPIO的配置来修改 // GPIO_PORT 和 GPIO_VPP_PIN 需要替换为实际的端口和引脚定义例如 DL_GPIO_PORT_A, DL_GPIO_PIN_0 #define SET_JQ8900_APP(X) ( (X) ? (DL_GPIO_setPins(GPIO_PORT_A, GPIO_PIN_0)) : (DL_GPIO_clearPins(GPIO_PORT_A, GPIO_PIN_0)) ) // 函数声明 void JQ8900_Init(void); void JQ8900_USART_send_String(unsigned char *str, unsigned int len); void JQ8900_USART_Send_Bit(unsigned char ch); void SendData ( unsigned char addr ); // 一线串行控制函数 void Clear_JQ8900_RX_BUFF(void); #endif3.2 核心驱动函数实现 (bsp_jq8900.c)这里包含了串口发送、初始化以及中断接收等核心功能。#include bsp_jq8900.h #include stdio.h #include string.h // 定义接收缓冲区和状态标志 unsigned char JQ8900_RX_BUFF[JQ8900_RX_LEN_MAX]; unsigned char JQ8900_RX_FLAG 0; // 接收完成标志 unsigned char JQ8900_RX_LEN 0; // 接收到的数据长度 /** * brief 向JQ8900发送单个字节 * param ch 要发送的字符 * note 内部会等待串口发送空闲防止数据覆盖 */ void JQ8900_USART_Send_Bit(unsigned char ch) { // 等待串口1的发送缓冲区空闲 while( DL_UART_isBusy(UART_1_INST) true ); // 发送数据 DL_UART_Main_transmitData(UART_1_INST, ch); } /** * brief 向JQ8900发送字符串指令帧 * param str 要发送的字符串指针 * param len 要发送的长度 */ void JQ8900_USART_send_String(unsigned char *str, unsigned int len) { while( len-- ) { JQ8900_USART_Send_Bit(*str); } } /** * brief 清除接收缓冲区 */ void Clear_JQ8900_RX_BUFF(void) { unsigned char i JQ8900_RX_LEN_MAX - 1; while(i) { JQ8900_RX_BUFF[i--] 0; } JQ8900_RX_LEN 0; JQ8900_RX_FLAG 0; } /** * brief JQ8900模块初始化 * note 主要开启串口接收中断以便接收模块的反馈信息如播放完成信号 */ void JQ8900_Init(void) { // 清除串口1的中断挂起标志 NVIC_ClearPendingIRQ(UART_1_INST_INT_IRQN); // 使能开启串口1的中断 NVIC_EnableIRQ(UART_1_INST_INT_IRQN); // 注意还需要在SysConfig中使能UART的接收中断功能 } /** * brief 一线串行控制模式发送指令 * param addr 要发送的指令对应语音序号等 * note 此函数使用一个GPIO引脚模拟特定时序如果使用两线串口可忽略此函数 */ void SendData ( unsigned char addr ) { unsigned char i; SET_JQ8900_APP(1); // 起始位先拉高电平 delay_us ( 500 ); SET_JQ8900_APP(0); // 开始引导码拉低 delay_ms ( 4 ); // 引导码低电平持续至少2ms建议4ms // 发送8位数据从最低位开始 for ( i 0; i 8; i ) { SET_JQ8900_APP(1); // 每个数据位都以高电平开始 if ( addr 0x01 ) // 判断当前最低位是1还是0 { // 发送‘1’高电平1300us低电平500us delay_us ( 1300 ); SET_JQ8900_APP(0); delay_us ( 500 ); } else { // 发送‘0’高电平500us低电平1300us delay_us ( 500 ); SET_JQ8900_APP(0); delay_us ( 1300 ); } addr 1; // 数据右移准备发送下一位 } SET_JQ8900_APP(1); // 发送完毕拉高总线 delay_ms(10); // 指令间延时建议10ms以上 } /** * brief 串口1中断服务函数 * note 当JQ8900模块有数据返回如播放状态时会进入此函数 */ void UART_1_INST_IRQHandler(void) { // 判断中断来源 switch( DL_UART_getPendingInterrupt(UART_1_INST) ) { case DL_UART_IIDX_RX: // 如果是接收中断 // 读取接收到的数据 JQ8900_RX_BUFF[ JQ8900_RX_LEN ] DL_UART_Main_receiveData(UART_1_INST); // 调试用将接收到的字符打印出来需确保printf已重定向 #if DEBUG printf(%c, JQ8900_RX_BUFF[ JQ8900_RX_LEN ]); #endif // 更新接收长度和缓冲区结束符 JQ8900_RX_LEN ( JQ8900_RX_LEN 1 ) % JQ8900_RX_LEN_MAX; JQ8900_RX_BUFF[JQ8900_RX_LEN] \0; // 设置接收完成标志主循环中可以查询此标志处理数据 JQ8900_RX_FLAG 1; break; default: // 处理其他类型的中断如发送中断 break; } }关键点解析发送函数JQ8900_USART_send_String是核心它用于发送符合JQ8900协议格式的指令帧。中断接收我们开启了串口接收中断。虽然简单的播放不需要接收但如果你需要查询模块状态比如是否播放完毕这个功能就很有用。数据会存到JQ8900_RX_BUFF中并通过JQ8900_RX_FLAG通知主程序。一线串行模式SendData函数提供了另一种控制方式。它通过精确的延时控制一个GPIO引脚的高低电平来传递数据节省了一个串口但对时序要求严格。4. 实战应用在主程序中播放语音驱动写好了最后就是在主函数里调用它。JQ8900的串口指令是固定的格式例如0xAA, 0x07, 0x02, 0xB3这样的4字节或5字节数据包。下面是一个简单的测试例程让模块循环播放下一曲#include board.h #include stdio.h #include bsp_jq8900.h int main(void) { // JQ8900两线串口控制指令示例0xAA 0x06 0x00 0xB0 (播放下一曲) uint8_t send_buff[4] {0xAA, 0x06, 0x00, 0xB0}; // 开发板初始化时钟、外设等 board_init(); // 初始化JQ8900模块主要是使能串口中断 JQ8900_Init(); printf(JQ8900 Test Start...\r\n); while(1) { // 每隔3秒发送一次“下一曲”指令 JQ8900_USART_send_String(send_buff, 4); delay_ms(3000); // 延时3秒 } }上电效果如果模块里存了多首语音上电后你就会听到它开始一首接一首地播放。常用指令参考你可以替换send_buff里的内容指定播放{0xAA, 0x07, 0x02, 0x01, 0xB4}播放第1首0x01是曲目号。暂停/播放{0xAA, 0x03, 0x00, 0xAD}停止{0xAA, 0x04, 0x00, 0xAE}音量设置{0xAA, 0x13, 0x01, 0x10, 0xDE}设置音量为160x10。移植中可能遇到的坑没声音首先检查硬件连接RX/TX是否接反、供电是否正常。然后用逻辑分析仪或另一个串口助手监听MSPM0的TX引脚看指令是否真的发出去了。指令不响应99%的原因是波特率不对。务必确认SysConfig里UART的波特率、数据位、停止位、校验位与模块9600, 8N1完全一致。一线模式时序问题如果使用一线模式delay_us和delay_ms的精度非常关键。确保你的系统时钟配置正确延时函数是准确的。好了整个移植过程就是这样。总结一下关键步骤硬件连接 - SysConfig配置引脚 - 编写驱动文件 - 主程序发指令。这套代码在立创的MSPM0开发板上跑通过你可以直接参考。把语音文件用U盘模式拷进模块修改一下主程序里的指令就能让你的设备“开口说话”了。

相关新闻