B43 - 基于STM32单片机的自动视力检测仪

任务

本系统设计了一个基于STM32单片机的自动视力检测系统,通过单片机控制LCD高清液晶显示屏显示“E”字形的开口方向和大小,来替代传统的视力测试面板;通过语音播放模块进行测试过程的提示语播放、语音识别模块进行识别测试者对于当前屏幕显示“E”形状的开口方向的回答,完成对测试者的自动视力检测过程;通过无线按钮为听力受损人员提供手动按下方向按键回答屏幕显示“E”行方向和大小的功能。本系统整体设计功能和参数如下。
设计功能:
(1)采用LCD高清液晶显示“E”字形,涵盖视力检测板所有“E”形状和大小。(2)自动化语音提示,确保检测者知道当前需要做什么。
(3)智能化语音识别,系统精准采集测试者的回答结果。
(4)无线按键,方便用户通过选择按下的方向按键回答显示屏“E”开口方向,扩大适用人群和使用环境。
(5)采用QT设计安卓程序,通过蓝牙和主控板连接,能够记录和显示测试者本人的近期视力检测结果,可以通过蓝牙应用程序或者在液晶屏上获取到对应的折线图,使用户方便直观的看到视力检测结果的变化。
(6)检测系统在调取检测结果时,可以根据历史检测结果做出温馨提醒,比如“近期视力检测下降,请注意适当休息哦!”。
设计参数:
(1)显示屏幕细腻,分辨率最低480*320,屏幕尺寸采用3.5寸。
(2)无线通讯距离不低于5米。
(3)语音识别:非特定人识别,2米内识别准确率95%以上,识别速度2秒以内。
(4)识别语种:中文。
(5)语音播放功率不小于3W。
(6)检测结果可存储不低于100人,可记录每人最低20条最近测试结果。

在这里插入图片描述

实物

主机

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

从机

在这里插入图片描述
在这里插入图片描述

手机APP

蓝牙连接界面

注意:本次使用的蓝牙模块是HC-05。
在这里插入图片描述

获取视力记录在手机上同步显示折线图

在这里插入图片描述

原理图

主机

在这里插入图片描述

从机

在这里插入图片描述

资源分配

主机

在这里插入图片描述

从机

在这里插入图片描述

设计流程

在这里插入图片描述

源程序

本系统程序过多,只放置可以参考的代码,在做此方面功能的可用于参考思路。

主机主程序

/*******************************************************************************

\* 文件名称:基于STM32单片机的自动视力检测仪

\* 实验目的:1.

\* 2.

\* 程序说明:完整程序Q:277 227 2579;@: itworkstation@ hotmail.com

\* 日期版本:本项目分享关键细节,熟悉使用单片机的可做参考代码。完整讲解+源代码工程可联系获取,可定制。

*******************************************************************************/

/* Includes ------------------------------------------------------------------*/
#include "main.h"   
#include "lcdUart.h"
#include "key.h" 
#include "bsp_timer3.h"  
#include "usart3.h" 
#include "wireless.h"
#include "e2prom.h" 
#include "usart1.h" 
#include "bluetooth.h"
#include <math.h>
#include <stdlib.h>

u8 EPROM[10][18]; //10个测试者,每个20空间。1-10, 21-40,...
extern u8 E2ReadNowUserTab[18];

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
void StoreEpRom(void) //将结果存储
{
    
    
	u8 i=0;
	for(i=0;i<18;i++)
	{
    
    
		if(EPROM[LCD_InfoStru.TestUser-1][i] == 0)
		{
    
    
			break; //找到数组最近的为0的位置
		}
	}
	if(i==18) //已经存储了18次测试记录,删掉最久存储的一次
	{
    
    
		for(i=0;i<17;i++)
		{
    
    
			EPROM[LCD_InfoStru.TestUser-1][i] = EPROM[LCD_InfoStru.TestUser-1][i+1];
		}
		EPROM[LCD_InfoStru.TestUser-1][17] = LCD_InfoStru.Hang_Now+1; //改变一下存储值,因为显示时1.2应该是15,原值为14
	}
	else
	{
    
    
		EPROM[LCD_InfoStru.TestUser-1][i] = LCD_InfoStru.Hang_Now+1; //改变一下存储值,因为显示时1.2应该是15,原值为14
	}
	for(i=0;i<10;i++)
	{
    
    
		E2WriteStr(1+i*20,EPROM[i],18);
	}
}
/**
  * @说明     主函数
  * @参数     None 
  * @返回值   None
  */
