STM32控制风扇转动、蜂鸣器响停、光敏电阻光强读取、温湿度传感器控制

提出问题:STM32如何控制风扇转动、蜂鸣器响停、光敏电阻光强读取、以及温湿度传感器控制?这些都是学习单片机较为基本的知识, 本文将对以上问题作出详细解答希望能帮到大家:

本文以STM32F103R6为例

STM32控制风扇转动、蜂鸣器响停、光敏电阻光强读取、温湿度传感器控制

一、控制风扇转动和蜂鸣器响停

直流电风扇在proteus库中的名称是FAN-DC
蜂鸣器在proteus库中的名称是BUZZER

#include "stm32f10x.h"
#include "led.h"
#include "uart.h"
#include "stdio.h"
#include "lcd.h"
void main_delay(u32 time)
{
		int i,j;
		for(i = 0; i < time; i++)
		{
			for(j = 0; j < 1000; j++)
			{
				j++;
				j--;
			}	
		}
}
//风扇初始化函数 
void fanInit(void)
{
	GPIO_InitTypeDef  GPIO_InitStruct;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_6;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);	
	GPIO_SetBits(GPIOA,GPIO_Pin_6);//置1,风扇关		
}

//蜂鸣器初始化函数 
void buzzerInit(void)
{
	GPIO_InitTypeDef  GPIO_InitStruct;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_7;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOC,&GPIO_InitStruct);	
	GPIO_SetBits(GPIOC,GPIO_Pin_7);//置1,蜂鸣器关		
}


int main(void)
{
	int i = 0;
	fanInit();//风扇初始化
	buzzerInit();//蜂鸣器初始化
	LED_GPIO_Config();
	while(1)
	{		//如果 置1 是关风扇和蜂鸣器
		GPIO_ResetBits(GPIOA,GPIO_Pin_6);//清零 风扇开
		GPIO_ResetBits(GPIOC,GPIO_Pin_7);//清零 蜂鸣器开
	}
}

注意:蜂鸣器要将导通电压设置成1.8v,否则可能会因为导通电压不足而不响。
STM32控制风扇转动、蜂鸣器响停、光敏电阻光强读取、温湿度传感器控制
二、温湿度传感器
本文用到的温湿度传感器是DHT11
代码实现:

int main(void)
{	 //unsigned char //无符号的字符
	u8 temp,hum;//用来保存温度和湿度整数
	char buf_temp[30];//用来保存格式化的温度字符串
	char buf_hum[30];//用来保存格式化的湿度字符串
	LCD_Init();//LCD液晶屏的初始化
	DHT11_Init();//温湿度传感器初始化
	while(1)
	{
		//读取温湿度 参数上的地址传递
		DHT11_Read_Data(&temp,&hum);//temp 和 hum保存了温度和湿度
		sprintf(buf_temp,"temp:%d",temp);//格式化的温度字符串,放入字符数组
		sprintf(buf_hum,"hum:%d",hum);//格式化的湿度字符串,放入字符数组
		LCD_P8x16Str(10,1,(u8 *)buf_temp);//显示到屏幕上
		LCD_P8x16Str(10,3,(u8 *)buf_hum);//显示到屏幕上
		main_delay(2000);//延时
	}
}

例:当温度大于30红灯闪烁,蜂鸣器响,湿度大于50风扇转动

#include "stm32f10x.h"
#include "LQ12864.h"
#include "DTH11.h"
#include <stdio.h>

//风扇初始化
void fanInit(void)
{
	GPIO_InitTypeDef  GPIO_InitStruct;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_1;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);	
	GPIO_SetBits(GPIOA, GPIO_Pin_1);	//置1,风扇关
}
//蜂鸣器初始化
void buzzerInit(void)
{
	GPIO_InitTypeDef  GPIO_InitStruct;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_2;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);	
	GPIO_SetBits(GPIOA, GPIO_Pin_2);	//置1,风扇关
}
void ledInit(void)
{
	GPIO_InitTypeDef  GPIO_InitStruct;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);	
	GPIO_SetBits(GPIOA, GPIO_Pin_0);	//置1,风扇关
}
void main_delay(int time)
{
	int i,j;
	for(i = 0; i < time; i++)
	{
		for(j = 0; j < 1000; j++)
		{
			j++;
			j--;
		}
	}
}

