本文介绍:

目录

在接着(上)写之前,首先来看一下效果
链接: 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;//输出50MHz
 GPIO_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;//输出50MHz
 GPIO_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 &amp;&amp; retry < 100)     //等待DHT11输出高电平
		{
			delay_us(1);
			retry++;
		}
		retry = 0;
    delay_us(30);          //延时30us,由于‘0’代码高电平时间26~28us,'1'代码高电平时间70us,延时30us判断出是1,还是0
    temp = 0;             //先将寄存器清零
    if(DHT11 ==1)        //延时30us之后如果还是电平,证明为1代码
      temp = 1;            //将1存储
    while(DHT11 ==1 &amp;&amp; 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);          //延时20us
  if(DHT11 ==0)          //如果读取低电平,证明DHT11响应
  {
    while(DHT11 ==0 &amp;&amp; retry < 100)  //等待变高电平
		{
			delay_us(1);
			retry++;				
		}
		retry = 0;
    while(DHT11 ==1 &amp;&amp; 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
    }
  else
     return 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, &amp;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;    //接收数据完成标志位置1
			USART_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_H



void 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. 不同工作模式

以上第四章节完成各个模块的驱动程序,那么接下来就要实现手动模式自动模式模式切换的代码了。

模式切换

  1. 最小系统板上电以后,自动进入模式选择界面通过按键和红外遥控器可以进行模式选择选择模式可用通过显示屏显示
  2. 选择完成相应的模式以后,也可以通过按键或者红外遥控器选择进入手动模式或者自动模式,进入相应模式以后,就可以执行相应的功能
  3. 当进入相应模式以后,如果想要切换模式,可以通过手动退出然后继续在模式选择界面进行选择。

.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;//退出标志位置为0
			flag_in_system=0;//进入系统标志位置为0
			manu_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_H

void mode_option_show(void);
void auto_manu_option(void);
void system_in_auto_manu(void);


#endif

手动模式:

  1. 红外控制模式:使用带有红外遥控器用户可以通过遥控器来对智能灯光进行控制用户可以通过遥控器上的按键打开/关闭灯光。
  2. 语音控制模式:使用语音助手用户可以通过语音命令控制智能灯光。用户可以说出指令,如“开灯”、“关灯”等,系统会解析语音指令执行相应的操作
  3. 按键控制模式:用户可以通过智能灯光控制系统配备的按键来控制灯光。
    .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_H


void manu_mode_init(void);
void manu_go(void);



#endif

自动模式:

  1. 外部环境变暗的时候,光照度传感器会检测到光照度的降低并输出相应的信号,这些信号传递给单片机进行处理,并且会使得相应的标志位进行标记
  2. 当红外检测传感器检测到周围有人的时候,也会产生相应的信号传递给单片机,将相应的标志位进行置位。
  3. 当同时满足外部环境变暗并且周围有人的时候,这是系统会自动处理事件,将灯打开;当其中一个事件满足时候,灯光就会关闭。
    .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_H

void auto_mode_init(void);
void auto_go(void);



#endif

6. 总结

基于stm32的红外、语音、按键智能灯光控制基本就可以实现了,如果想要完整源码原理图、PCB、流程图可以私信我,谢谢大家!!!

原文地址:https://blog.csdn.net/nbbskk/article/details/134792440

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_39928.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注