int main(void)
{
    
    
	u8 EpPos=0,EpPosY=0;
	LED_Init();
	
	Proc_Init();
	
	USART2_Init(); 
	Delay_ms(1000);//上电等待 1 秒是串口屏模块正常工作的前提,如果没有足够的等待时间模块有可能无法正常的接收指令而导致系统出错。	
	printf("CLR(%d);DIR(3);BL(%d);\r\n",LCD_BackColor,LCD_Light);  //CLR(16);DIR(1);BL(10);  //白色,横屏,背光10(0-255:最亮:最暗)
	LCD_CheckBusy(); 
	
	Key_Init();
	TIM4_Init();  
	
	LCD_Menu = LCD_DEFAULT; 
	LCD_Display();
	
	USART3_Init();
	
	USART1_Init();
	
	E2Init();
	for(EpPos=0;EpPos<10;EpPos++) // 清空数据,初始化数组
	{
    
    
		for(EpPosY=0;EpPosY<18;EpPosY++)
		{
    
    
			EPROM[EpPos][EpPosY] = 0;
		}
	}
	if(e2Struct.is_newE2)
	{
    
    
		for(EpPos=0;EpPos<10;EpPos++)//0-10  0-17
		{
    
    
			E2WriteStr(1+EpPos*20,EPROM[EpPos],18);
		}
	}
	else{
    
    
		for(EpPos=0;EpPos<10;EpPos++)
		{
    
    
			E2ReadStr(1+EpPos*20,EPROM[EpPos],18); //获得历史检测结果
		}
	}
	TIM3_Init();
	while(1){
    
    		 
		if(TIM4_FlagStatus.Flag_500MS == TRUE){
    
    
		   TIM4_FlagStatus.Flag_500MS = FALSE;
		   LED_Control(REVERSE);    			   
		}
		parseBLUETOOTHBuffer();
		if(LCD_Menu == LCD_TEST) 
		{
    
    
			parseWIRELESSBuffer();
			if(WIRELESS_Data.isUsefull)
			{
    
    
				if(WIRELESS_Data.isResultRight) //收到从机数据,且结果为真
				{
    
    			
					LCD_InfoStru.is_ResultRight = 1;
					LCD_Display();
					Delay_ms(3000);
					LCD_InfoStru.is_ResultRight = 0;
					
					LCD_InfoStru.Hang_Time ++;
					if(LCD_InfoStru.Hang_Time>=5) //结束
					{
    
    
						
						LCD_InfoStru.Hang_RightTime = 0;
						LCD_InfoStru.Hang_ErrorTime = 0;
						LCD_InfoStru.Hang_Time = 0;
						
						StoreEpRom();
						LCD_Menu = LCD_TESTEND;
						if(LCD_InfoStru.Hang_Now<13)
							WIRELESS_sendMessage("$O1@");
						else
							WIRELESS_sendMessage("$O2@");
					}
					LCD_InfoStru.Hang_RightTime ++;
					if(LCD_InfoStru.Hang_RightTime > 2)
					{
    
    
						if(LCD_InfoStru.Hang_Now < Hang_Init)		
						{
    
    							
							//初始化行上面,正确3次,结束
							StoreEpRom();
							LCD_Menu = LCD_TESTEND;
							WIRELESS_sendMessage("$O1@");
						}
						else
						{
    
    
							//3次正确,下一行
							LCD_InfoStru.Hang_Now ++;
							if(LCD_InfoStru.Hang_Now >Hang_END)
							{
    
    
								LCD_InfoStru.Hang_Now = Hang_END;
								//1.2视力,结束
								StoreEpRom();
								LCD_Menu = LCD_TESTEND;
								WIRELESS_sendMessage("$O2@");
							}
						}					
						LCD_InfoStru.Hang_RightTime = 0;
						LCD_InfoStru.Hang_ErrorTime = 0;
						LCD_InfoStru.Hang_Time = 0;
					}
				}
				else{
    
    
					LCD_InfoStru.is_ResultRight = 2;
					LCD_Display();
					Delay_ms(3000);
					LCD_InfoStru.is_ResultRight = 0;
					
					//从机识别错误
					LCD_InfoStru.Hang_Time ++;
					if(LCD_InfoStru.Hang_Time>=5) //结束
					{
    
    
						
						LCD_InfoStru.Hang_RightTime = 0;
						LCD_InfoStru.Hang_ErrorTime = 0;
						LCD_InfoStru.Hang_Time = 0;
						
						StoreEpRom();
						LCD_Menu = LCD_TESTEND;
						if(LCD_InfoStru.Hang_Now<13)
							WIRELESS_sendMessage("$O1@");
						else
							WIRELESS_sendMessage("$O2@");
					}
					LCD_InfoStru.Hang_ErrorTime ++;
					if(LCD_InfoStru.Hang_ErrorTime > 2)
					{
    
    
						if(LCD_InfoStru.Hang_Now <= Hang_Init)						
						{
    
    
							//3次错误,初始行或者小于初始行,退到上一行
							LCD_InfoStru.Hang_Now --;
							if(LCD_InfoStru.Hang_Now < 1)
							{
    
    
								WIRELESS_sendMessage("$O1@");
								//最上行,结束
								StoreEpRom();
								LCD_Menu = LCD_TESTEND;
							}							
						}
						else{
    
    
							if(LCD_InfoStru.Hang_Now<13)
								WIRELESS_sendMessage("$O1@");
							else
								WIRELESS_sendMessage("$O2@");
							//往下检测时,3次错误,结束
							StoreEpRom();
							LCD_Menu = LCD_TESTEND;
						}
						LCD_InfoStru.Hang_RightTime = 0;
						LCD_InfoStru.Hang_ErrorTime = 0;
						LCD_InfoStru.Hang_Time = 0;
					}
				}
				LCD_InfoStru.rand_E = rand()%4;  
				WIRELESS_Clear_Data(); //使用一次,清空数据
				sprintf(WIRELESS_Data.SendDire,"$D%1d@",LCD_InfoStru.rand_E+1);
				WIRELESS_sendMessage(WIRELESS_Data.SendDire);
				
				TIM3_DateClear(); // 重新计时
				LCD_Display(); //刷新
			}
			
			if(TIM3_FlagStatus.Flag_1000MS == TRUE){
    
    
			   TIM3_FlagStatus.Flag_1000MS = FALSE;
				
			   TIM3_FlagStatus.Time_jishi --;
			   if(TIM3_FlagStatus.Time_jishi<0)
			   {
    
    		
					TIM3_FlagStatus.Time_jishi = 0;	
				   LCD_InfoStru.is_ResultRight = 2;
					LCD_Display();
					Delay_ms(3000);
					LCD_InfoStru.is_ResultRight = 0;
				   
				    LCD_InfoStru.Hang_Time ++;
					if(LCD_InfoStru.Hang_Time>=5) //结束
					{
    
    
						
						LCD_InfoStru.Hang_RightTime = 0;
						LCD_InfoStru.Hang_ErrorTime = 0;
						LCD_InfoStru.Hang_Time = 0;
						
						StoreEpRom();
						LCD_Menu = LCD_TESTEND;
						if(LCD_InfoStru.Hang_Now<13)
							WIRELESS_sendMessage("$O1@");
						else
							WIRELESS_sendMessage("$O2@");
					}
					LCD_InfoStru.Hang_ErrorTime ++;
					if(LCD_InfoStru.Hang_ErrorTime > 2)
					{
    
    
						if(LCD_InfoStru.Hang_Now <= Hang_Init)						
						{
    
    
							//3次错误,初始行或者小于初始行,退到上一行
							LCD_InfoStru.Hang_Now --;
							if(LCD_InfoStru.Hang_Now < 1)
							{
    
    
								WIRELESS_sendMessage("$O1@");
								//最上行,结束
								StoreEpRom();
								LCD_Menu = LCD_TESTEND;
							}														
						}
						else{
    
    
							//往下检测时,3次错误,结束
							StoreEpRom();
							LCD_Menu = LCD_TESTEND;
							if(LCD_InfoStru.Hang_Now<13)
								WIRELESS_sendMessage("$O1@");
							else
								WIRELESS_sendMessage("$O2@");
						}
						LCD_InfoStru.Hang_RightTime = 0;
						LCD_InfoStru.Hang_ErrorTime = 0;
						LCD_InfoStru.Hang_Time = 0;
					}					
					LCD_InfoStru.rand_E = rand()%4;  
					WIRELESS_Clear_Data(); //使用一次,清空数据
					sprintf(WIRELESS_Data.SendDire,"$D%1d@",LCD_InfoStru.rand_E+1);
					WIRELESS_sendMessage(WIRELESS_Data.SendDire);
					
					TIM3_DateClear();  //重新计时,计算
			   }
			   LCD_Display(); //刷新
			}			
		}
				
		Proc_Key();		 		
    }     
}



