目录:
- 4.6. DHT11温湿度传感器模块
- 4.7. 语音识别模块
- 4.7. OLED显示屏模块
- 5. 不同的工作模式
- 6. 总结
在接着(上)写之前,首先来看一下效果:
链接: link
需要源码什么的可以私信我哦
4.6. DHT11温湿度传感器模块
这个模块主要就是用来监测环境温度的,没有什么其他的作用
.c文件
#include "stm32f10x.h"
#include "dht11.h"
#include "delay.h"uint8_t dat[5]={0x00,0x00,0x00,0x00,0x00}; //存储读取的温湿度信息
uint32_t sum=0; //存放校验时的求和/****************************************
设置PB12端口为输出
*****************************************/
void DHT11_PortOutput(void)
{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);GPIO_InitStructure.GPIO_Pin=GPIO_Pin_12;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//推挽输出GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//输出50MHzGPIO_Init(GPIOB,&GPIO_InitStructure);
}/****************************************
设置PB12端口为输入
*****************************************/
void DHT11_PortInput(void)
{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);GPIO_InitStructure.GPIO_Pin=GPIO_Pin_12;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;//推挽输出GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//输出50MHzGPIO_Init(GPIOB,&GPIO_InitStructure);
}/****************************************
函数名称:void DHT_Read_Byte()
函数功能:对DHT的数据中的一个字节读取函数
输入参数:无
返回值:无
*****************************************/
uint8_t DHT_Read_Byte(void)
{uint8_t temp; //存放读取到的位数据uint8_t ReadDat = 0;uint8_t i;uint8_t retry = 0;for(i=0;i<8;i++){while(DHT11 ==0 && retry < 100) //等待DHT11输出高电平{delay_us(1);retry++;}retry = 0;delay_us(30); //延时30us,由于‘0’代码高电平时间26~28us,'1'代码高电平时间70us,延时30us可判断出是1,还是0temp = 0; //先将寄存器清零if(DHT11 ==1) //延时30us之后如果还是高电平,证明为1代码temp = 1; //将1存储while(DHT11 ==1 && retry < 100) //等待信号被拉低,跳出{delay_us(1);retry++; }retry = 0;ReadDat<<=1; //数据左移1位,存放新得到的数据ReadDat|= temp; //新得到的数据放到最后1位}return ReadDat;
}/*********************************************
函数名称:unsigned char DHT_Read()
函数功能:读取DHT11的温湿度
输入参数:无
返回值: flag--数据读取、校验成功标志
*********************************************/
uint8_t DHT_Read(void)
{uint8_t i;uint8_t retry = 0;DHT11_PortOutput(); //端口方向设置为输出DHT11_LOW; //端口数据拉低delay_ms(18); //延时18ms,时序要求DHT11_HIGH; //端口数据拉高delay_us(40); //延时40us,DHT11_PortInput(); //方向设置为输入delay_us(20); //延时20usif(DHT11 ==0) //如果读取到低电平,证明DHT11响应{while(DHT11 ==0 && retry < 100) //等待变高电平{delay_us(1);retry++; }retry = 0;while(DHT11 ==1 && retry < 100) //等待变低电平{delay_us(1);retry++; }retry = 0;for(i=0;i<5;i++) //循环5次将40位读出{dat[i] = DHT_Read_Byte(); //读出1个字节}delay_us(50); //最后延时等待50us}sum=dat[0]+dat[1]+dat[2]+dat[3]; //前4个字节数据的和if(dat[4]==(u8)(sum)) //前4个数据和的末8位要和第5个数据相等,才算读取正确{return 1; //校验正确,返回1}elsereturn 0; //校验错误,返回0
}
.h文件
#ifndef __DHT11_H__
#define __DHT11_H__#define DHT11 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12)
#define DHT11_HIGH GPIO_SetBits(GPIOB,GPIO_Pin_12)
#define DHT11_LOW GPIO_ResetBits(GPIOB,GPIO_Pin_12)void DHT11_PortOutput(void);
void DHT11_PortInput(void);
uint8_t DHT_Read_Byte(void);
uint8_t DHT_Read(void);#endif
4.7. 语音识别模块
这里要注意,语音识别模块本身也是一个51单片机,所以说这个语音识别模块的代码仅仅是语音模块的51单片机与stm32进行交互的代码,并不是51单片机的代码,但是一般来讲,商家给你发货以后,都会在里面提前烧录上代码,所以我们不用去管51里面的代码。
.c文件
#include "stm32f10x.h" // Device header
#include "voice.h"/*
PB10 :TXD
PB11 : RXD
*/
extern uint32_t flag_led_on_off;
//变量引用
//变量声明
u8 RXBUF[20]; //串口存储数组
u8 RXOVER=0; //串口接收标志位
u8 RXCOUNT=0; //串口计数变量
u8 i; //清空数组变量//串口IO初始化函数
void USART3_Init(u32 bound)
{GPIO_InitTypeDef GPIO_InitStructure; //IO端口的初始化USART_InitTypeDef USART_InitStructure; //串口的初始化NVIC_InitTypeDef NVIC_InitStructure; //使能中断接收RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能IO端口的时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); //使能串口的时钟 //发送GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //发送引脚GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);//接收GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; //接收引脚GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;GPIO_Init(GPIOB,&GPIO_InitStructure);USART_InitStructure.USART_BaudRate = bound; //设置传输的波特率USART_InitStructure.USART_WordLength = USART_WordLength_8b; //设置传输一帧数据的数据位USART_InitStructure.USART_StopBits = USART_StopBits_1; //一位停止位USART_InitStructure.USART_Parity = USART_Parity_No; //无奇偶校验位USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //能使接收的发送USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件流控制USART_Init(USART3,&USART_InitStructure);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); //优先级分组NVIC_InitStructure.NVIC_IRQChannel= USART3_IRQn; //开启串口2的中断NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =0; //抢占优先级NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //响应优先级NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);USART_ITConfig(USART3,USART_IT_RXNE,ENABLE); //使能串口接收USART_Cmd(USART3,ENABLE); //使能串口2}/*
函数名:USART3中断服务函数
功能: 接收数据
注意:接收数据长度可调:RXCOUNT
*/
void USART3_IRQHandler(void)
{u8 temp;if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET){USART_ClearITPendingBit(USART3,USART_IT_RXNE);temp = USART_ReceiveData(USART3);if(temp == '\n' || RXCOUNT == 20) //判断是否接收到一个完整字符{RXCOUNT = 0;RXOVER =1; //接收数据完成标志位置1USART_ITConfig(USART3,USART_IT_RXNE,DISABLE);//失能串口接收中断标志 }else{RXBUF[RXCOUNT] = temp; //依次存放到数组中RXCOUNT++; //字符长度变化}}
}//串口处理函数
void USART_Deal(void)
{if(RXOVER){RXOVER = 0; //清除接收标志位switch(RXBUF[0]-48){case 1:flag_led_on_off=1; //点亮小灯break;case 2:flag_led_on_off=0; //熄灭小灯break; default: break; }for(i=0;i<20;i++) //将已接收数据的数组清空:共20个字符长度{RXBUF[i] = 0; //重置数据缓存区}USART_ITConfig(USART3,USART_IT_RXNE,ENABLE);//始能串口接收 }
}
.h文件
#ifndef __VOICE_H
#define __VOICE_Hvoid USART3_Init(u32 bound);
void USART_Deal(void);#endif
如果51单片机里面没有代码,就要使用串口工具进行烧录,需要问商家要源码,然后将hex文件烧录到里面。
4.7. OLED显示屏模块
OLED显示模块主要是用来显示和调试用的
OLED显示程序包括字库程序太大,放到以下链接中去下载,下载设置了0积分。
https://download.csdn.net/download/nbbskk/87238933
5. 不同的工作模式
以上第四章节完成了各个模块的驱动程序,那么接下来就要实现手动模式、自动模式和模式切换的代码了。
模式切换:
- 当最小系统板上电以后,自动进入模式选择界面,通过按键和红外遥控器可以进行模式的选择,选择的模式可用通过显示屏显示。
- 在选择完成相应的模式以后,也可以通过按键或者红外遥控器选择进入手动模式或者自动模式,进入相应模式以后,就可以执行相应的功能。
- 当进入相应模式以后,如果想要切换模式,可以通过手动退出,然后继续在模式选择界面进行选择。
.c文件
#include "stm32f10x.h" // Device header
#include "oled.h"
#include "mode_option.h"
#include "auto_mode.h"
#include "manu_mode.h"
#include "remote.h"extern uint32_t flag_auto_manu;
extern uint32_t flag_in_system;
uint32_t flag_break_mode=0;void mode_option_show(void)//文字显示
{OLED_ShowChinese(35,0,0,16,1);//选OLED_ShowChinese(51,0,1,16,1);//择OLED_ShowChinese(67,0,2,16,1);//模OLED_ShowChinese(83,0,3,16,1);//式OLED_Refresh();
}void auto_manu_option(void)//选择自动模式或者手动模式的函数
{if(flag_auto_manu==0){OLED_ShowChinese(50,30,4,16,1);//手OLED_ShowChinese(66,30,5,16,1);//动OLED_Refresh();}else{OLED_ShowChinese(50,30,6,16,1);//自OLED_ShowChinese(66,30,5,16,1);//动OLED_Refresh(); }}void system_in_auto_manu(void)//选择是否进入系统的函数
{if(flag_auto_manu==0&&flag_in_system==1)//如果手自动标志位为0并且进入系统标志位为1,则进入手动模式{flag_break_mode=0;//退出标志位置为0flag_in_system=0;//进入系统标志位置为0manu_mode_init();//手动模式初始化manu_go();//手动模式运行}else if(flag_auto_manu==1&&flag_in_system==1)//如果手自动标志位为1并且进入系统标志位为1,则进入自动模式{flag_break_mode=0;flag_in_system=0;auto_mode_init();auto_go();}
}
.h文件
#ifndef __MODE_OPTION_H
#define __MODE_OPTION_Hvoid mode_option_show(void);
void auto_manu_option(void);
void system_in_auto_manu(void);#endif
手动模式:
- 红外控制模式:使用带有红外遥控器的用户可以通过遥控器来对智能灯光进行控制。用户可以通过遥控器上的按键来打开/关闭灯光。
- 语音控制模式:使用语音助手的用户可以通过语音命令来控制智能灯光。用户可以说出指令,如“开灯”、“关灯”等,系统会解析语音指令并执行相应的操作。
- 按键控制模式:用户可以通过智能灯光控制系统配备的按键来控制灯光。
.c文件
#include "stm32f10x.h" // Device header
#include "manu_mode.h"
#include "LED.h"
#include "remote.h"
#include "dht11.h"
#include "oled.h"
#include "voice.h"extern uint32_t flag_break_mode;
extern uint32_t flag_led_on_off;
extern uint8_t dat[5];//存放温度数值void manu_mode_init(void)
{LED_Init();//led灯初始化USART3_Init(9600);//语音模块初始化OLED_Clear();OLED_ShowChinese(0,0,7,16,1);//灯OLED_ShowChinese(16,0,8,16,1);//光OLED_ShowChar(32,0,':',16,1);OLED_ShowChinese(0,16,9,16,1);//温OLED_ShowChinese(16,16,10,16,1);//度OLED_ShowChar(32,16,':',16,1);
}void manu_go(void)
{flag_led_on_off=0;//进入模式后,默认关灯while(1){remote_receive();//循环检测红外遥控USART_Deal();//循环检测语音模块if(flag_break_mode==1)//判断是否需要退出{flag_break_mode=0;OLED_Clear();break;}if(flag_led_on_off==0)//如果LED灯标志位为0,LED灯关闭{LED1_off();OLED_ShowChinese(40,0,12,16,1);//关}else//如果LED灯标志位为1,LED灯打开{LED1_on();OLED_ShowChinese(40,0,13,16,1);//开}if(DHT_Read())//读到DHT11温湿度传感器的数值并显示{OLED_ShowNum(40,16,dat[2],2,16,1);OLED_ShowChar(56,16,'.',16,1);OLED_ShowNum(60,16,dat[3],1,16,1);OLED_ShowChinese(70,16,10,16,1);//度OLED_Refresh();}}
}
.h文件
#ifndef __MANU_MODE_H
#define __MANU_MODE_Hvoid manu_mode_init(void);
void manu_go(void);#endif
自动模式:
- 当外部环境变暗的时候,光照度传感器会检测到光照度的降低并输出相应的信号,这些信号会传递给单片机进行处理,并且会使得相应的标志位进行标记。
- 当红外检测传感器检测到周围有人的时候,也会产生相应的信号传递给单片机,将相应的标志位进行置位。
- 当同时满足外部环境变暗并且周围有人的时候,这是系统会自动处理事件,将灯打开;当其中一个事件不满足的时候,灯光就会关闭。
.c文件
#include "stm32f10x.h" // Device header
#include "auto_mode.h"
#include "LED.h"
#include "remote.h"
#include "delay.h"
#include "bh1750.h"
#include "oled.h"
#include "infrared.h"
#include "dht11.h"extern uint32_t flag_break_mode;
extern uint32_t flag_infrared;
uint16_t light_value=0;
extern uint8_t dat[5];void auto_mode_init(void)
{LED_Init();infrared_Init();BH1750_Config_Init(); //BH1750的初始化bh_data_send(BHPowOn); //打开模块等待测量命令bh_data_send(BHReset); //重置数据寄存器值在PowerOn模式下有效bh_data_send(BHModeL); //低分辨率 单位4lx 测量时间16ms delay_ms(180); //等待测量结束延时180ms,保证通讯 OLED_Clear();OLED_ShowChinese(0,0,7,16,1);//灯OLED_ShowChinese(16,0,8,16,1);//光OLED_ShowChar(32,0,':',16,1);OLED_ShowChinese(0,16,9,16,1);//温OLED_ShowChinese(16,16,10,16,1);//度OLED_ShowChar(32,16,':',16,1);OLED_ShowChinese(0,32,11,16,1);//亮OLED_ShowChinese(16,32,10,16,1);//度OLED_ShowChar(32,32,':',16,1);
}void auto_go(void)
{while(1){remote_receive();if(flag_break_mode==1){flag_break_mode=0;OLED_Clear();break;}light_value = bh_data_read()*4/1.2; //光照强度的计算公式 = 寄存器值*分辨率/1.2 infrared_read();//检测红外检测模块的值OLED_ShowNum(40,32,light_value,4,16,1);//显示亮度值OLED_ShowString(72,32,(uint8_t*)"lx",16,1);//显示单位if(light_value<1000&&flag_infrared==1)//当亮度小于1000lx,并且红外检测模块标志位置为1,则开灯{LED1_on();OLED_ShowChinese(40,0,13,16,1);//开} else//否则关灯{LED1_off();OLED_ShowChinese(40,0,12,16,1);//关} if(DHT_Read()){OLED_ShowNum(40,16,dat[2],2,16,1);OLED_ShowChar(56,16,'.',16,1);OLED_ShowNum(60,16,dat[3],1,16,1);OLED_ShowChinese(70,16,10,16,1);//度OLED_Refresh();}}
}
.h文件
#ifndef __AUTO_MODE_H
#define __AUTO_MODE_Hvoid auto_mode_init(void);
void auto_go(void);#endif
6. 总结
基于stm32的红外、语音、按键智能灯光控制基本就可以实现了,如果想要完整的源码、原理图、PCB、流程图可以私信我,谢谢大家!!!