目录
一、定制词条
二、直接用串口通信
三、使用单片机通信
理论篇在这,依旧是深圳雷龙发展的语音模块。
http://t.csdnimg.cn/2SzJL
一、定制词条
因为我想后面加到我的毕设上加个语音模块,所以定制的词条都是和芯测相关的。
动作 | 词条 | 播报 | 串口输出(9600) |
开机播报 | 无 | ||
10S自动退出唤醒 | 有需要再叫我 | 无 | |
唤醒词 | 你好小龙 | 我在 | FE 04 00 00 02 FD |
命令词 | 录制音频 | 开始录制 | FE 04 00 01 03 FD |
播放音频 | 开始播放 | FE 04 00 02 04 FD | |
显示红色 | 显示红色 | FE 04 00 03 05 FD | |
显示多色 | 显示多色 | FE 04 00 04 06 FD | |
调节背光 | 调节背光 | FE 04 00 05 07 FD | |
时钟测试 | 开始测试 | FE 04 00 06 08 FD | |
四八五测试 | 开始测试 | FE 04 00 07 09 FD | |
看测试 | 开始测试 | FE 04 00 08 0A FD | |
按键测试 | 开始测试 | FE 04 00 09 0B FD | |
查看温度 | 查看温度 | FE 04 00 0A 0C FD | |
开始网络通信 | 开始网络通信 | FE 04 00 0B 0D FD | |
关闭网络通信 | 关闭网络通信 | FE 04 00 0C 0E FD | |
关闭显示器 | 关闭显示器 | FE 04 00 0D 0F FD | |
打开显示器 | 打开显示器 | FE 04 00 0E 10 FD | |
查看环境温度 | 查看环境温度 | FE 04 00 0F 11 FD | |
查看环境湿度 | 查看环境湿度 | FE 04 00 10 12 FD | |
查看当前位置 | 查看单签位置 | FE 04 00 11 13 FD | |
前进 | 前进 | FE 04 00 12 14 FD | |
后退 | 后退 | FE 04 00 13 15 FD | |
停止 | 停止 | FE 04 00 14 16 FD |
二、直接用串口通信
起始码 | 长度 | 方向 | 动作ID | SUM | 结束码 |
0xFE | 0x04 | 0x00 | 0xXX | 0xXX | 0xFD |
和技术人员沟通电源最好用5V的供电,我直接接串口用PC做了下测试
因为这个接线柱是2.0的所以不能直接用杜邦线,杜邦线是2.54的。所欲我就扒了个皮给他焊上了,防止不同接线柱之间连电,这里需要保留一部分塑料。
随便测了几个指令这里拾音度是真的高很灵敏。比我之前做的那个灵敏。但是还是那个缺点,不能自己改语音指令有点难受。
为了低功耗,所以这类语音模块都是那种唤醒词形式的。像咱们的手机小爱同学,hi,Siri等等这种,我的这个叫你好小龙。
总体来说可定制化很高比那种自己可以拿SDK烧写的要高很多,缺点是没SDK。
音量的调节也比较麻烦需要修改电阻的大小。具体怎么修改到时候可以问技术人员
大概就是修改这两个电阻。
三、使用单片机通信
重点来咯,怎么用单片机实现,之前想着用I.MAX6ULL来着,但是我现在没时间,就用经典c8t6来做个demo吧。很好一年没写32的程序了已经忘的差不多了哈哈。
先说说思路,初始化串口1和串口2.串口2接我们的模块,接收到指令后分析一下转化成对应语句打印到串口1很简单的程序,为什么不真的来控制一下呢,还是那句话,没时间。c8t6最小系统没有板载传感器,连灯泡也就一个。难受的很我要自己焊接,属实麻烦嘿嘿。各位读者朋友见谅哈。作者要做毕设,时间紧任务重呀,用韦东山老师的板子本来以为有移植好的鸿蒙和驱动,我只做服务器客户端还有通信就可用呢。但是被骗了,裸机写的驱动程序,和鸿蒙没有一毛钱关系。我要开发14个驱动程序还要学习鸿蒙应用层开发,以及最难的。把鸿蒙移植到I.MAX6ULL上。所以木有办法咯,抱歉抱歉后面有机会再来好好写写怎么用语音模块。
下面是串口2的驱动程序,基于标准库的,为什么叫ESP8266因为我懒所以拿那个代码改的哈哈。
/* 函数体 --------------------------------------------------------------------*/
/*** 函数功能: 初始化ESP8266用到的GPIO引脚* 输入参数: 无* 返 回 值: 无* 说 明:无*/
static void ESP8266_GPIO_Config ( void )
{/*定义一个GPIO_InitTypeDef类型的结构体*/GPIO_InitTypeDef GPIO_InitStructure;/* 配置 CH_PD 引脚*/RCC_APB2PeriphClockCmd( ESP8266_RST_CLK, ENABLE ); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; /* 配置 RST 引脚*/ GPIO_InitStructure.GPIO_Pin = ESP8266_RST_PIN;GPIO_Init ( ESP8266_RST_PORT, & GPIO_InitStructure ); /* 拉高WiFi模块的复位重启引脚 */GPIO_ResetBits( ESP8266_RST_PORT, ESP8266_RST_PIN );}/*** 函数功能: 配置 ESP8266 USART 的 NVIC 中断优先级* 输入参数: 无* 返 回 值: 无* 说 明:无*/
static void ESP8266_USART_NVIC_Configuration ( void )
{NVIC_InitTypeDef NVIC_InitStructure; /* Configure the NVIC Preemption Priority Bits */ NVIC_PriorityGroupConfig ( NVIC_PriorityGroup_2 );/* Enable the USART2 Interrupt */NVIC_InitStructure.NVIC_IRQChannel = ESP8266_USART_IRQ; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);}/*** 函数功能: 初始化ESP8266用到的 USART* 输入参数: 无* 返 回 值: 无* 说 明:无*/
static void ESP8266_USART_Config ( void )
{GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure; /* config USART clock */ESP8266_USART_APBxClock_FUN ( ESP8266_USART_CLK, ENABLE );ESP8266_USART_GPIO_APBxClock_FUN ( ESP8266_USART_GPIO_CLK | RCC_APB2Periph_AFIO, ENABLE );/* USART GPIO config *//* Configure USART Tx as alternate function push-pull */GPIO_InitStructure.GPIO_Pin = ESP8266_USART_TX_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(ESP8266_USART_TX_PORT, &GPIO_InitStructure); /* Configure USART Rx as input floating */GPIO_InitStructure.GPIO_Pin = ESP8266_USART_RX_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(ESP8266_USART_RX_PORT, &GPIO_InitStructure);/* USART1 mode config */USART_InitStructure.USART_BaudRate = ESP8266_USART_BAUD_RATE;USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_InitStructure.USART_StopBits = USART_StopBits_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_Init(ESP8266_USARTx, &USART_InitStructure);/* 中断配置 */USART_ITConfig ( ESP8266_USARTx, USART_IT_RXNE, ENABLE ); //使能串口接收中断 USART_ITConfig ( ESP8266_USARTx, USART_IT_IDLE, ENABLE ); //使能串口总线空闲中断 ESP8266_USART_NVIC_Configuration(); USART_Cmd(ESP8266_USARTx, ENABLE); /* 清除发送完成标志 */USART_ClearFlag(ESP8266_USARTx, USART_FLAG_TC|USART_FLAG_TXE|USART_FLAG_RXNE);
}/*** 函数功能: 格式化输出,类似于C库中的printf,但这里没有用到C库* 输入参数: USARTx 串口通道,这里只用到了串口2,即USART2* Data 要发送到串口的内容的指针* ... 其他参数* 返 回 值: 无* 说 明:典型应用 USART2_printf( USART2, "\r\n this is a demo \r\n" );* USART2_printf( USART2, "\r\n %d \r\n", i );* USART2_printf( USART2, "\r\n %s \r\n", j );*/
void USART_printf(USART_TypeDef * USARTx, char * Data, ... )
{const char *s;int d; char buf[16];va_list ap;va_start(ap, Data);while ( * Data != 0 ) // 判断是否到达字符串结束符{ if ( * Data == 0x5c ) //'\'{ switch ( *++Data ){case 'r': //回车符USART_SendData(USARTx, 0x0d);Data ++;break;case 'n': //换行符USART_SendData(USARTx, 0x0a); Data ++;break;default:Data ++;break;} }else if ( * Data == '%'){ //switch ( *++Data ){ case 's': //字符串s = va_arg(ap, const char *);for ( ; *s; s++) {USART_SendData(USARTx,*s);while( USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET );} Data++; break;case 'd': //十进制d = va_arg(ap, int); itoa(d, buf, 10); for (s = buf; *s; s++) {USART_SendData(USARTx,*s);while( USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET );} Data++; break; default:Data++; break; } } else USART_SendData(USARTx, *Data++);while ( USART_GetFlagStatus ( USARTx, USART_FLAG_TXE ) == RESET );}
}/*** 函数功能: 将整形数据转换成字符串* 输入参数: radix =10 表示10进制,其他结果为0* value 要转换的整形数* buf 转换后的字符串* radix = 10* 返 回 值: 无* 说 明:被USART_printf()调用*/
static char * itoa( int value, char *string, int radix )
{int i, d;int flag = 0;char *ptr = string;/* This implementation only works for decimal numbers. */if (radix != 10){*ptr = 0;return string;}if (!value){*ptr++ = 0x30;*ptr = 0;return string;}/* if this is a negative value insert the minus sign. */if (value < 0){*ptr++ = '-';/* Make the value positive. */value *= -1;}for (i = 10000; i > 0; i /= 10){d = value / i;if (d || flag){*ptr++ = (char)(d + 0x30);value -= (d * i);flag = 1;}}/* Null terminate the string. */*ptr = 0;return string;
} /* NCL_Itoa *//*** 函数功能: ESP8266初始化函数* 输入参数: 无* 返 回 值: 无* 说 明:无*/
void ESP8266_Init ( void )
{ESP8266_GPIO_Config (); ESP8266_USART_Config ();
}
下面是串口1的初始化和输入输出重定向
void DEBUG_USART_Init(void)
{/* 定义IO硬件初始化结构体变量 */GPIO_InitTypeDef GPIO_InitStructure;/* 定义USART初始化结构体变量 */USART_InitTypeDef USART_InitStructure;/* 使能USART时钟 */DEBUG_USARTx_ClockCmd(DEBUG_USARTx_CLK,ENABLE);/* 使能USART功能GPIO时钟 */DEBUG_USARTx_GPIO_ClockCmd(DEBUG_USARTx_TX_CLK | DEBUG_USARTx_RX_CLK | RCC_APB2Periph_AFIO,ENABLE);/* 调试USART功能GPIO初始化 *//* 设定USART发送对应IO编号 */GPIO_InitStructure.GPIO_Pin = DEBUG_USARTx_TX_PIN;/* 设定USART发送对应IO模式:复用推挽输出 */GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;/* 设定USART发送对应IO最大操作速度 :GPIO_Speed_50MHz */GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;/* 初始化USART发送对应IO */GPIO_Init(DEBUG_USARTx_TX_PORT, &GPIO_InitStructure); /* 设定USART接收对应IO编号 */GPIO_InitStructure.GPIO_Pin = DEBUG_USARTx_RX_PIN;/* 设定USART发送对应IO模式:浮空输入 */GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;/* 其他没有重新赋值的成员使用与串口发送相同配置 *//* 初始化USART接收对应IO */GPIO_Init(DEBUG_USARTx_RX_PORT, &GPIO_InitStructure); /* USART工作环境配置 *//* USART波特率:115200 */USART_InitStructure.USART_BaudRate = DEBUG_USARTx_BAUDRATE;/* USART字长(有效位):8位 */USART_InitStructure.USART_WordLength = USART_WordLength_8b;/* USART停止位:1位 */USART_InitStructure.USART_StopBits = USART_StopBits_1;/* USART校验位:无 */USART_InitStructure.USART_Parity = USART_Parity_No ;/* USART硬件数据流控制(硬件信号控制传输停止):无 */USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;/* USART工作模式使能:允许接收和发送 */USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;/* 初始化USART */USART_Init(DEBUG_USARTx, &USART_InitStructure);/* 使能USART */USART_Cmd(DEBUG_USARTx, ENABLE);}/*** 函数功能: 重定向c库函数printf到USARTx* 输入参数: 无* 返 回 值: 无* 说 明:无*/
int fputc(int ch, FILE *f)
{/* 发送一个字节数据到调试串口 */USART_SendData(DEBUG_USARTx, (uint8_t) ch);/* 等待串口数据发送完毕 */while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET); return (ch);
}/*** 函数功能: 重定向c库函数getchar,scanf到USARTx* 输入参数: 无* 返 回 值: 无* 说 明:无*/
int fgetc(FILE *f)
{/* 等待串口输入数据 */while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_RXNE) == RESET);return (int)USART_ReceiveData(DEBUG_USARTx);
}
主要是中断处理,在中断接收数据并存入缓冲区然后主函数中对缓冲区内容与ID进行比对,最后打印到串口助手。
void ESP8266_USART_INT_FUN(void)
{uint8_t ucCh;count++;if ( USART_GetITStatus (ESP8266_USARTx, USART_IT_RXNE ) != RESET ){
// ucCh = USART_ReceiveData(ESP8266_USARTx );
// ucaRxBuf[count] = ucCh;if ( strEsp8266_Fram_Record .InfBit .FramLength < ( RX_BUF_MAX_LEN - 1 ) ) //预留1个字节写结束符strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength ++ ] = ucCh;}if ( USART_GetITStatus(ESP8266_USARTx, USART_IT_IDLE ) == SET ) //数据帧接收完毕{if(strEsp8266_Fram_Record .InfBit .FramLength >= 6){ ucTcpClosedFlag = 1;strEsp8266_Fram_Record .InfBit .FramFinishFlag = 1;strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength++ ] = '\0';}ucCh = USART_ReceiveData(ESP8266_USARTx );//ucTcpClosedFlag = strstr(strEsp8266_Fram_Record .Data_RX_BUF, "CLOSED\r\n" ) ? 1 : 0;}else{strEsp8266_Fram_Record .InfBit .FramFinishFlag = 0;//ucTcpClosedFlag = 0;}
}
稍微修改了一下。
主函数的逻辑大家按照自己的需要去做就行,接收到什么ID对应去操作什么器件。我这里就直接解析并且打印了。