从机主程序

/*******************************************************************************  
* 文件名称:最小系统板STM32C8T6
* 实验目的:1.
*           2.
* 程序说明:
* 日期版本:
*******************************************************************************/

/* Includes ------------------------------------------------------------------*/
#include "main.h"   
#include "usart1.h" 
#include "JQ_8400.h" 
#include "key.h" 
#include "usart2.h" 
#include "wireless.h"
#include "usart3.h" 
#include "Lu_ASR01.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/**
  * @说明     主函数
  * @参数     None 
  * @返回值   None
  */
int main(void)
{
    
    
	u8 keyValue=0xff;
	LED_Init();
	LED_Control(ON);
	Delay_ms(1000);
	LED_Control(OFF);
	
	Proc_Init();
	
	USART1_Init();
	JQ8400_Init();
	
	Key_Init();
	
	USART2_Init();
	
	USART3_Init();
	
	TIM4_Init();  
	while(1){
    
    		 
		if(TIM4_FlagStatus.Flag_200MS == SET){
    
    
		   TIM4_FlagStatus.Flag_200MS = RESET;
		   LED_Control(REVERSE);    
		   Proc_200Ms();  
		}
		
		parseWIRELESSBuffer();
		
		if(WIRELESS_Data.isUsefull) // 只有接收到方向后才启动语音识别
		{
    
    
			parseASR01Buffer(); 
			if(ASR01_Data.isUsefull)
			{
    
    
				//无线接收到方向,语音识别到方向
				if(ASR01_Data.Direction == WIRELESS_Data.Direction)
				{
    
    				
					WIRELESS_SendStr("$T@");
				}
				else{
    
    					
					WIRELESS_SendStr("$F@");
				}
				ASR01_Clear_Data();
				WIRELESS_Clear_Data();
			}
			
			keyValue = Key_Scan();
			if(keyValue != 0xff)
			{
    
    
				if(WIRELESS_Data.Direction == keyValue)
				{
    
    
					JQ8400_6x00SendCmd(SELECTE_PLAY,2); 
					WIRELESS_SendStr("$T@");
				}
				else{
    
    
					JQ8400_6x00SendCmd(SELECTE_PLAY,3); 
					WIRELESS_SendStr("$F@");
				}
				WIRELESS_Clear_Data();
			}
		}
		else
		{
    
    
			ASR01_Clear_Data();
		}		
  }     
}



