基于STM32设计的语音智能家居系统(微信小程序)
一、前言
1.1 项目介绍
【1】项目功能介绍
随着物联网(IoT)、人工智能(AI)以及智能家居技术的快速发展,人们对于生活品质和家居环境智能化的需求不断提升。传统的家庭管理模式已无法满足现代人追求便捷、舒适和安全生活的需要,而智能语音控制作为新兴的人机交互方式,以其自然、高效的特点深受用户青睐。
当前设计的基于STM32设计的语音智能家居系统,该系统将先进的嵌入式硬件技术与智能语音识别模块相结合,并通过微信小程序实现远程操控,为用户提供一个高度集成且易于使用的智慧家庭解决方案。
在硬件层面,项目选用STM32F103RCT6微控制器作为主控核心,它具有高性能、低功耗以及丰富的外设资源,能够有效处理各种传感器数据并控制各类家用设备。同时,搭载LD3320语音识别模块,使用户可以通过简单的语音指令轻松控制家中的风扇、灯光、窗户、门等设施。
考虑到现代生活节奏快,用户对远程管理的需求日益增长,系统集成了ESP8266 WiFi模块,实现实时数据传输和远程控制功能。用户可通过定制开发的微信小程序随时随地查看家中烟雾、雨滴、光敏、温湿度等多种环境参数,以及各类家电设备的状态,并进行远程开关控制。
本项目还注重了家居环境的安全性和舒适性,具备自动检测及响应功能。当检测到烟雾或火焰时,系统会自动启动相应的防护措施,如开启风扇通风、打开窗户排放有害气体,并发出语音警报提醒用户;在下雨时,系统能自动关闭窗户,确保室内不受雨水侵扰。
项目立足于现代智能家居市场的需求和发展趋势,充分运用物联网、语音识别、无线通信等前沿技术,打造了一款以STM32为核心的全方位、多维度、易操作的语音智能家居系统,有力推动了智慧家庭生活的发展与普及。
方案测试阶段:
【2】设计实现的功能
(1)语音控制功能:
- 通过集成LD3320语音识别模块,系统能够识别并解析用户的语音指令,用户可以通过自然语言命令来控制家中的风扇、卧室灯、阳台灯、客厅灯、窗户和门的开关。
(2)环境监测与自动控制:
- 烟雾检测与报警:采用MQ-2传感器实时监控室内烟雾浓度,当检测到烟雾或可燃气体泄漏时,系统将自动打开风扇和窗户进行通风,并发出语音警报提醒用户。
- 火源探测与预警:具备火焰检测功能,一旦发现火源,立即触发语音警告,发出火警预警信息。
- 温湿度调控:利用DHT11温湿度传感器检测环境温度与湿度,当温度超出预设阈值时,自动开启风扇和窗户降低室内温度。
- 雨滴感应与响应:通过雨滴传感器检测下雨情况,当下雨时系统会自动关闭窗户,并播放语音提示“下雨了,记得收衣服哦”。
(3)光强度感知与智能调节:
- 使用光敏电阻采集环境光线强度,虽然该项目中未明确说明是否根据光照强度进行智能控制,但理论上可以结合此数据实现对灯光亮度的自动化调整。
(4)家居设备远程操控:
- 用户可通过微信小程序实现对家中所有智能家居设备(风扇、卧室灯、阳台灯、客厅灯、窗户、门)的远程开关控制。
(5)实时数据展示与记录:
- 系统配备本地LCD显示屏,实时显示当前检测到的烟雾、雨滴、光敏、温湿度等环境参数的具体数值。
- 所有监测数据及家居设备状态都通过ESP8266-WiFi上传至微信小程序上,用户在手机端就能随时查看和管理。
(6)硬件设施控制:
- SG90舵机用于控制门和窗户的开关动作。
- 28bj48步进电机负责窗帘的开合操作。
- 继电器用来控制风扇的启动与停止。
- LED指示灯分别代表卧室灯、阳台灯、客厅灯的开关状态。
【3】项目硬件模块组成
项目硬件模块组成如下:
(1)主控模块
- 主控芯片:STM32F103RCT6
- 功能:作为整个系统的核心处理器,负责协调各模块间的工作、数据处理和控制命令的执行。
(2)语音识别模块
- 模块型号:LD3320
- 功能:实现对用户语音指令的采集与识别,并将识别结果传输至主控模块进行处理。
(3)无线通信模块
- 模块型号:ESP8266 WiFi模组
- 功能:提供网络连接功能,实现远程控制和数据上传至微信小程序服务器,便于用户通过手机端实时查看并操控家居设备状态。
(4)环境监测模块
- 烟雾检测传感器:MQ-2
- 功能:检测空气中的烟雾浓度和可燃气体含量。
- 雨滴传感器:高低电平输出型
- 功能:检测是否有雨水滴落,判断是否下雨。
- 光敏电阻(光强度检测)
- 功能:感知环境光照强度。
- 温湿度传感器:DHT11
- 功能:实时测量并记录环境温湿度。
(5)家电控制模块
- 舵机:SG90舵机 x 2
- 功能:分别用于控制门和窗户的开关动作。
- 步进电机:28bj48
- 功能:驱动窗帘的开合操作。
- 继电器
- 功能:通过继电器控制风扇的启动与停止。
(6)指示灯模块
- LED指示灯 x 3
- 功能:分别代表卧室灯、阳台灯、客厅灯的状态,显示灯具当前是开启还是关闭。
(7)LCD显示屏
- 功能:实时显示环境监测数据(烟雾、雨滴、光敏、温湿度)以及各家电设备(风扇、灯光、窗户、门)的开关状态。
1.2 设计思路
(1)需求分析与功能定义:
- 根据智能家居应用场景和用户需求,明确系统需要实现的功能模块,包括语音控制、环境监测、自动控制以及远程操控等核心功能。
(2)硬件选型与架构设计:
- 核心处理器选用STM32F103作为主控芯片,具备足够的处理能力和丰富的接口资源以满足系统的复杂性要求。
- 语音识别模块采用LD3320,集成到系统中用于接收用户的语音指令并进行本地解析。
- 环境监测方面选择MQ-2烟雾传感器、雨滴传感器、光敏电阻和DHT11温湿度传感器来实时监测家庭环境状况。
- 家电控制部分利用SG90舵机控制门窗开关,28bj48步进电机控制窗帘开合,并通过继电器控制风扇启停。
- LED指示灯用来直观反馈卧室灯、阳台灯、客厅灯的状态。
- 无线通信模块使用ESP8266 WiFi模组,实现与微信小程序的实时数据交互。
(3)软件设计与算法开发:
- 开发嵌入式程序,对接各硬件模块驱动,确保设备间有效通讯和控制。
- 设计语音识别算法和命令解析逻辑,将用户的语音指令转化为具体的执行动作。
- 实现环境参数阈值判断算法,当检测数值超过设定范围时,触发相应的自动控制机制,如开启风扇、窗户,发出报警信息等。
- 开发微信小程序端应用程序,实现远程查看和控制家居设备状态,并实时接收来自STM32的数据更新。
(4)系统集成与调试优化:
- 将各个硬件模块和软件组件进行集成测试,确保所有功能都能稳定可靠地运行。
- 调整和完善系统响应速度、准确性及用户体验,对环境适应性和故障恢复机制进行充分验证。
(5)部署与应用:
- 完成整个系统的设计与调试后,将其部署至实际的家庭环境中,让用户可以便捷地通过语音指令或微信小程序远程控制家居设备,同时享受自动化的环境监控与智能调控服务。
1.3 系统功能总结
项目总结 |
---|
硬件支持 |
主控芯片 |
语音识别模块 |
WiFi模块 |
环境监测模块 |
- 烟雾检测 |
- 雨滴检测 |
- 光敏检测 |
- 温湿度检测 |
家电控制模块 |
- 舵机1 |
- 舵机2 |
- 步进电机 |
- 继电器 |
显示指示模块 |
控制方式 |
---|
语音控制 |
微信小程序远程控制 |
功能实现 |
---|
本地LCD显示屏显示 |
自动控制功能 |
- 烟雾警报与处理 |
- 火焰警报 |
- 温度调节 |
- 雨滴感应响应 |
数据上传与远程查看 |
1.4 开发工具的选择
STM32的编程语言选择C语言,C语言执行效率高,大学里主学的C语言,C语言编译出来的可执行文件最接近于机器码,汇编语言执行效率最高,但是汇编的移植性比较差,目前在一些操作系统内核里还有一些低配的单片机使用的较多,平常的单片机编程还是以C语言为主。C语言的执行效率仅次于汇编,语法理解简单、代码通用性强,也支持跨平台,在嵌入式底层、单片机编程里用的非常多,当前的设计就是采用C语言开发。
开发工具选择Keil,keil是一家世界领先的嵌入式微控制器软件开发商,在2015年,keil被ARM公司收购。因为当前芯片选择的是STM32F103系列,STMF103是属于ARM公司的芯片构架、Cortex-M3内核系列的芯片,所以使用Kile来开发STM32是有先天优势的,而keil在各大高校使用的也非常多,很多教科书里都是以keil来教学,开发51单片机、STM32单片机等等。目前作为MCU芯片开发的软件也不只是keil一家独大,IAR在MCU微处理器开发领域里也使用的非常多,IAR扩展性更强,也支持STM32开发,也支持其他芯片,比如:CC2530,51单片机的开发。从软件的使用上来讲,IAR比keil更加简洁,功能相对少一些。如果之前使用过keil,而且使用频率较多,已经习惯再使用IAR是有点不适应界面的。
二、硬件选型
【1】STM32开发板
主控CPU采用STM32F103RCT6,这颗芯片包括48 KB SRAM、256 KB Flash、2个基本定时器、4个通用定时器、2个高级定时器、51个通用IO口、5个串口、2个DMA控制器、3个SPI、2个I2C、1个USB、1个CAN、3个12位ADC、1个12位DAC、1个SDIO接口,芯片属于大容量类型,配置较高,整体符合硬件选型设计。当前选择的这款开发板自带了一个1.4寸的TFT-LCD彩屏,可以显示当前传感器数据以及一些运行状态信息。
【2】USB下载线
【3】PCB洞洞板
链接:
【4】语音识别模块: LD3320
链接:https://detail.tmall.com/item.htm?spm=a230r.1.14.16.3ae126f3iyJq5n&id=41365254224&ns=1&abbucket=14
【5】ESP8266 -串口WIFI
【6】3W大功率LED灯(3颗)
链接:https://detail.tmall.com/item.htm?id=536336613714&spm=a1z09.2.0.0.43332e8dOm1vox&_u=k1pq7ueo7540
【7】步进电机模块
【8】继电器模块
【9】温湿度-DHT11
【10】BH1750光敏传感器
链接:https://m.tb.cn/h.fKJqLkE?tk=hKa02iyZAPK
【11】杜邦线(2排)
【12】舵机SG90
三、微信小程序设计
下一章介绍。
四、LD3320语音识别模块编程
下载程序示例。 将开发板的串口通过USB转TTL模块连接电脑即可。
波特率是9600,语音识别时,想要说小杰
,唤醒语音识别,然后再说出指令,唤醒语音识别就,模块上有一个红色的LED灯会亮。
当前支持的指令如下:
小杰,开卧室灯
小杰,关卧室灯
小杰,开客厅灯
小杰,关客厅灯
小杰,打开电视
小杰,关闭电视
小杰,打开风扇
小杰,关闭风扇
小杰,打开窗帘
小杰,关闭窗帘
小杰,打开空调
小杰,关闭空调
五、STM32开发
【1】SG90舵机
#include "stm32f10x.h"
#define PWM_FREQ 50 // 设置PWM信号频率为50Hz
#define SERVO_MIN_PULSE_WIDTH 500 // 舵机最小脉宽500us
#define SERVO_MAX_PULSE_WIDTH 2500 // 舵机最大脉宽2500us
void delay_us(uint32_t us) {
uint32_t count = us * (SystemCoreClock / 1000000) / 9;
while(count--);
}
void servo_rotate(uint16_t pulse_width) {
GPIO_SetBits(GPIOB, GPIO_Pin_5); // 设置PB5输出高电平
delay_us(pulse_width); // 延时等待脉宽结束
GPIO_ResetBits(GPIOB, GPIO_Pin_5); // 设置PB5输出低电平
delay_us(20000 - pulse_width); // 延时保持50Hz的PWM周期
}
int main(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // 使能GPIOB时钟
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; // PB5口
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 最大输出频率为50Mhz
GPIO_Init(GPIOB, &GPIO_InitStructure);
while(1) {
// 控制舵机正向旋转360°
for (int i = SERVO_MIN_PULSE_WIDTH; i <= SERVO_MAX_PULSE_WIDTH; i += 10) {
servo_rotate(i);
}
for (int i = SERVO_MAX_PULSE_WIDTH; i >= SERVO_MIN_PULSE_WIDTH; i -= 10) {
servo_rotate(i);
}
// 控制舵机反向旋转360°
for (int i = SERVO_MAX_PULSE_WIDTH; i >= SERVO_MIN_PULSE_WIDTH; i -= 10) {
servo_rotate(i);
}
for (int i = SERVO_MIN_PULSE_WIDTH; i <= SERVO_MAX_PULSE_WIDTH; i += 10) {
servo_rotate(i);
}
}
}
【2】LD3320语音识别模块
/*******************************************************
** CPU: STC11L08XE
** 晶振:22.1184MHZ
** 波特率:9600 bit/S
** 口令模式: 即每次识别时都需要说“小杰”这个口令 ,才能够进行下一级的识别
/*********************************************************/
#include "config.h"
extern void delay(unsigned long uldata);
uint8 idata ucRegVal;
extern uint8 idata nAsrStatus;
void ProcessInt0(void);
/************************************************************************
功能描述: 复位LD模块
入口参数: none
返 回 值: none
其他说明: none
**************************************************************************/
void LD_Reset()
{
RSTB=1;
delay(5);
RSTB=0;
delay(5);
RSTB=1;
delay(5);
CSB=0;
delay(5);
CSB=1;
delay(5);
}
/************************************************************************
功能描述: LD模块命令初始化
入口参数: none
返 回 值: none
其他说明: 该函数为出厂配置,一般不需要修改;
有兴趣的客户可对照开发手册根据需要自行修改。
**************************************************************************/
void LD_Init_Common()
{
LD_ReadReg(0x06);
LD_WriteReg(0x17, 0x35);
delay(10);
LD_ReadReg(0x06);
LD_WriteReg(0x89, 0x03);
delay(5);
LD_WriteReg(0xCF, 0x43);
delay(5);
LD_WriteReg(0xCB, 0x02);
/*PLL setting*/
LD_WriteReg(0x11, LD_PLL_11);
LD_WriteReg(0x1E,0x00);
LD_WriteReg(0x19, LD_PLL_ASR_19);
LD_WriteReg(0x1B, LD_PLL_ASR_1B);
LD_WriteReg(0x1D, LD_PLL_ASR_1D);
delay(10);
LD_WriteReg(0xCD, 0x04);
// LD_WriteReg(0x17, 0x4c);
delay(5);
LD_WriteReg(0xB9, 0x00);
LD_WriteReg(0xCF, 0x4F);
LD_WriteReg(0x6F, 0xFF);
}
/************************************************************************
功能描述: LD模块 ASR功能初始化
入口参数: none
返 回 值: none
其他说明: 该函数为出厂配置,一般不需要修改;
有兴趣的客户可对照开发手册根据需要自行修改。
**************************************************************************/
void LD_Init_ASR()
{
LD_Init_Common();
LD_WriteReg(0xBD, 0x00);
LD_WriteReg(0x17, 0x48);
delay( 10 );
LD_WriteReg(0x3C, 0x80);
LD_WriteReg(0x3E, 0x07);
LD_WriteReg(0x38, 0xff);
LD_WriteReg(0x3A, 0x07);
LD_WriteReg(0x40, 0);
LD_WriteReg(0x42, 8);
LD_WriteReg(0x44, 0);
LD_WriteReg(0x46, 8);
delay( 1 );
}
/************************************************************************
功能描述: 中断处理函数
入口参数: none
返 回 值: none
其他说明: 当LD模块接收到音频信号时,将进入该函数,
判断识别是否有结果,如果没有从新配置寄
存器准备下一次的识别。
**************************************************************************/
void ProcessInt0(void)
{
uint8 nAsrResCount=0;
EX0=0;
ucRegVal = LD_ReadReg(0x2B);
LD_WriteReg(0x29,0) ;
LD_WriteReg(0x02,0) ;
if((ucRegVal & 0x10) &&
LD_ReadReg(0xb2)==0x21 &&
LD_ReadReg(0xbf)==0x35) /*识别成功*/
{
nAsrResCount = LD_ReadReg(0xba);
if(nAsrResCount>0 && nAsrResCount<=4)
{
nAsrStatus=LD_ASR_FOUNDOK;
}
else
{
nAsrStatus=LD_ASR_FOUNDZERO;
}
} /*没有识别结果*/
else
{
nAsrStatus=LD_ASR_FOUNDZERO;
}
LD_WriteReg(0x2b, 0);
LD_WriteReg(0x1C,0);/*写0:ADC不可用*/
LD_WriteReg(0x29,0) ;
LD_WriteReg(0x02,0) ;
LD_WriteReg(0x2B, 0);
LD_WriteReg(0xBA, 0);
LD_WriteReg(0xBC,0);
LD_WriteReg(0x08,1); /*清除FIFO_DATA*/
LD_WriteReg(0x08,0); /*清除FIFO_DATA后 再次写0*/
EX0=1;
}
/************************************************************************
功能描述: 运行ASR识别流程
入口参数: none
返 回 值: asrflag:1->启动成功, 0—>启动失败
其他说明: 识别顺序如下:
1、RunASR()函数实现了一次完整的ASR语音识别流程
2、LD_AsrStart() 函数实现了ASR初始化
3、LD_AsrAddFixed() 函数实现了添加关键词语到LD3320芯片中
4、LD_AsrRun() 函数启动了一次ASR语音识别流程
任何一次ASR识别流程,都需要按照这个顺序,从初始化开始
**************************************************************************/
uint8 RunASR(void)
{
uint8 i=0;
uint8 asrflag=0;
for (i=0; i<5; i++) // 防止由于硬件原因导致LD3320芯片工作不正常,所以一共尝试5次启动ASR识别流程
{
LD_AsrStart();
delay(50);
if (LD_AsrAddFixed()==0)
{
LD_Reset(); // LD3320芯片内部出现不正常,立即重启LD3320芯片
delay(50); // 并从初始化开始重新ASR识别流程
continue;
}
delay(10);
if (LD_AsrRun() == 0)
{
LD_Reset(); // LD3320芯片内部出现不正常,立即重启LD3320芯片
delay(50); // 并从初始化开始重新ASR识别流程
continue;
}
asrflag=1;
break; // ASR流程启动成功,退出当前for循环。开始等待LD3320送出的中断信号
}
return asrflag;
}
/************************************************************************
功能描述: 检测LD模块是否空闲
入口参数: none
返 回 值: flag:1-> 空闲
其他说明: none
**************************************************************************/
uint8 LD_Check_ASRBusyFlag_b2()
{
uint8 j;
uint8 flag = 0;
for (j=0; j<10; j++)
{
if (LD_ReadReg(0xb2) == 0x21)
{
flag = 1;
break;
}
delay(10);
}
return flag;
}
/************************************************************************
功能描述: 启动ASR
入口参数: none
返 回 值: none
其他说明: none
**************************************************************************/
void LD_AsrStart()
{
LD_Init_ASR();
}
/************************************************************************
功能描述: 运行ASR
入口参数: none
返 回 值: 1:启动成功
其他说明: none
**************************************************************************/
uint8 LD_AsrRun()
{
EX0=0;
LD_WriteReg(0x35, MIC_VOL);
LD_WriteReg(0x1C, 0x09);
LD_WriteReg(0xBD, 0x20);
LD_WriteReg(0x08, 0x01);
delay( 1 );
LD_WriteReg(0x08, 0x00);
delay( 1 );
if(LD_Check_ASRBusyFlag_b2() == 0)
{
return 0;
}
// LD_WriteReg(0xB6, 0xa); //识别时间 1S
// LD_WriteReg(0xB5, 0x1E); //背景音段时间 300ms
// LD_WriteReg(0xB8, 10); //结束时间
// LD_WriteReg(0x1C, 0x07); //配置双通道音频信号做为输入信号
LD_WriteReg(0x1C, 0x0b); //配置麦克风做为输入信号
LD_WriteReg(0xB2, 0xff);
delay( 1);
LD_WriteReg(0x37, 0x06);
delay( 1 );
LD_WriteReg(0x37, 0x06);
delay( 5 );
LD_WriteReg(0x29, 0x10);
LD_WriteReg(0xBD, 0x00);
EX0=1;
return 1;
}
/************************************************************************
功能描述: 向LD模块添加关键词
入口参数: none
返 回 值: flag:1->添加成功
其他说明: 用户修改.
1、根据如下格式添加拼音关键词,同时注意修改sRecog 和pCode 数组的长度
和对应变了k的循环置。拼音串和识别码是一一对应的。
2、开发者可以学习"语音识别芯片LD3320高阶秘籍.pdf"中
关于垃圾词语吸收错误的用法,来提供识别效果。
3、”xiao jie “ 为口令,故在每次识别时,必须先发一级口令“小捷”
**************************************************************************/
uint8 LD_AsrAddFixed()
{
uint8 k, flag;
uint8 nAsrAddLength;
#define DATE_A 50 /*数组二维数值*/
#define DATE_B 20 /*数组一维数值*/
uint8 code sRecog[DATE_A][DATE_B] =
{
"xiao jie",\
"kai wo shi deng",\
"guan wo shi deng",\
"kai ke ting deng",\
"guan ke ting deng",\
"da kai dian shi",\
"guan bi dian shi",\
"da kai feng shan",\
"guan bi feng shan",\
"da kai chuang lian",\
"guan bi chuang lian",\
"da kai kong tiao",\
"guan bi kong tiao",\
"quan bu da kai",\
"quan bu guan bi",\
}; /*添加关键词,用户修改*/
uint8 code pCode[DATE_A] =
{
CODE_CMD, \
CODE_1, \
CODE_2, \
CODE_3, \
CODE_4, \
CODE_5, \
CODE_6, \
CODE_7, \
CODE_8, \
CODE_9, \
CODE_10, \
CODE_11, \
CODE_12, \
CODE_13, \
CODE_14, \
CODE_15, \
CODE_16, \
CODE_17, \
CODE_18, \
CODE_19, \
CODE_20, \
CODE_21, \
CODE_22, \
CODE_23, \
CODE_24, \
CODE_25, \
CODE_26, \
CODE_27, \
CODE_28, \
CODE_29, \
CODE_30, \
CODE_31, \
CODE_32, \
CODE_33, \
CODE_34, \
CODE_35, \
CODE_36, \
CODE_37, \
CODE_38, \
CODE_39, \
CODE_40, \
CODE_41, \
CODE_42, \
CODE_43, \
CODE_44, \
CODE_45, \
CODE_46, \
CODE_47, \
CODE_48, \
CODE_49, \
}; /*添加识别码,用户修改*/
flag = 1;
for (k=0; k<DATE_A; k++)
{
if(LD_Check_ASRBusyFlag_b2() == 0)
{
flag = 0;
break;
}
LD_WriteReg(0xc1, pCode[k] );
LD_WriteReg(0xc3, 0 );
LD_WriteReg(0x08, 0x04);
delay(1);
LD_WriteReg(0x08, 0x00);
delay(1);
for (nAsrAddLength=0; nAsrAddLength<DATE_B; nAsrAddLength++)
{
if (sRecog[k][nAsrAddLength] == 0)
break;
LD_WriteReg(0x5, sRecog[k][nAsrAddLength]);
}
LD_WriteReg(0xb9, nAsrAddLength);
LD_WriteReg(0xb2, 0xff);
LD_WriteReg(0x37, 0x04);
}
return flag;
}
/************************************************************************
功能描述: 获取识别结果
入口参数: none
返 回 值: LD_ReadReg(0xc5 ); 读取内部寄存器返回识别码。
其他说明: none
**************************************************************************/
uint8 LD_GetResult()
{
return LD_ReadReg(0xc5 );
}
【3】LD3320串口配置
#include "config.h"
#define FOSC 22118400L //System frequency
uint32_t baud=9600; //UART baudrate
uint8_t RX_BUF[50];
uint8_t NUM_1=0;
/************************************************************************
函 数 名: 串口初始化
功能描述: STC10L08XE 单片机串口初始化函数
返回函数: none
其他说明: none
**************************************************************************/
void UartIni(void)
{
SCON = 0x50; //8-bit variable UART
TMOD = 0x20; //Set Timer1 as 8-bit auto reload mode
TH1 = TL1 = -(FOSC/12/32/baud); //Set auto-reload vaule
TR1 = 1; //Timer1 start run
ES = 1; //Enable UART interrupt
EA = 1; //Open master interrupt switch
}
/************************************************************************
功能描述: 串口发送一字节数据
入口参数: DAT:带发送的数据
返 回 值: none
其他说明: none
**************************************************************************/
void UARTSendByte(uint8_t DAT)
{
ES = 0;
TI=0;
SBUF = DAT;
while(TI==0);
TI=0;
ES = 1;
}
/************************************************************************
功能描述: 串口发送字符串数据
入口参数: *DAT:字符串指针
返 回 值: none
其他说明: API 供外部使用,直观!
**************************************************************************/
void PrintCom(uint8_t *DAT)
{
while(*DAT)
{
UARTSendByte(*DAT++);
}
}
void Uart_Isr() interrupt 4 using 1
{
if (RI)
{
RI=0;
RX_BUF[NUM_1]=SBUF;
NUM_1++;
if(NUM_1>=49)
NUM_1=0;
if(NUM_1>=3)
{
if(RX_BUF[NUM_1]==0xF8&&RX_BUF[NUM_1-1]==0xF8&&RX_BUF[NUM_1-2]==0xF8)
IAP_CONTR=0x60;
}
}
}
【4】LD3320主函数代码
/*******************************************************
** CPU: STC11L08XE
** 晶振:22.1184MHZ
** 波特率:9600 bit/S
** 口令模式: 即每次识别时都需要说“小杰”这个口令 ,才能够进行下一级的识别
/*********************************************************/
#include "config.h"
/************************************************************************************/
// nAsrStatus 用来在main主程序中表示程序运行的状态,不是LD3320芯片内部的状态寄存器
// LD_ASR_NONE: 表示没有在作ASR识别
// LD_ASR_RUNING: 表示LD3320正在作ASR识别中
// LD_ASR_FOUNDOK: 表示一次识别流程结束后,有一个识别结果
// LD_ASR_FOUNDZERO: 表示一次识别流程结束后,没有识别结果
// LD_ASR_ERROR: 表示一次识别流程中LD3320芯片内部出现不正确的状态
/***********************************************************************************/
uint8 idata nAsrStatus = 0;
void MCU_init();
void ProcessInt0(); //识别处理函数
void delay(unsigned long uldata);
void User_handle(uint8 dat);//用户执行操作函数
void Delay200ms();
void Led_test(void);//单片机工作指示
uint8_t G0_flag = DISABLE; //运行标志,ENABLE:运行。DISABLE:禁止运行
sbit LED = P4 ^ 2; //信号指示灯
sbit SRD1 = P1 ^ 7;
sbit SRD2 = P1 ^ 6;
sbit SRD3 = P1 ^ 5;
sbit SRD4 = P1 ^ 4;
/***********************************************************
* 名 称: void main(void)
* 功 能: 主函数 程序入口
* 入口参数:
* 出口参数:
* 说 明:
* 调用方法:
**********************************************************/
void main(void)
{
uint8 idata nAsrRes;
uint8 i = 0;
P1M0 = 0xFF;
P1M1 = 0x00;
SRD1 = SRD2 = SRD3 = SRD4 = 0;
Led_test();
MCU_init();
LD_Reset();
UartIni(); /*串口初始化*/
nAsrStatus = LD_ASR_NONE; // 初始状态:没有在作ASR
PrintCom("<G>大家好-我是DS小龙哥");
while(1)
{
switch(nAsrStatus)
{
case LD_ASR_RUNING:
case LD_ASR_ERROR:
break;
case LD_ASR_NONE:
{
nAsrStatus = LD_ASR_RUNING;
if (RunASR() == 0) /* 启动一次ASR识别流程:ASR初始化,ASR添加关键词语,启动ASR运算*/
{
nAsrStatus = LD_ASR_ERROR;
}
break;
}
case LD_ASR_FOUNDOK: /* 一次ASR识别流程结束,去取ASR识别结果*/
{
nAsrRes = LD_GetResult(); /*获取结果*/
User_handle(nAsrRes);//用户执行函数
nAsrStatus = LD_ASR_NONE;
break;
}
case LD_ASR_FOUNDZERO:
default:
{
nAsrStatus = LD_ASR_NONE;
break;
}
}// switch
}// while
}
/***********************************************************
* 名 称: LED灯测试
* 功 能: 单片机是否工作指示
* 入口参数: 无
* 出口参数:无
* 说 明:
**********************************************************/
void Led_test(void)
{
LED = ~ LED;
Delay200ms();
LED = ~ LED;
Delay200ms();
LED = ~ LED;
Delay200ms();
LED = ~ LED;
Delay200ms();
LED = ~ LED;
Delay200ms();
LED = ~ LED;
}
/***********************************************************
* 名 称: void MCU_init()
* 功 能: 单片机初始化
* 入口参数:
* 出口参数:
* 说 明:
* 调用方法:
**********************************************************/
void MCU_init()
{
P0 = 0xff;
P1 = 0x00;
P2 = 0xff;
P3 = 0xff;
P4 = 0xff;
AUXR &= 0x7F; //定时器时钟12T模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0x00; //设置定时初值
TH0 = 0x28; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;
LD_MODE = 0; // 设置MD管脚为低,并行模式读写
IE0 = 1;
EX0 = 1;
EA = 1;
WDT_CONTR = 0x3D;
}
/***********************************************************
* 名 称: 延时函数
* 功 能:
* 入口参数:
* 出口参数:
* 说 明:
* 调用方法:
**********************************************************/
void Delay200us() //@22.1184MHz
{
unsigned char i, j;
_nop_();
_nop_();
i = 5;
j = 73;
do
{
while (--j);
}
while (--i);
}
void delay(unsigned long uldata)
{
unsigned int j = 0;
unsigned int g = 0;
while(uldata--)
Delay200us();
}
void Delay200ms() //@22.1184MHz
{
unsigned char i, j, k;
i = 17;
j = 208;
k = 27;
do
{
do
{
while (--k);
}
while (--j);
}
while (--i);
}
/***********************************************************
* 名 称: 中断处理函数
* 功 能:
* 入口参数:
* 出口参数:
* 说 明:
* 调用方法:
**********************************************************/
void ExtInt0Handler(void) interrupt 0
{
ProcessInt0();
}
/***********************************************************
* 名 称:用户执行函数
* 功 能:识别成功后,执行动作可在此进行修改
* 入口参数: 无
* 出口参数:无
* 说 明:
**********************************************************/
void User_handle(uint8 dat)
{
if(0 == dat)
{
G0_flag = ENABLE;
PrintCom("<G>你好,主人");
LED = 0;
}
else if(ENABLE == G0_flag)
{
G0_flag = DISABLE;
LED = 1;
switch(dat)
{
case CODE_1: /*命令“开灯”*/
SRD1 = 1;
PrintCom("<G>卧室灯已打开");
break;
case CODE_2: /*命令“关灯”*/
SRD1 = 0;
PrintCom("<G>卧室灯已关闭\r\n");
break;
case CODE_3: /*命令“打开电视”*/
SRD2 = 1;
PrintCom("<G>客厅灯已打开\r\n");
break;
case CODE_4: /*命令“关闭电视”*/
SRD2 = 0;
PrintCom("<G>客厅灯已关闭\r\n");
break;
case CODE_5: /*命令“打开冰箱”*/
SRD3 = 1;
PrintCom("<G>电视机已打开\r\n");
break;
case CODE_6: /*命令“关闭冰箱”*/
SRD3 = 0;
PrintCom("<G>电视机已关闭\r\n");
break;
case CODE_7: /*命令“打开空调”*/
SRD4 = 1;
PrintCom("<G>风扇已打开\r\n");
break;
case CODE_8: /*命令“关闭空调”*/
SRD4 = 0;
PrintCom("<G>风扇已关闭\r\n");
break;
case CODE_9: /*命令“全部打开”*/
PrintCom("<G>窗帘已打开\r\n");
// SRD1 = 1;
// SRD2 = 1;
// SRD3 = 1;
// SRD4 = 1;
// PrintCom("<G>已全部打开\r\n");
break;
case CODE_10: /*命令“全部关闭”*/
PrintCom("<G>窗帘已关闭\r\n");
// SRD1 = 0;
// SRD2 = 0;
// SRD3 = 0;
// SRD4 = 0;
// PrintCom("<G>已全部关闭\r\n");
break;
case CODE_11: /*命令“.....”*/
PrintCom("<G>空调已打开\r\n");
break;
case CODE_12: /*命令“.....”*/
PrintCom("<G>空调已关闭\r\n");
break;
case CODE_13: /*命令“.....”*/
PrintCom("<G>全部打开\r\n");
break;
case CODE_14: /*命令“.....”*/
PrintCom("<G>全部关闭\r\n");
break;
case CODE_15: /*命令“.....”*/
PrintCom("");
break;
case CODE_16: /*命令“.....”*/
PrintCom("");
break;
case CODE_17: /*命令“.....”*/
PrintCom("");
break;
case CODE_18: /*命令“.....”*/
PrintCom("");
break;
case CODE_19: /*命令“.....”*/
PrintCom("");
break;
case CODE_20: /*命令“.....”*/
PrintCom("");
break;
case CODE_21: /*命令“.....”*/
PrintCom("");
break;
case CODE_22: /*命令“.....”*/
PrintCom("");
break;
case CODE_23: /*命令“.....”*/
PrintCom("");
break;
case CODE_24: /*命令“.....”*/
PrintCom("");
break;
case CODE_25: /*命令“.....”*/
PrintCom("");
break;
case CODE_26: /*命令“.....”*/
PrintCom("");
break;
case CODE_27: /*命令“.....”*/
PrintCom("");
break;
case CODE_28: /*命令“.....”*/
PrintCom("");
break;
case CODE_29: /*命令“.....”*/
PrintCom("");
break;
case CODE_30: /*命令“.....”*/
PrintCom("");
break;
case CODE_31: /*命令“.....”*/
PrintCom("");
break;
case CODE_32: /*命令“.....”*/
PrintCom("");
break;
case CODE_33: /*命令“.....”*/
PrintCom("");
break;
case CODE_34: /*命令“.....”*/
PrintCom("");
break;
case CODE_35: /*命令“.....”*/
PrintCom("");
break;
case CODE_36: /*命令“.....”*/
PrintCom("");
break;
case CODE_37: /*命令“.....”*/
PrintCom("");
break;
case CODE_38: /*命令“.....”*/
PrintCom("");
break;
case CODE_39: /*命令“.....”*/
PrintCom("");
break;
case CODE_40: /*命令“.....”*/
PrintCom("");
break;
case CODE_41: /*命令“.....”*/
PrintCom("");
break;
case CODE_42: /*命令“.....”*/
PrintCom("");
break;
case CODE_43: /*命令“.....”*/
PrintCom("");
break;
case CODE_44: /*命令“.....”*/
PrintCom("");
break;
case CODE_45: /*命令“.....”*/
PrintCom("");
break;
case CODE_46: /*命令“.....”*/
PrintCom("");
break;
case CODE_47: /*命令“.....”*/
PrintCom("");
break;
case CODE_48: /*命令“.....”*/
PrintCom("");
break;
case CODE_49: /*命令“.....”*/
PrintCom("");
break;
default:/*text.....*/
break;
}
}
else
{
//PrintCom("请说出一级口令\r\n"); /*text.....*/
}
}
void tm0_isr() interrupt 1
{
TL0 = 0x00; //设置定时初值
TH0 = 0x28; //设置定时初值
WDT_CONTR=0x3D;
}
- 点赞
- 收藏
- 关注作者
评论(0)