最终实现效果:按下一个按键,灯亮蜂鸣器响一下。复位后才可按下一个按键。
main.c部分代码
?
#include "led.h"
#include "key.h"
#include "beep.h"
//备注: LED1--PC4 LED2--PC5 LED3--PC6 LED4--PC7 0亮1灭
// WKUP-PA0 KEY2-PE2 KEY3-PE3 KEY4-PE4
int main()
{
u8 key_val;
LED_Init(); //LED初始化
KEY_Init(); //按键初始化
BEEP_Init(); //蜂鸣器初始化
while(1) //使循环不断进行
{
key_val = KEY_Scan();
switch(key_val)
{
case 1: beep_on(); GPIOC->ODR ^= 1 << 4; break; //ODR初始状态高电平1 1异或
1为0 低电平灯亮;再次循环时 ODR为0 0异或1为1 高电平灯灭
case 2: beep_on(); GPIOC->ODR ^= 1 << 5; break;
case 3: beep_on(); GPIOC->ODR ^= 1 << 6; break;
case 4: beep_on(); GPIOC->ODR ^= 1 << 7; break;
}
}
}
?
key.c部分
#include "key.h"
//函数的功能:LED初始化
//形参:void
//返回值:void
//备注:PA0-没有按下低电平,按下为高电平
void KEY_Init(void) //函数的功能:LED初始化(函数名根据习惯自定义)
{
RCC->AHB1ENR |= 1 << 0; //使能GPIOA时钟
RCC->AHB1ENR |= 1 << 4; //使能GPIOE时钟
/*PA0配置*/
GPIOA->MODER &= ~(3 << (2 * 0)); //输入模式
GPIOA->PUPDR &= ~(3 << (2 * 0)); //清零
GPIOA->PUPDR |= 2 << (2 * 0); //配置为下拉模式(此处用无上下拉也可)
/*PE2配置*/
GPIOE->MODER &= ~(3 << (2 * 2)); //输入模式
GPIOE->PUPDR &= ~(3 << (2 * 2)); //清零
GPIOE->PUPDR |= 2 << (1 * 2); //上拉
/*PE3配置*/
GPIOE->MODER &= ~(3 << (2 * 3)); //输入模式
GPIOE->PUPDR &= ~(3 << (2 * 3)); //清零
GPIOE->PUPDR |= 2 << (1 * 3); //上拉
/*PE4配置*/
GPIOE->MODER &= ~(3 << (2 * 4)); //输入模式
GPIOE->PUPDR &= ~(3 << (2 * 4)); //清零
GPIOE->PUPDR |= 2 << (1 * 4); //上拉
}
void delay(u32 t)
{
while(t--);
}
//按键扫描
//形参:void
//返回值:返回1 -- 按键1按下
//备注:PA0 - 没有按下低电平 按下高电平
u8 KEY_Scan(void) //扫描函数
{
//static 让该函数调用完后flag的值依旧为1
static u8 flag = 1; //定义没有按下的状态 0:未按下 1:按下
u8 key = 0; //初始值
if((KEY1 || KEY2 || KEY3 || KEY4) && flag == 1) //此刻是高电平
{
delay(200000); //约10ms 延时消抖:先读 延时 再读
if(KEY1) //此刻是高电平
{
flag = 0; //清零
key = 1;
}
else if(KEY2)
{
flag = 0;
key = 2;
}
else if(KEY3)
{
flag = 0;
key = 3;
}
else if(KEY4)
{
flag = 0;
key = 4;
}
}
else if(!KEY1 && !KEY2 && !KEY3 && !KEY4) //此时低电平0 未按下
{
flag = 1; //为下一次按键按下做准备
}
return key; //如果没有按下返回初始值0 按下则返回1
}
key.h部分
#ifndef _LED_H_
#define _LED_H_
#include <stm32f4xx.h>
void KEY_Init(void);
void delay(u32 t);
u8 KEY_Scan(void);
#define KEY1 GPIOA->IDR & (1 << 0) //宏定义 此时是高电平 按下
#define KEY2 (!(GPIOE->IDR & (1 << 2))) //低电平 按下
#define KEY3 (!(GPIOE->IDR & (1 << 3))) //低电平 按下
#define KEY4 (!(GPIOE->IDR & (1 << 4))) //低电平 按下
#endif
led.c部分
#include "led.h"
void LED_Init(void)
{
//使能GPIO时钟
RCC->AHB1ENR |= 1 << 2; //GPIO时钟使能
//设置PC4工作模式
GPIOC->MODER &= ~(3 << (2 * 4));
GPIOC->MODER |= 1 << (2 * 4); //设为输出模式
//设置输出类型
GPIOC->OTYPER &= ~(1 << 5); //设置为推挽输出
//设置输出速度
GPIOC->OSPEEDR &= ~(3 << (2 * 4));
GPIOC->OSPEEDR |= 2 << (2 * 4); //设置为50Hz
//设置上下拉
GPIOC->PUPDR &= ~(3 << (2 * 4)); //无上下拉
//设置GPIO初始状态
GPIOC->ODR |= 1 << 4; //初始状态为高电平
//设置P5工作模式
GPIOC->MODER &= ~(3 << (2 * 5));
GPIOC->MODER |= 1 << (2 * 5); //设为输出模式
//设置输出类型
GPIOC->OTYPER &= ~(1 << 6); //设置为推挽输出
//设置输出速度
GPIOC->OSPEEDR &= ~(3 << (2 * 5));
GPIOC->OSPEEDR |= 2 << (2 * 5); //设置为50Hz
//设置上下拉
GPIOC->PUPDR &= ~(3 << (2 * 5)); //无上下拉
//设置GPIO初始状态
GPIOC->ODR |= 1 << 5; //初始状态为高电平
//设置P6工作模式
GPIOC->MODER &= ~(3 << (2 * 6));
GPIOC->MODER |= 1 << (2 * 6); //设为输出模式
//设置输出类型
GPIOC->OTYPER &= ~(1 << 7); //设置为推挽输出
//设置输出速度
GPIOC->OSPEEDR &= ~(3 << (2 * 6));
GPIOC->OSPEEDR |= 2 << (2 * 6); //设置为50Hz
//设置上下拉
GPIOC->PUPDR &= ~(3 << (2 * 6)); //无上下拉
//设置GPIO初始状态
GPIOC->ODR |= 1 << 6; //初始状态为高电平
//设置P7工作模式
GPIOC->MODER &= ~(3 << (2 * 7));
GPIOC->MODER |= 1 << (2 * 7); //设为输出模式
//设置输出类型
GPIOC->OTYPER &= ~(1 << 8); //设置为推挽输出
//设置输出速度
GPIOC->OSPEEDR &= ~(3 << (2 * 7));
GPIOC->OSPEEDR |= 2 << (2 * 7); //设置为50Hz
//设置上下拉
GPIOC->PUPDR &= ~(3 << (2 * 7)); //无上下拉
//设置GPIO初始状态
GPIOC->ODR |= 1 << 7; //初始状态为高电平
}
led.h部分
#ifndef _LED_H
#define _LED_H
//防止名称冲突
#include<stm32f4xx.h>
void LED_Init(void); //函数声明
#endif
|