语音模块代码

#ifndef __Lu_ASR01_H
#define __Lu_ASR01_H

#include "stm32f10x.h"
#include "Def_config.h"

#define ASR01_Buffer_Length 50
#define ASR01_Length 5

typedef struct
{
    
    
	char ASR01_Rec_Buffer[ASR01_Buffer_Length];
	ENUM_JUDGE isGetData;		//是否获取到数据
	ENUM_JUDGE isParseData;	//是否解析完成

	ENUM_JUDGE isUsefull;		//信息是否有效
	
	uint16_t Direction;
} _ASR01Data;

extern _ASR01Data ASR01_Data;

void ASR01_RecHandle(u8 Res);
void ASR01_Clear_Data(void);
void parseASR01Buffer(void);

#endif 


#include "Lu_ASR01.h"
#include <string.h>
#include <stdio.h>

#include "JQ_8400.h" 

_ASR01Data ASR01_Data;
char  ASR01_RX_BUF[ASR01_Buffer_Length]; //接收缓冲,最大ASR01_Buffer_Length个字节.末字节为换行符 
u8 LuAsr_point2 = 0;
void ASR01_RecHandle(u8 Res)
{
    
    
	if(Res == '$')
	{
    
    
		LuAsr_point2 = 0;	
	}
	ASR01_RX_BUF[LuAsr_point2++] = Res;
	if(Res == '@' || LuAsr_point2 >3)									   
	{
    
    
		memset(ASR01_Data.ASR01_Rec_Buffer, 0, ASR01_Buffer_Length);      //清空
		memcpy(ASR01_Data.ASR01_Rec_Buffer, ASR01_RX_BUF, LuAsr_point2); 	//保存数据
		ASR01_Data.isGetData = TRUE; 
		LuAsr_point2 = 0;
		memset(ASR01_RX_BUF, 0, ASR01_Buffer_Length);      //清空
	}		
	if(LuAsr_point2 >= ASR01_Buffer_Length)
	{
    
    
		LuAsr_point2 = ASR01_Buffer_Length;
	}	
}
u8 ASR01_Find(char *a)                   // 串口命令识别函数
{
    
     
    if(strstr(ASR01_Data.ASR01_Rec_Buffer,a)!=NULL)
	    return 1;
	else
		return 0;
}
void ASR01_Clear_Data(void)
{
    
    
	ASR01_Data.isGetData = FALSE;
	ASR01_Data.isParseData = FALSE;
	ASR01_Data.isUsefull = FALSE;
	memset(ASR01_Data.ASR01_Rec_Buffer, 0, ASR01_Buffer_Length);      //清空

	memset(ASR01_RX_BUF, 0, ASR01_Buffer_Length);
	
	ASR01_Data.Direction = 0;
}
void parseASR01Buffer(void)
{
    
    
	if (ASR01_Data.isGetData)  //获得语音模块的数据 --- $1@   : $4@
	{
    
    
		ASR01_Data.isGetData = FALSE;
		if(ASR01_Find("$D1@"))
		{
    
    
			ASR01_Data.isParseData = TRUE;
			ASR01_Data.isUsefull = TRUE;
			
			ASR01_Data.Direction = 1;
//			JQ8400_6x00SendCmd(SELECTE_PLAY,1); //选择指定曲目播放
		}
		else if(ASR01_Find("$D2@"))
		{
    
    
			ASR01_Data.isParseData = TRUE;
			ASR01_Data.isUsefull = TRUE;
			
			ASR01_Data.Direction = 2;
		}
		else if(ASR01_Find("$D3@"))
		{
    
    
			ASR01_Data.isParseData = TRUE;
			ASR01_Data.isUsefull = TRUE;
			
			ASR01_Data.Direction = 4; //右
		}
		else if(ASR01_Find("$D4@"))
		{
    
      	
			ASR01_Data.isParseData = TRUE;
			ASR01_Data.isUsefull = TRUE;
			
			ASR01_Data.Direction = 3;
		}
		else
		{
    
    
			ASR01_Clear_Data(); //清空接收到的数据---数据帧无效
		}
	}
}





