STM32入门开发操作记录(三)——按键控制LED

一、模块化

  前篇介绍了如何向项目添加模块,本篇将进一步介绍模块的编写与封装。随着模块的增加,需要用到Manage Project Items,以便于快速新建目录、添加已有文件和调整目录次序请添加图片描述
  新建模块Hardware,与第一篇创建主函数文件同理,在目录下新建两组C语言源代码文件和头文件,拓展名分别为.c.h,并在Path Include完成路径添加
请添加图片描述

二、LED交替闪烁

  通过构建LED驱动模块简化灯控程序的代码。在A1A2端口接入LED,完成模块构建后运行主函数。

1. LED.c

#include "stm32f10x.h"

// LED端口初始化
void LED_Init(void)
{
	// 使能/失能APB2的外设时钟 -> 开启IO端口A时钟
	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;	// PA1和PA2引脚
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		// 最大速度50MHz
	
	// 配置端口模式 -> 初始化GPIOA外设时钟
	GPIO_Init(GPIOA, &GPIO_InitStructure);
}

// 点亮A1灯
void LED1_ON(void)
{
	GPIO_ResetBits(GPIOA, GPIO_Pin_1);
}

// 熄灭A1灯
void LED1_OFF(void)
{
	GPIO_SetBits(GPIOA, GPIO_Pin_1);
}

// 点亮A2灯
void LED2_ON(void)
{
	GPIO_ResetBits(GPIOA, GPIO_Pin_2);			// 低电平:点亮LED2
}

// 熄灭A2灯
void LED2_OFF(void)
{
	GPIO_SetBits(GPIOA, GPIO_Pin_2);			// 高电平:熄灭LED2
}

2. LED.h

#ifndef __LED_H		// 如果__LED_H未被定义,则执行关键字#define与#endif之间的命令
#define __LED_H

// 对模块外部声明以下函数可被调用
int main(void);		
void LED1_ON(void);
void LED1_OFF(void);
void LED2_ON(void);
void LED2_OFF(void);

#endif

3. 主函数

#include "stm32f10x.h"	// 器件模块
#include "Delay.h"		// 延时模块
#include "LED.h"		// LED驱动模块

// 双灯交替闪烁
int main(void)
{
	LED_Init();		// LED端口初始化
	
	while(1)
	{
		LED1_ON();
		LED2_OFF();
		Delay_ms(200);
		LED1_OFF();
		LED2_ON();
		Delay_ms(200);
	}
}

三、按键控制LED

  通过两个按键分别控制两个LED的亮灭,在A1A2端口接入LEDB1B11端口与零线之间接入按键。(除了上篇提过的J-Link调试端口,其他GPIO均可随意使用)
请添加图片描述

  按下按键时,开关闭合,电流导入零线B端输入低电平0松开按键时,开关断开,B端输入高电平1。由图可见,按键端口在常态下输入高电平,而在按键按下与松开的过程中存在电流波动,称为按键抖动,需要进行延时消除处理。
请添加图片描述

1. Key.c

  根据上文分析,按键按下一次产生的电平变化可被程序检测,并向LED驱动模块发出控制信号,其数据类型为uint8_t,即unsigned char.

#include "stm32f10x.h"
#include "Delay.h"

// 按键端口初始化
void Key_Init(void)
{
	// 使能/失能APB2的外设时钟 -> 开启IO端口B时钟
	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;	// PBA1和PB11引脚
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		// 最大速度50MHz
	
	// 配置端口模式 -> 初始化GPIOB外设时钟
	GPIO_Init(GPIOB, &GPIO_InitStructure);
}

// 监控按键信号
uint8_t Key_GetNum(void)
{
	// 初始化信号:松开
	uint8_t KeyNum = 0;
	
	// 检测到B1输入低电平
	if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1)==0)
	{
		Delay_ms(20);	// 消除按键抖动:按下
		while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1)==0);	// 持续按下,直至松开
		Delay_ms(20);	// 消除按键抖动:松开
		KeyNum = 1;		// B1端按键被按下了一次
	}
	
	// 检测到B11输入低电平
	if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11)==0)
	{
		Delay_ms(20);	// 消除按键抖动:按下
		while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11)==0);	// 持续按下,直至松开
		Delay_ms(20);	// 消除按键抖动:松开
		KeyNum = 2;		// B11端按键被按下了一次
	}

	return KeyNum;	// 发送按键信号
}

2. Key.h

#ifndef __KEY_H		// 如果__KEY_H未被定义,则执行关键字#define与#endif之间的命令
#define __KEY_H

// 对模块外部声明以下函数可被调用
void Key_Init(void);
uint8_t Key_GetNum(void);

#endif

3. LED.c

#include "stm32f10x.h"

// LED端口初始化
void LED_Init(void)
{
	// 使能/失能APB2的外设时钟 -> 开启IO端口A时钟
	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;	// PA1和PA2引脚
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		// 最大速度50MHz
	
	// 配置端口模式 -> 初始化GPIOA外设时钟
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	// 端口电平初始化:高电平,熄灭
	GPIO_SetBits(GPIOA, GPIO_Pin_1 | GPIO_Pin_2);
}

// LED1开关:切换电平输入
void LED1_Turn(void)
{
	// A1端LED输出低电平:点亮
	if (GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_1) == 0)
	{
		GPIO_SetBits(GPIOA, GPIO_Pin_1);	// 熄灭
	}
	else
	{
		GPIO_ResetBits(GPIOA, GPIO_Pin_1);
	}
}

// LED2开关:切换电平输入
void LED2_Turn(void)
{
	// A1端LED输出低电平:点亮
	if (GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_2)==0)
	{
		GPIO_SetBits(GPIOA, GPIO_Pin_2);	// 熄灭
	}
	else
	{
		GPIO_ResetBits(GPIOA, GPIO_Pin_2);
	}
}

4. LED.h

#ifndef __LED_H		// 如果__LED_H未被定义,则执行关键字#define与#endif之间的命令
#define __LED_H

// 对模块外部声明该函数可被调用
void LED_Init(void);		
void LED1_Turn(void);
void LED2_Turn(void);

#endif

5. 主函数

#include "stm32f10x.h"	// 器件模块
#include "Delay.h"		// 延时模块
#include "LED.h"		// LED驱动模块
#include "Key.h"		// 按键监控模块

uint8_t KeyNum;		// 定义全局变量:按键信号

// 按键控制LED![请添加图片描述](https://i-blog.csdnimg.cn/direct/ab1af9a1642b4efea4369bcebdbb7544.jpeg)

int main(void)
{
	// 端口初始化
	LED_Init();
	Key_Init();
	
	while(1)
	{
		// 监控并接收按键端口信号
		KeyNum = Key_GetNum();
		
		// B1按键控制A1灯:按下一次切换亮灭
		if (KeyNum == 1)
		{
			LED1_Turn();
		}
		
		// B11按键控制A2灯:按下一次切换亮灭
		if (KeyNum == 2)
		{
			LED2_Turn();
		}
	}
}

请添加图片描述

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值