丈夫欲遂平生志,一载寒窗一举汤。这篇文章主要讲述#yyds干货盘点#基于CC2530设计的智能风扇相关的知识,希望能为你提供帮助。
1. 项目介绍随着空调降温设备的频繁使用,全球气候不断变暖空调降温设备排放出的物质对环境的影响越来越大。二是人们在熟睡之后经常因为温度太低而感冒或者温度升高而不适,风扇相比空调更加适用于老人儿童和体质较弱的人使用。
通过物联网技术的智能风扇设计可以解决因为睡熟导致降温设备依旧运行工作,实现更加节能更加智能的控制。
通过温度传感器对环境温度进行数据采集和语音控制模块来调节风速实现对风扇的智能控制,使风扇随温度变化来自动调节风力大小。
具体实现功能如下:
- 实现语音控制,可以识别到语音命令并自动做出相应的工作;
- 实现温度实时监测;
- 实现通过实时温度来自动控制风扇转速;
- 实现通电后可以进行风扇的开光和转数调节:
采用DHT11温湿度传感器,采集环境温度,根据设置的温度阀值与采集的环境温度做对比,控制风扇的开关,也可以通过语音识别模块检测语音完成语音控制。
实现的功能总结如下:
- 按下开发板上的按键控制风扇的开关(LED灯的开关)
- 通过语音控制风扇的开关(LED灯的开关)
语音由语音模块进行识别。 - 在主函数里每500ms采集一次DHT11温度,然后通过OLED显示屏显示。
文章图片
2. 硬件介绍 2.1 OLED显示屏
OLED采用0.96寸的SPI接口显示屏。分辨率是128x64.
具体接线如下:
#define LCD_SCLP1_2//SCLK时钟 D0(SCLK)
#define LCD_SDAP1_3//SDAD1(MOSI) 数据
#define LCD_RSTP1_7//_REShardware reset复位
#define LCD_DCP0_0//A0H/L 命令数据选通端,H:数据,L:命令
VCC接3.3V
GND接GND
文章图片
2.2DHT11温湿度传感器
DHT11是单总线数字温湿度传感器,电压兼容3v~5v,单片机可以直接IO口连接模拟时序完成数据读取。
具体接线如下:
DATA接在P0_7口
VCC接3.3V
GND接GND
文章图片
2.3 语音模块
语音模块采用LD3320芯片进行识别,可以设置内部识别的词条,支持二次开发编程。
默认内置的识别词条如下:
文章图片
下面是语音识别模块的实物图:
文章图片
文章图片
文章图片
文章图片
文章图片
文章图片
文章图片
【#yyds干货盘点#基于CC2530设计的智能风扇】
文章图片
3. 案例代码 3.1 语音识别模块代码
/*******************************************************
**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;
/***********************************************************
* 名称: voidmain(void)
* 功能: 主函数程序入口
* 入口参数:
* 出口参数:
* 说明:
* 调用方法:
**********************************************************/
voidmain(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>
欢迎使用");
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.1184MHzunsigned char i, j;
_nop_();
_nop_();
i = 5;
j = 73;
dowhile (--j);
while (--i);
voiddelay(unsigned long uldata)unsigned int j=0;
unsigned int g=0;
while(uldata--)
Delay200us();
void Delay200ms()//@22.1184MHzunsigned char i, j, k;
i = 17;
j = 208;
k = 27;
dodowhile (--k);
while (--j);
while (--i);
/***********************************************************
* 名称: 中断处理函数
* 功能:
* 入口参数:
* 出口参数:
* 说明:
* 调用方法:
**********************************************************/
void ExtInt0Handler(void) interrupt 0ProcessInt0();
/***********************************************************
* 名称:用户执行函数
* 功能:识别成功后,执行动作可在此进行修改
* 入口参数: 无
* 出口参数:无
* 说明:
**********************************************************/
voidUser_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:/*命令“全部打开”*/
SRD1 = 1;
SRD2 = 1;
SRD3 = 1;
SRD4 = 1;
PrintCom("<
G>
已全部打开\\r\\n");
break;
case CODE_10:/*命令“全部关闭”*/
SRD1 = 0;
SRD2 = 0;
SRD3 = 0;
SRD4 = 0;
PrintCom("<
G>
已全部关闭\\r\\n");
break;
case CODE_11:/*命令“.....”*/PrintCom("");
break;
case CODE_12:/*命令“.....”*/PrintCom("");
break;
case CODE_13:/*命令“.....”*/PrintCom("");
break;
case CODE_14:/*命令“.....”*/PrintCom("");
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 1TL0 = 0x00;
//设置定时初值
TH0 = 0x28;
//设置定时初值
WDT_CONTR=0x3D;
3.2 cc2530串口代码
#include "uart.h"
/*
函数功能:串口0初始化
*/
void Init_Uart0(void)PERCFG&
=~(1<
<
0);
//串口0的引脚映射到位置1,即P0_2和P0_3
P0SEL|=0x3<
<
2;
//将P0_2和P0_3端口设置成外设功能
U0BAUD = 216;
//32MHz的系统时钟产生115200BPS的波特率
U0GCR&
=~(0x1F<
<
0);
//清空波特率指数
U0GCR|=11<
<
0;
//32MHz的系统时钟产生115200BPS的波特率
U0UCR |= 0x80;
//禁止流控,8位数据,清除缓冲器
U0CSR |= 0x3<
<
6;
//选择UART模式,使能接收器/*
函数功能:UART0发送字符串函数
*/
void UR0SendString(char *str) while(*str!=\\0)U0DBUF = *str;
//将要发送的1字节数据写入U0DBUF
while(UTX0IF == 0);
//等待数据发送完成
UTX0IF = 0;
//清除发送完成标志,准备下一次发送
str++;
/*
函数功能: 模仿printf风格的格式化打印功能
*/
char USART0_PRINT_BUFF[200];
//格式化数据缓存数据
void USART0_Printf(const char *format,...)char *str=NULL;
/*1. 格式化转换*/
va_list ap;
// va_list---->
char *
va_start(ap,format);
//初始化参数列表
vsprintf(USART0_PRINT_BUFF,
format,
ap);
//格式化打印
va_end(ap);
//结束参数获取
/*2. 串口打印*/
str=USART0_PRINT_BUFF;
//指针赋值
while(*str!=\\0)U0DBUF=*str;
//发送一个字节的数据
str++;
//指针自增,指向下一个数据
while(UTX0IF == 0);
//等待数据发送完成
UTX0IF = 0;
//清除发送完成标志,准备下一次发送
3.3 OLED显示屏代码
typedef unsigned char uchar;
typedef unsigned intuint;
#define LCD_SCL P1_2//SCLK时钟 D0(SCLK)
#define LCD_SDA P1_3//SDAD1(MOSI) 数据
#define LCD_RST P1_7//_REShardware reset复位
#define LCD_DCP0_0//A0H/L 命令数据选通端,H:数据,L:命令#define XLevelL0x00
#define XLevelH0x10
#define XLevel((XLevelH&
0x0F)*16+XLevelL)
#define Max_Column128
#define Max_Row64
#define Brightness0xCF
#define X_WIDTH128
#define Y_WIDTH64void DelayMS(unsigned int msec)
unsigned int i,j;
for (i=0;
i<
msec;
i++)
for (j=0;
j<
530;
j++);
/*********************LCD 延时1ms************************************/
void LCD_DLY_ms(unsigned int ms)unsigned int a;
while(ms)a=1800;
while(a--);
ms--;
return;
/*********************LCD写数据************************************/
void LCD_WrDat(unsigned char dat)unsigned char i=8, temp=0;
LCD_DC=1;
for(i=0;
i<
8;
i++) //发送一个八位数据 LCD_SCL=0;
temp = dat&
0x80;
if (temp == 0)LCD_SDA = 0;
elseLCD_SDA = 1;
LCD_SCL=1;
dat<
<
=1;
/*********************LCD写命令************************************/
void LCD_WrCmd(unsigned char cmd)unsigned char i=8, temp=0;
LCD_DC=0;
for(i=0;
i<
8;
i++) //发送一个八位数据 LCD_SCL=0;
temp = cmd&
0x80;
if (temp == 0)LCD_SDA = 0;
elseLCD_SDA = 1;
LCD_SCL=1;
cmd<
<
=1;
;
/*********************LCD 设置坐标************************************/
void LCD_Set_Pos(unsigned char x, unsigned char y)
LCD_WrCmd(0xb0+y);
LCD_WrCmd(((x&
0xf0)>
>
4)|0x10);
LCD_WrCmd((x&
0x0f)|0x01);
/*********************LCD全屏************************************/
void LCD_Fill(unsigned char bmp_dat) unsigned char y,x;
for(y=0;
y<
8;
y++)LCD_WrCmd(0xb0+y);
LCD_WrCmd(0x01);
LCD_WrCmd(0x10);
for(x=0;
x<
X_WIDTH;
x++)
LCD_WrDat(bmp_dat);
/*********************LCD复位************************************/
void LCD_CLS(void)unsigned char y,x;
for(y=0;
y<
8;
y++)LCD_WrCmd(0xb0+y);
LCD_WrCmd(0x01);
LCD_WrCmd(0x10);
for(x=0;
x<
X_WIDTH;
x++)
LCD_WrDat(0);
/*********************LCD初始化************************************/
void LCD_Init(void)P0SEL &
= 0xFE;
//让P0.0为普通IO口,
P0DIR |= 0x01;
//让P0.0为为输出P1SEL &
= 0x73;
//让 P1.2 P1.3 P1.7为普通IO口
P1DIR |= 0x8C;
//把 P1.2 P1.3 1.7设置为输出LCD_SCL=1;
LCD_RST=0;
LCD_DLY_ms(50);
LCD_RST=1;
//从上电到下面开始初始化要有足够的时间,即等待RC复位完毕
LCD_WrCmd(0xae);
//--turn off oled panel
LCD_WrCmd(0x00);
//---set low column address
LCD_WrCmd(0x10);
//---set high column address
LCD_WrCmd(0x40);
//--set start line addressSet Mapping RAM Display Start Line (0x00~0x3F)
LCD_WrCmd(0x81);
//--set contrast control register
LCD_WrCmd(0xcf);
// Set SEG Output Current Brightness
LCD_WrCmd(0xa1);
//--Set SEG/Column Mapping0xa0左右反置 0xa1正常
LCD_WrCmd(0xc8);
//Set COM/Row Scan Direction0xc0上下反置 0xc8正常
LCD_WrCmd(0xa6);
//--set normal display
LCD_WrCmd(0xa8);
//--set multiplex ratio(1 to 64)
LCD_WrCmd(0x3f);
//--1/64 duty
LCD_WrCmd(0xd3);
//-set display offsetShift Mapping RAM Counter (0x00~0x3F)
LCD_WrCmd(0x00);
//-not offset
LCD_WrCmd(0xd5);
//--set display clock divide ratio/oscillator frequency
LCD_WrCmd(0x80);
//--set divide ratio, Set Clock as 100 Frames/Sec
LCD_WrCmd(0xd9);
//--set pre-charge period
LCD_WrCmd(0xf1);
//Set Pre-Charge as 15 Clocks &
Discharge as 1 Clock
LCD_WrCmd(0xda);
//--set com pins hardware configuration
LCD_WrCmd(0x12);
LCD_WrCmd(0xdb);
//--set vcomh
LCD_WrCmd(0x40);
//Set VCOM Deselect Level
LCD_WrCmd(0x20);
//-Set Page Addressing Mode (0x00/0x01/0x02)
LCD_WrCmd(0x02);
//
LCD_WrCmd(0x8d);
//--set Charge Pump enable/disable
LCD_WrCmd(0x14);
//--set(0x10) disable
LCD_WrCmd(0xa4);
// Disable Entire Display On (0xa4/0xa5)
LCD_WrCmd(0xa6);
// Disable Inverse Display On (0xa6/a7)
LCD_WrCmd(0xaf);
//--turn on oled panel
LCD_Fill(0xff);
//初始清屏
LCD_Set_Pos(0,0);
推荐阅读
- 赵渝强使用二进制包部署Kubernetes集群
- #yyds干货盘点#three.js源码解读-EventDispatcher
- #yyds干货盘点#Web Components系列 ——自定义组件的生命周期
- #yyds干货盘点#swagger定位问题?式
- Redis列表list字符类型详解#yyds干货盘点#
- Linux 防火墙是什么,你需要它吗( | Linux 中国)
- 「2022」打算跳槽的,必知的 WEB 安全面试题
- 「2022」打算跳槽涨薪,必问面试题及答案 -- vue3 篇
- #yyds干货盘点# HCIE-Security Day11(初步学习防火墙双机热备和VGMP概念)