主机蓝牙指令处理

#ifndef __BLUETOOTH_h
#define __BLUETOOTH_h

#include "stm32f10x.h"
#include <string.h>
#include <stdio.h>
#include "Def_config.h"

#include "usart1.h" 
#define BLUETOOTH_SendStr  USART1_SendString

#define BLUETOOTH_Buffer_Length 100
#define BLUETOOTH_Length 50
#define BLUETOOTH_IntLength 4
typedef struct
{
    
    
	char BLUETOOTH_Rec_Buffer[BLUETOOTH_Buffer_Length];
	ENUM_JUDGE isGetData;		//是否获取到数据
	ENUM_JUDGE isParseData;	//是否解析完成
	ENUM_JUDGE isUsefull;		//信息是否有效
	
	char sendMessage[BLUETOOTH_Buffer_Length];

	char userIDchar[BLUETOOTH_IntLength];
	u16 userIDInt;
} _BLUETOOTHData;
extern _BLUETOOTHData BLUETOOTH_Data;

void BLUETOOTH_sendMessage(void);
void BLUETOOTH_RecHandle(u8 Res);
void BLUETOOTH_Clear_Data(void);
void parseBLUETOOTHBuffer(void);



#endif 




#include "bluetooth.h"
_BLUETOOTHData BLUETOOTH_Data;
char  BLUETOOTH_RX_BUF[BLUETOOTH_Buffer_Length]; //接收缓冲,最大BLUETOOTH_Buffer_Length个字节.末字节为换行符 
u8 BLUETOOTH_point2 = 0;
void BLUETOOTH_RecHandle(u8 Res)
{
    
    
	if(Res == '$')
	{
    
    
		BLUETOOTH_point2 = 0;	
	}
	BLUETOOTH_RX_BUF[BLUETOOTH_point2++] = Res;
	if(Res == '@')									   
	{
    
    
		memset(BLUETOOTH_Data.BLUETOOTH_Rec_Buffer, 0, BLUETOOTH_Buffer_Length);      //清空
		memcpy(BLUETOOTH_Data.BLUETOOTH_Rec_Buffer, BLUETOOTH_RX_BUF, BLUETOOTH_point2); 	//保存数据
		BLUETOOTH_Data.isGetData = TRUE; 
		BLUETOOTH_point2 = 0;
		memset(BLUETOOTH_RX_BUF, 0, BLUETOOTH_Buffer_Length);      //清空
	}		
	if(BLUETOOTH_point2 >= BLUETOOTH_Buffer_Length)
	{
    
    
		BLUETOOTH_point2 = BLUETOOTH_Buffer_Length;
	}	
}
void BLUETOOTH_Clear_Data(void)
{
    
    
	BLUETOOTH_Data.isGetData = FALSE;
	BLUETOOTH_Data.isParseData = FALSE;
	BLUETOOTH_Data.isUsefull = FALSE;
	memset(BLUETOOTH_Data.BLUETOOTH_Rec_Buffer, 0, BLUETOOTH_Buffer_Length);      //清空
	
	
	memset(BLUETOOTH_Data.sendMessage, 0, BLUETOOTH_Buffer_Length);      //清空
	memset(BLUETOOTH_Data.userIDchar, 0, BLUETOOTH_IntLength); 
	BLUETOOTH_Data.userIDInt = 0;
}
u8 BLUETOOTH_Find(char *a)                   // 串口命令识别函数
{
    
     
    if(strstr(BLUETOOTH_Data.BLUETOOTH_Rec_Buffer,a)!=NULL)
	    return 1;
	else
		return 0;
}
u16 transform(u8 dat)
{
    
    
	u16 date_shili = 0;
	switch(dat)
	{
    
    
		case 1:date_shili=5;break;
		case 2:date_shili=6;break;
		case 3:date_shili=8;break;
		case 4:date_shili=10;break;
		case 5:date_shili=12;break;
		case 6:date_shili=15;break;
		case 7:date_shili=20;break;
		case 8:date_shili=25;break;
		case 9:date_shili=30;break;
		case 10:date_shili=40;break;
		case 11:date_shili=50;break;
		case 12:date_shili=60;break;
		case 13:date_shili=80;break;
		case 14:date_shili=100;break;
		case 15:date_shili=120;break;
		default:break;
	}
	return date_shili;
}
extern u8 EPROM[10][18]; 
void BLUETOOTH_sendMessage(void)
{
    
    
	u8 i=0;u8 length=0;
	u16 E2ReadNowUserTab[18];
	
	for(i=0;i<18;i++)
	{
    
    
		E2ReadNowUserTab[i] = 0;
	}
	for(i=0;i<18;i++)
	{
    
    
		E2ReadNowUserTab[i] = transform(EPROM[BLUETOOTH_Data.userIDInt-1][i]);
		if(E2ReadNowUserTab[i] == 0)
		{
    
    
			break;
		}		
	}
	if(i==0)
		length = 0;
	else
		length = i;
	
	memset(BLUETOOTH_Data.sendMessage, 0, BLUETOOTH_Buffer_Length);      //清空
	sprintf(BLUETOOTH_Data.sendMessage,
	"$%d,%d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,%03d,@",
	BLUETOOTH_Data.userIDInt,length,E2ReadNowUserTab[0],E2ReadNowUserTab[1],E2ReadNowUserTab[2],
	E2ReadNowUserTab[3],E2ReadNowUserTab[4],E2ReadNowUserTab[5],E2ReadNowUserTab[6],E2ReadNowUserTab[7],
	E2ReadNowUserTab[8],E2ReadNowUserTab[9],E2ReadNowUserTab[10],E2ReadNowUserTab[11],E2ReadNowUserTab[12],
	E2ReadNowUserTab[13],E2ReadNowUserTab[14],E2ReadNowUserTab[15],E2ReadNowUserTab[16],E2ReadNowUserTab[17]
	);
	BLUETOOTH_SendStr(BLUETOOTH_Data.sendMessage);
}
uint16_t CharToInt(char *dat)
{
    
    
	uint16_t date=0;
	
	while((*dat) != '\0')
	{
    
    
		if(((*dat) > 0x30)&&((*dat) <= 0x39))
			date = ((*dat)-0x30) + date*10;
		dat++;
	}
	return date;
}
void parseBLUETOOTHBuffer(void)
{
    
    
	char *str = NULL, *strNext = NULL;
	if (BLUETOOTH_Data.isGetData)  //获得语音模块的数据 --- $1@   : $4@
	{
    
    
		BLUETOOTH_Data.isGetData = FALSE;

		str = strstr(BLUETOOTH_Data.BLUETOOTH_Rec_Buffer,"ID");
		if(str != NULL)  //$ID1@  -  $ID10@
		{
    
    
			BLUETOOTH_Data.isParseData = TRUE;
			BLUETOOTH_Data.isUsefull = TRUE;
			
			str = str+2;
			strNext = strstr(str,"@");
			if(strNext != NULL)
			{
    
    
				memset(BLUETOOTH_Data.userIDchar, 0, BLUETOOTH_IntLength);
				memcpy(BLUETOOTH_Data.userIDchar,str, strNext - str); 
				
//				BLUETOOTH_SendStr(BLUETOOTH_Data.userIDchar);
				
				BLUETOOTH_Data.userIDInt = CharToInt(BLUETOOTH_Data.userIDchar); //1-10
				if(BLUETOOTH_Data.userIDInt > 0 && BLUETOOTH_Data.userIDInt < 11)
				{
    
    
					BLUETOOTH_sendMessage();
				}	
			}							
		}
		else
		{
    
    
//			BLUETOOTH_Clear_Data(); //清空接收到的数据---数据帧无效
		}
	}
}