int main(void)
{	 
	u8是指//unsigned char //无符号的字符
	u8 temp,hum;//用来保存温度和湿度整数
	char buf_temp[30];//用来保存格式化的温度字符串
	char buf_hum[30];//用来保存格式化的湿度字符串
	LCD_Init();
	DHT11_Init();
	fanInit();
	buzzerInit();
	ledInit();
	while(1)
	{
			//读取温湿度 参数上的地址传递
		DHT11_Read_Data(&temp,&hum);//temp 和 hum保存了温度和湿度
		sprintf(buf_temp,"temp:%d",temp);//格式化的温度字符串,放入字符数组
		sprintf(buf_hum,"hum:%d",hum);//格式化的湿度字符串,放入字符数组
		LCD_P8x16Str(10,1,(u8 *)buf_temp);//显示到屏幕上
		LCD_P8x16Str(10,3,(u8 *)buf_hum);//显示到屏幕上
		main_delay(2000);//延时
		if(temp>30)
		{
			
			GPIO_ResetBits(GPIOA, GPIO_Pin_2);
			
					GPIO_ResetBits(GPIOA, GPIO_Pin_0);
				main_delay(200);
				GPIO_SetBits(GPIOA, GPIO_Pin_0);
				
			
		}
		else
		{
			GPIO_SetBits(GPIOA, GPIO_Pin_0);
			GPIO_SetBits(GPIOA, GPIO_Pin_2);
		}
		if(hum>50)
		{
			GPIO_ResetBits(GPIOA, GPIO_Pin_1);
		
		}
		else
		{
			GPIO_SetBits(GPIOA, GPIO_Pin_1);
		}
	}	
}

注意:
DHT11的传输方式:
传输数据使用的是 单总线 即只有一根数据线
1 byte == 8 bit
DHT11一次传输 40 bit 数据
8bit -->温度的整数部分
8bit -->温度的小数部分
8bit -->湿度的整数部分
8bit -->湿度的小数部分
8bit -->校验位
为什么要有检验位?因为单总线传输容易丢失数据,校验位的值便是前四位的和,若发送的和接受的校验位的值不等则说明数据丢失。
这个问题在LQ12864.c文件中充分的显示出来

LQ12864.c
u8 DHT11_Read_Data(u8 *temp,u8 *humi)    //u8是无符号的char----unsigned char

{        

 u8 buf[5];

 u8 i;

 DHT11_Rst();

	if(DHT11_Check()==0)

	{

	for(i=0;i<5;i++)//读取40位数据

	{

	buf[i]=DHT11_Read_Byte();
		//buf[0]存放温度的整数部分
		//buf[1]存放温度的小数部分
		//buf[2]存放湿度的整数部分
		//buf[3]存放湿度的小数部分
		//buf[4]存放标志位

	}

	if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
	//验证标志位,因为单总线传输容易丢失数据
	{

	*humi=buf[0];

	*temp=buf[2];

	}

	}else return 1;

	return 0;    

}

三:光电传感器,光敏电阻 光敏电阻在proteus中的名称为TORCH 光敏电阻的工作原理:根据光照不同,电阻的阻值发生变化,光越强电阻越小电压小 。 ADC模数转换器

void Adc_Init(void) //ADC初始化

u16 Get_Adc(void) //读取光照强度

代码实现

int main(void) 
{	 
	int light;//用来保存读取到的光照强度
	char buf[100] = { 0 };//用来保存格式化的光照强度的字符串
	
	Adc_Init();//ADC初始化 
	LCD_Init();//LCD初始化
	
	while(1)
	{
		light = Get_Adc();//读取光照强度
		sprintf(buf,"light:%d   ",light);
		LCD_P8x16Str(0,0,buf);
		main_delay(200);
	}
}

例:光强度值高于1000(灯光变暗)

	//添加三个黄灯
	0-1000 三个灯灭 
	1000-2000 一个灯亮
	2000-3000 两个灯亮 
	3000-4500 三个灯亮	

STM32控制风扇转动、蜂鸣器响停、光敏电阻光强读取、温湿度传感器控制
代码如下:


#include "stm32f10x.h"
#include "LQ12864.h"
#include "DTH11.h"
#include <stdio.h>
#include "adc.h"

void main_delay(int time)
{
	int i,j;
	for(i = 0; i < time; i++)
	{
		for(j = 0; j < 1000; j++)
		{
			j++;
			j--;
		}
	}
}
//风扇初始化
void fanInit()
{
	GPIO_InitTypeDef init;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	init.GPIO_Mode = GPIO_Mode_Out_PP;
	init.GPIO_Pin = GPIO_Pin_3;
	init.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&init);
	GPIO_SetBits(GPIOA,GPIO_Pin_3);//置1,风扇关
}
//蜂鸣器初始化
void buzzerInit()
{
	GPIO_InitTypeDef init;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	init.GPIO_Mode = GPIO_Mode_Out_PP;
	init.GPIO_Pin = GPIO_Pin_5;
	init.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&init);
	GPIO_SetBits(GPIOA,GPIO_Pin_5);//置1,蜂鸣器关
}
//LED初始化
void ledInit()
{
	GPIO_InitTypeDef init;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	init.GPIO_Mode = GPIO_Mode_Out_PP;
	init.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12;
	init.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&init);
	GPIO_SetBits(GPIOA,GPIO_Pin_7|GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12);//置1,LED关
}
//控制灯的亮灭 
//0 000
//4 100
//6 110
//7 111
void ledSwitch(int num)
{
	num & 4 ? GPIO_ResetBits(GPIOA,GPIO_Pin_10) : GPIO_SetBits(GPIOA,GPIO_Pin_10);
	num & 2 ? GPIO_ResetBits(GPIOA,GPIO_Pin_11) : GPIO_SetBits(GPIOA,GPIO_Pin_11);
	num & 1 ? GPIO_ResetBits(GPIOA,GPIO_Pin_12) : GPIO_SetBits(GPIOA,GPIO_Pin_12);
}


