一:按键控制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(); } } }