/*******************参考处理设计,自行添加内容*****************************
void Proc_Bluethooth(void)
{
	parseBLUETOOTHBuffer();
	if(BLUETOOTH_Data.isUsefull == TRUE)
	{
		BLUETOOTH_Data.isUsefull = FALSE;


	}
}
************************************************/




主机无线指令处理

#ifndef __WIRELESS_h
#define __WIRELESS_h

#include "stm32f10x.h"
#include <string.h>
#include <stdio.h>
#include "Def_config.h"

#include "usart3.h" 
#define WIRELESS_SendStr       USART3_SendString 

#define WIRELESS_Buffer_Length 100
#define WIRELESS_Length 50

typedef struct
{
    
    
	char WIRELESS_Rec_Buffer[WIRELESS_Buffer_Length];
	ENUM_JUDGE isGetData;		//是否获取到数据
	ENUM_JUDGE isParseData;	//是否解析完成
	ENUM_JUDGE isUsefull;		//信息是否有效
	
	char SendDire[WIRELESS_Length];
	ENUM_JUDGE isResultRight;
} _WIRELESSData;
extern _WIRELESSData WIRELESS_Data;

void WIRELESS_sendMessage(char *p);
void WIRELESS_RecHandle(u8 Res);

void WIRELESS_Clear_Data(void);

void parseWIRELESSBuffer(void);



#endif 




#include "wireless.h"

