我们需要完成LED和按键的驱动代码,但把两个混在主函数里,就会太乱,也不好移植,所以选择将驱动代码封装起来,单独放在.c和.h文件里,这就是模块化编程的方式
准备工作
添加必要代码
#ifndef __LED_H
#define __LED_H
#endif
一定要在最后留空格
按键控制LED主体代码
不显示代码提示的话,可以按下Ctrl+Alt+空格
LED代码部分
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_ResetBits(GPIOA, GPIO_Pin_1 | GPIO_Pin_2);//GPIO配置好后默认是低电平
}//这个函数是用来初始化LED的
只需调用LED_Init();两个LED的两个GPIO口就初始化完成了
void LED1_ON(void)
{
GPIO_ResetBits(GPIOA, GPIO_Pin_1);
}
void LED1_OFF(void)
{
GPIO_SetBits(GPIOA, GPIO_Pin_1);
}
LED的定亮和熄灭的代码,记得去.h文件里面声明
void LED1_ON(void);
void LED1_OFF(void);
按键代码部分
准备工作同上,只是名字为Key
同样写个Key初始化的函数
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相当于unsinged char
{
uint8_t KEY_NUM = 0 ; //如果按键没有按下,默认给0
if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0 ){
Delay_ms(20); //需要用到delay函数,头文件还需加上#include "Delay.h"
while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0 );//按键一般是松手才有动作,所以加上判断
Delay_ms(20); //同样是消抖
KEY_NUM = 1;
}
if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0 ){
Delay_ms(20);
while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0 );
Delay_ms(20);
KEY_NUM = 2;
}
//一开始的疑惑是为什么两个if写在一个函数里面,但是这段实现的功能就是,按键1按下LED1点亮,按键2按下LED2熄灭
return KEY_NUM;
}
同样记得,在.h文件里声明,在main.c文件里加上头文件#include "Key.h"
顺便一看GPIO的读取函数
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
*用来读取数据输入寄存器某一个端口的输入值,读取按键要用到这个函数
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);
*用来读取整个数据输入寄存器的
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
*用来读取数据输出寄存器某一个端口的输入值,这个函数一般用于输出模式下,用来看自己输出什么
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);
*用来读取整个数据输出寄存器的
如果我们要实现按键按一下熄灭,再按一下点亮该如何实现呢?也就是实现按键按下,LED取反
这就需要用到GPIO_ReadOutputDataBit();,在LED里加上这段函数,调用它LED的状态取反
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);
}//实现了端口的电平反转
这段我的理解是,如果按下原来是关就给开,原来是开就给关
光敏传感器控制蜂鸣器
光敏传感器,电位器可以调节高低电平的判断阈值(我不知道具体指哪个且不知道怎么调)
总体代码和上一个差不多
main.c
#include "stm32f10x.h" // Device header
#include "BUZZER.h"
#include "LIGHTSENSOR.h"
int main(void)
{
BUZZER_Init();
LIGHTSENSOR_Init();
while(1)
{
if( LIGHT_GET() == 1 ){
BUZZER_ON();
}
else BUZZER_OFF();
}
}
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;//这里输入模式选择?YES
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB, GPIO_Pin_12);
}
void BUZZER_ON(void){
GPIO_ResetBits(GPIOB, GPIO_Pin_12);//一开始错误在参数GPIOA没改
}
void BUZZER_OFF(void){
GPIO_SetBits(GPIOB, GPIO_Pin_12);
}
BUZZER.h
#ifndef __BUZZER_H
#define __BUZZER_H
void BUZZER_Init(void);
void BUZZER_ON(void);
void BUZZER_OFF(void);
#endif
LIGHTSENSOR.h
#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);
}
uint8_t LIGHT_GET(void){
return GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_13);
}
LIGHTSENSOR.h
#ifndef __LIGHTSENSOR_H
#define __LIGHTSENSOR_H
void LIGHTSENSOR_Init(void);
uint8_t LIGHT_GET(void);
#endif