打印
[其他ST产品]

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

[复制链接]
106|14
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
提出问题: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);//清零 蜂鸣器开

        }

}




使用特权

评论回复
沙发
是你的乱码|  楼主 | 2023-12-29 12:25 | 只看该作者
注意:蜂鸣器要将导通电压设置成1.8v,否则可能会因为导通电压不足而不响。

使用特权

评论回复
板凳
是你的乱码|  楼主 | 2023-12-29 12:25 | 只看该作者
二、温湿度传感器
本文用到的温湿度传感器是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);//延时
        }
}

使用特权

评论回复
地板
是你的乱码|  楼主 | 2023-12-29 12:25 | 只看该作者
例:当温度大于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);
                }
        }       
}

使用特权

评论回复
5
是你的乱码|  楼主 | 2023-12-29 12:25 | 只看该作者
注意:
DHT11的传输方式:
传输数据使用的是 单总线 即只有一根数据线
1 byte == 8 bit
DHT11一次传输 40 bit 数据
8bit -->温度的整数部分
8bit -->温度的小数部分
8bit -->湿度的整数部分
8bit -->湿度的小数部分
8bit -->校验位
为什么要有检验位?因为单总线传输容易丢失数据,校验位的值便是前四位的和,若发送的和接受的校验位的值不等则说明数据丢失。

使用特权

评论回复
6
是你的乱码|  楼主 | 2023-12-29 12:26 | 只看该作者
这个问题在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;   

}

使用特权

评论回复
7
是你的乱码|  楼主 | 2023-12-29 12:26 | 只看该作者
三:光电传感器,光敏电阻 光敏电阻在proteus中的名称为TORCH 光敏电阻的工作原理:根据光照不同,电阻的阻值发生变化,光越强电阻越小电压小 。 ADC模数转换器
void Adc_Init(void) //ADC初始化

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

使用特权

评论回复
8
是你的乱码|  楼主 | 2023-12-29 12:27 | 只看该作者
代码实现
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);
        }
}

使用特权

评论回复
9
是你的乱码|  楼主 | 2023-12-29 12:27 | 只看该作者
例:光强度值高于1000(灯光变暗)
        //添加三个黄灯
        0-1000 三个灯灭
        1000-2000 一个灯亮
        2000-3000 两个灯亮
        3000-4500 三个灯亮       

使用特权

评论回复
10
是你的乱码|  楼主 | 2023-12-29 12:27 | 只看该作者

使用特权

评论回复
11
是你的乱码|  楼主 | 2023-12-29 12:28 | 只看该作者
代码如下:

#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);
        }       
}

使用特权

评论回复
12
是你的乱码|  楼主 | 2023-12-29 12:28 | 只看该作者
注意:

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

使用特权

评论回复
13
是你的乱码|  楼主 | 2023-12-29 12:28 | 只看该作者

使用特权

评论回复
14
是你的乱码|  楼主 | 2023-12-29 12:35 | 只看该作者
右键USER,选择添加已存在的文件,选中adc.c,点击添加即可。

使用特权

评论回复
15
是你的乱码|  楼主 | 2023-12-29 12:35 | 只看该作者
例:添加两个按键,分别控制风扇和蜂鸣器的开关,按一下开,再按一下关。
#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);//按键消抖
        }
}


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

19

主题

263

帖子

1

粉丝