int main(void) //休息10分钟
{	 
	int light;//用来保存读取到的光照强度
	char buf[100] = { 0 };//用来保存格式化的光照强度的字符串
	
	Adc_Init();//ADC初始化 
	LCD_Init();//LCD初始化
	ledInit();//LED初始化
	while(1)
	{
		light = Get_Adc();//读取光照强度
		if(light > 0 && light <= 1000)
			ledSwitch(0);//三个灯灭
		else if(light > 1000 && light <= 2000)
			ledSwitch(4);
		else if(light > 2000 && light <= 3000)
			ledSwitch(6);
		else if(light > 3000 && light <= 4500)
			ledSwitch(7);
		sprintf(buf,"light:%d   ",light);
		LCD_P8x16Str(0,0,buf);
		main_delay(200);
	}	
}

注意:

  • ADC的实现需要adc.c文件和adc.h文件,点击下载ADC文件,下面介绍如何导入adc.c到keil工程中。
  • 把下载好的ladc.c和adc.h文件复制到user文件夹下,即和main.c在同一文件夹下
  • 导入adc.c文件后要添加#include "adc.h"才能正常运行**

STM32控制风扇转动、蜂鸣器响停、光敏电阻光强读取、温湿度传感器控制

  • 右键USER,选择添加已存在的文件,选中adc.c,点击添加即可。

STM32控制风扇转动、蜂鸣器响停、光敏电阻光强读取、温湿度传感器控制
STM32控制风扇转动、蜂鸣器响停、光敏电阻光强读取、温湿度传感器控制

例:添加两个按键,分别控制风扇和蜂鸣器的开关,按一下开,再按一下关。

#include "stm32f10x.h"
#include "led.h"
#include "uart.h"
#include "stdio.h"
#include "lcd.h"

#define KEY_FAN 1
#define KEY_BUZZER 2
#define NONE 0

void main_delay(u32 time)
{
		int i,j;
		for(i = 0; i < time; i++)
		{
			for(j = 0; j < 1000; j++)
			{
				j++;
				j--;
			}	
		}
}

//风扇初始化函数 
void fanInit(void)
{
	GPIO_InitTypeDef  GPIO_InitStruct;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_6;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);	
	GPIO_SetBits(GPIOA,GPIO_Pin_6);//置1,风扇关		
}

//蜂鸣器初始化函数 
void buzzerInit(void)
{
	GPIO_InitTypeDef  GPIO_InitStruct;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_7;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOC,&GPIO_InitStruct);	
	GPIO_SetBits(GPIOC,GPIO_Pin_7);//置1,蜂鸣器关		
}
//按键初始化 
void keyInit(void)
{
	GPIO_InitTypeDef  GPIO_InitStruct;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU;//输入模式
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_2 | GPIO_Pin_5;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStruct);	
}
//读取按键的值
int keyRead()
{
	if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_2) == 0)//风扇
		return KEY_FAN;
	if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_5) == 0)//蜂鸣器
		return KEY_BUZZER;
	return NONE;
}

int main(void)
{
	int i = 0;
	int key;
	char status[2] = {0,0};//两个元素分别代表 风扇和蜂鸣器开关的状态
	fanInit();//风扇初始化
	buzzerInit();//蜂鸣器初始化
	keyInit();//按键初始化
	LED_GPIO_Config();
	while(1)
	{		
		//读取按键的值 
		key = keyRead();
		if(key == KEY_FAN)
		{// ! 取非, 原来为真,加上!后变为假 C语言中 1 真 0 假
		           //原来为假,加上!后变为真
			status[0] = !status[0];// !status[0] 1
			//1 代表开 0 代表关
			status[0] ? GPIO_ResetBits(GPIOA,GPIO_Pin_6) : GPIO_SetBits(GPIOA,GPIO_Pin_6);	
		}
		else if(key == KEY_BUZZER)
		{
			status[1] = !status[1];// !status[0] 1
			//1 代表开 0 代表关
			status[1] ? GPIO_ResetBits(GPIOC,GPIO_Pin_7) : GPIO_SetBits(GPIOC,GPIO_Pin_7);
		}
		main_delay(200);//按键消抖
	}
}


以上就是本文所有内容,希望能帮到大家!!!

上一篇:STM32端口IO方向设置问题的IO方向设置问题


下一篇:我对STM32所用位带操作宏的超详细剖析、优势分析及应用推广探索研究(持续更新,欢迎讨论交流)(转)