STM32第三课:按键控制LED灯,光敏传感器控制蜂鸣器

一:按键控制LED灯

        STM32的第三课,我们来学习如何使用按键来控制LED灯的亮灭。上一节课我们通过代码控制了LED的状态,但是还是处于一种较为低级的方式控制LED灯,缺少交互性,用按键进行控制属于更高的一个层次。然后我们将学习通过光敏传感器控制蜂鸣器的通断,让我们的学习之路更加有趣、精彩。

1.1 初始化函数代码的编写 

        首先编写LED小灯的初始化函数代码,用于初始化将要控制LED小灯的I/O口。

        首先,在工程文件中先创建一个名为Hardware的文件夹,用于存放我们将要配置的系统文件。

         同样,在魔术棒里面,配置Hardware文件夹的头文件路径,用于使用自己编写的头文件驱动程序。此处再演示一下如何进行配置。

        第一步:先在工程文件中创建名为Hardware的文件夹。

第二步,在三个小箱子里面添加名为Hardware的文件,用于存放编写的驱动代码。 

        然后右键左侧刚添加的Hardware文件夹,选择添加新文件到Hardware         然后依次选择.c文件,名称填LED,点Add再选择下面的.h文件,名称也填LED,点Add,这样我们就在Hardware文件夹里面创建了两个配置驱动的文件了。

         同时按照同样的思路,再创建一个Key.c和Key.h的两个驱动文件放在Hardware文件夹里,用于配置按键的驱动。

        在魔术棒里添加上Hardware的头文件地址即可。

        在驱动文件LED.c文件里,主要编写驱动文件的函数,用于在主函数main.c文件里面直接引用。把所有想实现的功能都编写成函数有利于代码的检查和移植。LED.h文件主要编写对外引用函数的代码,这就是.c文件和.h文件的主要区别。

          在驱动文件LED.c文件里,首先编写初始化函数的代码,然后再编写相关功能的代码,比如说LED_ONLED_OFF、LED_Turn,分别代表LED灯的亮灭和电位翻转。详细代码见如下所示:

LED.c

#include "stm32f10x.h"

void LED_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	GPIO_SetBits(GPIOA,GPIO_Pin_1 | GPIO_Pin_2);
}

void LED1_ON(void)
{
	GPIO_ResetBits(GPIOA,GPIO_Pin_1);
}



void LED1_OFF(void)
{
	GPIO_SetBits(GPIOA,GPIO_Pin_1);
}

void LED1_Turn(void)
{
	if (GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_1) == 0)
	{
		GPIO_SetBits(GPIOA,GPIO_Pin_1);
	}
	else
	{
		GPIO_ResetBits(GPIOA,GPIO_Pin_1);
	}
}

void LED2_ON(void)
{
	GPIO_ResetBits(GPIOA,GPIO_Pin_2);
}

void LED2_OFF(void)
{
	GPIO_SetBits(GPIOA,GPIO_Pin_2);
}

void LED2_Turn(void)
{
	if (GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_2) == 0)
	{
		GPIO_SetBits(GPIOA,GPIO_Pin_2);
	}
	else
	{
		GPIO_ResetBits(GPIOA,GPIO_Pin_2);
	}
}

        LED.h文件里主要放置LED.c文件中的函数对外引用,直接把函数的名称拿过来即可。但是LED.h文件首先要写上防止重复引用的函数,都是一个套路,所有的.h文件里面都要写。详细代码如下:

LED.h

#ifndef __LED_H
#define __LED_H

void LED_Init(void);
void LED1_ON(void);
void LED1_OFF(void);
void LED2_ON(void);
void LED2_OFF(void);
void LED1_Turn(void);
void LED2_Turn(void);

#endif

这样一来LED小灯的驱动代码就写好了。

然后我们再来配置按键的驱动代码LED.c和LED.h的代码内容。

LED.c代码也是需要我们编写相关功能的驱动代码函数,首先编写初始化函数,结构和上文LED.c的初始化函数大同小异,只有引脚端口号不一样而已。然后编写按键的数据读取函数,在这里我们使用GPIO_ReadInputDataBit函数,可以直接读取某一个引脚的电位值。按键需要延时20微秒用于防抖,详细代码如下:

Key.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"

void Key_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	
	GPIO_Init(GPIOB,&GPIO_InitStructure);
}

uint8_t Key_GetNum(void)
{
	uint8_t KeyNum = 0;
	
	if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) == 0)
	{
		Delay_ms(20);
		while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) == 0);
		Delay_ms(20);
		
		KeyNum = 1;
	}
	
	if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11) == 0)
	{
		Delay_ms(20);
		while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11) == 0);
		Delay_ms(20);
		
		KeyNum = 2;
	}
	
	
	return KeyNum;
}

Key.h 

#ifndef __KEY_H
#define __KEY_H
#include "stm32f10x.h"                  // Device header


void Key_Init(void);
uint8_t Key_GetNum(void);

#endif

这样一来,初始化驱动文件就配置好了。

1.2 电路接线方法

1.3 主体代码演示 

 首先我们要配置好头文件,延时函数Delay.h也要配置上,这一点在我上一篇文章中有讲到。然后初始化LED和Key,再循环函数里面编写相关代码即可。代码如下:

main.c

#include "stm32f10x.h"
#include "LED.h"
#include "Delay.h"
#include "KEY.h"


uint8_t KeyNum;

int main(void)
{
	LED_Init();
	Key_Init();
	
	
	while(1)
	{
		//************按键控制LED
		KeyNum = Key_GetNum();
		
		if(KeyNum == 1)
		{
			LED1_Turn();
		}
		if(KeyNum == 2)
		{
			LED2_Turn();
		}
		
	}
	
}

1.4 实操效果展示

 

二:光敏电阻控制蜂鸣器 

         光敏电阻是采用半导体材料制作,利用内光电效应工作的光电元件。它在光线的作用下其阻值往往变小,这种现 象称为光导效应,因此,光敏电阻又称光导管。

2.1 光敏电阻传感器

 2.1.1 产品特性

         光敏电阻模块一般用来检测周围环境的光线的亮度,触发单片机或继电器模块等。使用宽电压LM393比较器,信号干净,波形好,驱动能力强,超过15mA。配可调电位器可调节检测光线亮度。设有固定螺栓孔M3,方便安装。

2.1.2 工作原理 

        光敏电阻是用硫化隔或硒化隔等半导体材料制成的特殊电阻器,其工作原理是基于内光电效应。随着光照强度的升高,电阻值迅速降低,由于光照产生的载流子都参与导电,在外加电场的作用下作漂移运动,电子奔向电源的正极,空穴奔向电源的负极,从而使光敏电阻器的阻值迅速下降。其在无光照时,几乎呈高阻状态,暗电阻很大。

2.1.3 产品参数 

         工作电压:DC3.3-5V
        光敏电阻型号:5516

 2.1.4 使用说明

         数字量DO输出端可以直接驱动本店继电器模块,由此可以组成一个光控开关。模拟量A0可以和AD模块相连,通过AD转换,可以获得环境光强的数值。当环境光线亮度达不到设定闽值时,DO端输出高电平,当外界环境光线亮度超过设定闽值时,DO端输出低电平。检测亮度可以通过电位器进行调节,顺时针调电位器,检测亮度增加;逆时针调电位器,检测亮度减少。

2.2 初始化驱动代码的编写 

         首先创建有关于蜂鸣器的Buzzer.c和Buzzer.h的两个驱动文件,再创建有关于光敏传感器的LightSensor.c和LightSensor.h的两个驱动文件,按照上文的方法分别添加到Hardware文件中。

        Buzzer.c文件主要编写实现蜂鸣器响起来的代码函数,类型和上文类似,这里不再赘述。直接给出Buzzer.c和Buzzer.h的代码。

Buzzer.c

#include "stm32f10x.h"                  // Device header

void Buzzer_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	
	GPIO_Init(GPIOB,&GPIO_InitStructure);
	
	GPIO_SetBits(GPIOA,GPIO_Pin_12);
}

void Buzzer_ON(void)
{
	GPIO_ResetBits(GPIOB,GPIO_Pin_12);
}



void Buzzer_OFF(void)
{
	GPIO_SetBits(GPIOB,GPIO_Pin_12);
}

void Buzzer_Turn(void)
{
	if (GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_12) == 0)
	{
		GPIO_SetBits(GPIOB,GPIO_Pin_12);
	}
	else
	{
		GPIO_ResetBits(GPIOB,GPIO_Pin_12);
	}
}

Buzzer.h

#ifndef __Buzzer_H
#define __Buzzer_H

void Buzzer_Init(void);
void Buzzer_ON(void);
void Buzzer_OFF(void);
void Buzzer_Turn(void);



#endif

        关于LightSensor.c和LightSensor.h的两个驱动文件的话,在LightSensor.c文件中内容与上文类似,不过有关代码部分我们只需要传回光敏传感器引脚的值就行。代码如下:

LightSensor.c

#include "stm32f10x.h"                  // Device header

void LightSensor_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	
	GPIO_Init(GPIOB,&GPIO_InitStructure);
	
	GPIO_SetBits(GPIOA,GPIO_Pin_13);
}

uint8_t LightSensor_Get(void)
{
	return GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13);
}

LightSensor.h

#ifndef __LIGHT_SENSOR_
#define __LIGHT_SENSOR_

void LightSensor_Init(void);
uint8_t LightSensor_Get(void);

#endif

如此一来,我们驱动文件基本上配置好了,下面只要完善主函数main.c中的代码即可。

2.3 电路接线方法

2.4 主体代码演示 

         相关的头文件是必须要包含的,比如#include "stm32f10x.h"、#include "Delay.h",还有刚刚配置好的#include "Buzzer.h"、#include "LightSensor.h"等头文件。

        紧接着初始化Buzzer和LightSensor函数。

        在while循环函数中,接收光敏传感器返回的引脚电位数值,进行 if 判断。代码如下所示:

#include "stm32f10x.h"
#include "Delay.h"
#include "Buzzer.h"
#include "LightSensor.h"


int main(void)
{
	Buzzer_Init();
	LightSensor_Init();
	
	
	while(1)
	{
		
		if (LightSensor_Get() == 1)
		{
			Buzzer_ON();
		}
		else
		{
			Buzzer_OFF();
		}
		
	}
	
}

2.5 实操效果演示