_WIRELESSData WIRELESS_Data;
char  WIRELESS_RX_BUF[WIRELESS_Buffer_Length]; //接收缓冲,最大WIRELESS_Buffer_Length个字节.末字节为换行符 
u8 point2 = 0;
void WIRELESS_RecHandle(u8 Res)
{
    
    
	if(Res == '$')
	{
    
    
		point2 = 0;	
	}
	WIRELESS_RX_BUF[point2++] = Res;
	if(Res == '@')									   
	{
    
    
		memset(WIRELESS_Data.WIRELESS_Rec_Buffer, 0, WIRELESS_Buffer_Length);      //清空
		memcpy(WIRELESS_Data.WIRELESS_Rec_Buffer, WIRELESS_RX_BUF, point2); 	//保存数据
		WIRELESS_Data.isGetData = TRUE; 
		point2 = 0;
		memset(WIRELESS_RX_BUF, 0, WIRELESS_Buffer_Length);      //清空
	}		
	if(point2 >= WIRELESS_Buffer_Length)
	{
    
    
		point2 = WIRELESS_Buffer_Length;
	}	
}
void WIRELESS_Clear_Data(void)
{
    
    
	WIRELESS_Data.isGetData = FALSE;
	WIRELESS_Data.isParseData = FALSE;
	WIRELESS_Data.isUsefull = FALSE;
	memset(WIRELESS_Data.WIRELESS_Rec_Buffer, 0, WIRELESS_Buffer_Length);      //清空
	
	memset(WIRELESS_RX_BUF, 0, WIRELESS_Buffer_Length);      //清空

	WIRELESS_Data.isResultRight = FALSE;
	memset(WIRELESS_Data.SendDire, 0, WIRELESS_Length); 	
}
u8 WIRELESS_Find(char *a)                   // 串口命令识别函数
{
    
     
    if(strstr(WIRELESS_Data.WIRELESS_Rec_Buffer,a)!=NULL)
	    return 1;
	else
		return 0;
}
void WIRELESS_sendMessage(char *p)
{
    
    
	WIRELESS_SendStr(p); 
}
void parseWIRELESSBuffer(void)
{
    
    
	if (WIRELESS_Data.isGetData)  //获得模块的数据 --- $D1@   : $D4@
	{
    
    
		WIRELESS_Data.isGetData = FALSE;
		if(WIRELESS_Find("$T@"))
		{
    
    
			WIRELESS_Data.isParseData = TRUE;
			WIRELESS_Data.isUsefull = TRUE;	
			
			WIRELESS_Data.isResultRight = TRUE;
		}
		else if(WIRELESS_Find("$F@"))
		{
    
    
			WIRELESS_Data.isParseData = TRUE;
			WIRELESS_Data.isUsefull = TRUE;	
			
			WIRELESS_Data.isResultRight=FALSE;
		}
		else
		{
    
    
			WIRELESS_Clear_Data(); //清空接收到的数据---数据帧无效
		}
	}
}

/*******************参考处理设计,自行添加内容*****************************
void Proc_Bluethooth(void)
{
	parseWIRELESSBuffer();
	if(WIRELESS_Data.isUsefull == TRUE)
	{
		WIRELESS_Data.isUsefull = FALSE;


	}
}
************************************************/




从机无线模块指令处理

#ifndef __WIRELESS_h
#define __WIRELESS_h

#include "stm32f10x.h"
#include <string.h>
#include <stdio.h>
#include "Def_config.h"

#include "usart2.h" 
#define WIRELESS_SendStr       USART2_SendString 

#define WIRELESS_Buffer_Length 100
#define WIRELESS_Length 50

typedef struct
{
    
    
	char WIRELESS_Rec_Buffer[WIRELESS_Buffer_Length];
	ENUM_JUDGE isGetData;		//是否获取到数据
	ENUM_JUDGE isParseData;	//是否解析完成
	ENUM_JUDGE isUsefull;		//信息是否有效
	
	uint16_t Direction;
} _WIRELESSData;
extern _WIRELESSData WIRELESS_Data;

void WIRELESS_sendMessage(char *p);
void WIRELESS_RecHandle(u8 Res);

void WIRELESS_Clear_Data(void);

void parseWIRELESSBuffer(void);



#endif 




#include "wireless.h"
#include "JQ_8400.h" 

