提出问题:STM32如何控制风扇转动、蜂鸣器响停、光敏电阻光强读取、以及温湿度传感器控制?这些都是学习单片机较为基本的知识, 本文将对以上问题作出详细解答希望能帮到大家:
本文以STM32F103R6为例
一、控制风扇转动和蜂鸣器响停
直流电风扇在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,否则可能会因为导通电压不足而不响。
二、温湿度传感器
本文用到的温湿度传感器是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 三个灯亮
代码如下:
#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"才能正常运行**
- 右键USER,选择添加已存在的文件,选中adc.c,点击添加即可。
例:添加两个按键,分别控制风扇和蜂鸣器的开关,按一下开,再按一下关。
#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);//按键消抖
}
}