_WIRELESSData WIRELESS_Data;
char  WIRELESS_RX_BUF[WIRELESS_Buffer_Length]; //接收缓冲,最大WIRELESS_Buffer_Length个字节.末字节为换行符 
u8 point2 = 0;
void WIRELESS_RecHandle(u8 Res)
{
    
    
	if(Res == '$')
	{
    
    
		point2 = 0;	
	}
	WIRELESS_RX_BUF[point2++] = Res;
	if(Res == '@')									   
	{
    
    
		memset(WIRELESS_Data.WIRELESS_Rec_Buffer, 0, WIRELESS_Buffer_Length);      //清空
		memcpy(WIRELESS_Data.WIRELESS_Rec_Buffer, WIRELESS_RX_BUF, point2); 	//保存数据
		WIRELESS_Data.isGetData = TRUE; 
		point2 = 0;
		memset(WIRELESS_RX_BUF, 0, WIRELESS_Buffer_Length);      //清空
	}		
	if(point2 >= WIRELESS_Buffer_Length)
	{
    
    
		point2 = WIRELESS_Buffer_Length;
	}	
}
void WIRELESS_Clear_Data(void)
{
    
    
	WIRELESS_Data.isGetData = FALSE;
	WIRELESS_Data.isParseData = FALSE;
	WIRELESS_Data.isUsefull = FALSE;
	memset(WIRELESS_Data.WIRELESS_Rec_Buffer, 0, WIRELESS_Buffer_Length);      //清空
	
	memset(WIRELESS_RX_BUF, 0, WIRELESS_Buffer_Length);      //清空

	WIRELESS_Data.Direction = 0;
}
u8 WIRELESS_Find(char *a)                   // 串口命令识别函数
{
    
     
    if(strstr(WIRELESS_Data.WIRELESS_Rec_Buffer,a)!=NULL)
	    return 1;
	else
		return 0;
}
void WIRELESS_sendMessage(char *p)
{
    
    
	WIRELESS_SendStr(p); 
}
void parseWIRELESSBuffer(void)
{
    
    
	if (WIRELESS_Data.isGetData)  //获得模块的数据 --- $D1@   : $D4@
	{
    
    
		WIRELESS_Data.isGetData = FALSE;
		if(WIRELESS_Find("$D1@"))
		{
    
    
			WIRELESS_Data.isParseData = TRUE;
			WIRELESS_Data.isUsefull = TRUE;	
			
			WIRELESS_Data.Direction = 1;
		}
		else if(WIRELESS_Find("$D2@"))
		{
    
    
			WIRELESS_Data.isParseData = TRUE;
			WIRELESS_Data.isUsefull = TRUE;	
			
			WIRELESS_Data.Direction=2;
		}
		else if(WIRELESS_Find("$D3@"))
		{
    
    
			WIRELESS_Data.isParseData = TRUE;
			WIRELESS_Data.isUsefull = TRUE;	
			
			WIRELESS_Data.Direction =3; //右
		}
		else if(WIRELESS_Find("$D4@"))
		{
    
    
			WIRELESS_Data.isParseData = TRUE;
			WIRELESS_Data.isUsefull = TRUE;	
			
			WIRELESS_Data.Direction = 4;
//			WIRELESS_SendStr("$OK@");
		}
		else if(WIRELESS_Find("$O1@"))
		{
    
    
			WIRELESS_Data.isParseData = TRUE;
			WIRELESS_Data.isUsefull = TRUE;	
			
			JQ8400_6x00SendCmd(SELECTE_PLAY,4);
			WIRELESS_Clear_Data();
		}
		else if(WIRELESS_Find("$O2@"))
		{
    
    
			WIRELESS_Data.isParseData = TRUE;
			WIRELESS_Data.isUsefull = TRUE;	
			
			JQ8400_6x00SendCmd(SELECTE_PLAY,5);
			WIRELESS_Clear_Data();
		}
		else if(WIRELESS_Find("$OK@"))
		{
    
    
			WIRELESS_Data.isParseData = TRUE;
			WIRELESS_Data.isUsefull = TRUE;	
			
			JQ8400_6x00SendCmd(SELECTE_PLAY,6);
			WIRELESS_Clear_Data();
		}
		else
		{
    
    
			WIRELESS_Clear_Data(); //清空接收到的数据---数据帧无效
		}
	}
}

/*******************参考处理设计,自行添加内容*****************************
void Proc_Bluethooth(void)
{
	parseWIRELESSBuffer();
	if(WIRELESS_Data.isUsefull == TRUE)
	{
		WIRELESS_Data.isUsefull = FALSE;


	}
}
************************************************/




语音识别模块

LU-ASR01鹿小班智能语音识别模块是由鹿小班开源电子厂家设计生产的一款高性能语音识别模组。该模块支持天问公司的block软件,是天问ASR主板系列之一,支持以可视化代码积木的方式配置语音指令、设定语音识别提示、串口输出指令信息等。模块扩展了8个输出I/O口用于直接和控制设备相连,且支持DHT11温湿度模块直接采集的特性。该模块支持10米超远距离唤醒功能、超过98%的超高识别准确率。本系统将LU-ASR01语音模块的输出串口TXD连接到了从机的串口3对应的PB11引脚用于接收语音识别后的输出指令。通过LU-ASR01语音识别模块的开发平台设定好语音识别指令词和识别到关键词的串口输出内容,当语音模块接收到测试者的语音并处理解析到对应的指令词后,通过串口向从机输出设定的指令对应数据用于系统的逻辑处理。
在这里插入图片描述
在这里插入图片描述

QT设计蓝牙APP

在此占位,后期有时间整理了再开源。

猜你喜欢

转载自blog.csdn.net/qq_20467929/article/details/126119878