stm32学习-2(按键控制LED灯)

一、LED模块

(1)LED回顾

在上一次的学习中,我们学习了如何点亮LED灯,并且实现了LED灯的闪烁,如果我们想要通过按键来控制LED灯的亮灭,假设按键按下我们会检测到一个信号,此时如果灯是亮的那么就让灯熄灭,如果灯是灭的就让灯亮,这样就可以通过一个按键来控制一个LED灯的亮灭了,可以发现,如果我们把所有的函数都放在主函数里,那代码将非常长,既不利于阅读也不利于代码的移植,因此我们新建一个led.c文件来存放LED有关的函数,新建一个led.h文件作为此文件的头文件

(2)LED模块

我们在文件开始前先做一些准备工作,以便后面的编程,首先我们先把需要的头文件引入,再定义一下我们要初始化的端口,这样当我们需要修改LED的位置时只要修改前面的define就可以了

#include "stm32f10x.h"                  // Device header

#define io_clock RCC_APB2Periph_GPIOA
#define io GPIOA
#define led_1 GPIO_Pin_1
#define led_2 GPIO_Pin_2

然后我们和上次的思路一样,我们先要把LED的那几个GPIO口初始化,我们把它写成一个函数,在这个函数内对端口初始化,在操作LED之前,先调用这个函数来对LED进行初始化,这样其他函数才能正确使用

void led_init()
{
	RCC_APB2PeriphClockCmd(io_clock, ENABLE);
	GPIO_InitTypeDef gpio_init;
	gpio_init.GPIO_Mode = GPIO_Mode_Out_PP;
	gpio_init.GPIO_Pin = led_1 | led_2;
	gpio_init.GPIO_Speed = GPIO_Speed_10MHz;
	GPIO_Init(io, &gpio_init);
	GPIO_SetBits(io, led_1 | led_2);
}

我们把LED需要初始化的代码封装成了一个函数,这样我们要使用LED的时候只要在主函数中条用一下这个初始化函数就可以完成对LED灯的初始化了。

那么接下来我们要实现的就是LED状态翻转函数了,如果LED是亮的话,那么调用这个函数就可以使其灭,反之亦然,我们之前学习的都是LED的输出函数,GPIO也有一些常见的输入函数,便于我们信号的读取,下面是GPIO的一些常用的输入函数

同样我们可以用跳转定义的方法来了解这四个函数,其实从函数名上也可以知道大概,第一个是读取某一位的输入数据,第二个是读取输入寄存器,也就是读取所有位的输入数据,第三个读取的是某一位的输出数据,第四个读取的是输出寄存器的所有值,也就是读取所有位的输出数据,那么这里我们只用第三个来读取LED灯位置的输出数据就可以完成翻转,我们的两个LED位置翻转可以分成两个函数写

void led1_flip()
{
	if (GPIO_ReadOutputDataBit(io, led_1))
	{
		GPIO_ResetBits(io, led_1);
	}
	else
	{
		GPIO_SetBits(io, led_1);
	}
}

void led2_flip()
{
	if (GPIO_ReadOutputDataBit(io, led_2))
	{
		GPIO_ResetBits(io, led_2);
	}
	else
	{
		GPIO_SetBits(io, led_2);
	}
}

到这里我们的LED程序模块就写好了,我们在主程序中只要先初始化,然后在有按键信号来的时候调用一下对应的LED翻转程序就可以了,那我们把这些函数在头文件上声明,使其成为外部可调用函数

#ifndef __LED_H__
#define __LED_H__

void led_init(void);
void led1_flip(void);
void led2_flip(void);

#endif

二、按键模块

经过之前的分析我们知道,按键模块要实现的功能无非就是一个,那就是我们在对应的端口有按键信号时告诉主程序,我们把两个按键分别接在PB6和PB14口上;

先写好初始化按键的程序,和之前写LED的初始化程序思路一样,注意的是这里我们的按键是接在PB口上,因此我们要使能的是GPIOB

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

#define io_clock RCC_APB2Periph_GPIOB
#define io GPIOB
#define key1 GPIO_Pin_6
#define key2 GPIO_Pin_14

void button_init()
{
	RCC_APB2PeriphClockCmd(io_clock, ENABLE);
	GPIO_InitTypeDef gpio_init;
	gpio_init.GPIO_Pin = key1 | key2;
	gpio_init.GPIO_Mode = GPIO_Mode_IPU;
	gpio_init.GPIO_Speed = GPIO_Speed_10MHz;
	GPIO_Init(io, &gpio_init);
}

按键的一端连接低电平,一端连接到单片机的IO口上,所以我们选择的是上拉输入模式(gpio_init.GPIO_Mode = GPIO_Mode_IPU)这样我们在按键按下时得到的信号位低电平信号,在按键没有按下的时候得到的信号位默认的高电平信号;

在检测IO口高低电平时,我们还要注意一下按键的消抖问题,我们暂停20ms再进行检测,这里了解之前读取IO口的函数后,程序的设计和51单片机的差不多

unsigned char get_button()
{
	unsigned char key = 0;
	if (GPIO_ReadInputDataBit(io, key1) == 0)
	{
		Delay_ms(20);
		while (GPIO_ReadInputDataBit(io, key1) == 0);
		Delay_ms(20);
		key = 1;
	}
	else if (GPIO_ReadInputDataBit(io, key2) == 0)
	{
		Delay_ms(20);
		while (GPIO_ReadInputDataBit(io, key2) == 0);
		Delay_ms(20);
		key = 2;
	}
	return key;
}

之后我们和LED一样在头文件上把这两个函数做好声明就完成了按键模块的程序编写

三、主程序

有了按键模块和LED模块后,主程序的设计就显得明朗了,我们无非是读取按键的值,判断按键是否按下,如果按下就调用LED的翻转函数,可以这样设计

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

int main()
{
	unsigned char button;
	led_init();
	button_init();
	while(1)
	{
		button = get_button();
		if (button == 1)
		{
			led1_flip();
		}
		else if (button == 2)
		{
			led2_flip();
		}
	}
	return 0;
}

四、自动开灯

通过之前的学习我们已经熟悉了IO口的输入输出操作了,我们可以用光敏传感器模块来实现一个当环境亮度变暗就自动开灯的程序,我们把光敏传感器模块的DO(数字输出口)接入PB14中,当光线亮时其输出值为0,光线暗时输出为1(可以设置相对的光线比较),我们用之前一样的思路来构建其模块

#include "stm32f10x.h"                  // Device header

#define io_init RCC_APB2Periph_GPIOB
#define io GPIOB
#define sensor_loc GPIO_Pin_14

void sensor_init()
{
	RCC_APB2PeriphClockCmd(io_init, ENABLE);
	GPIO_InitTypeDef gpio_init;
	gpio_init.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	gpio_init.GPIO_Pin = sensor_loc;
	gpio_init.GPIO_Speed = GPIO_Speed_10MHz;
	GPIO_Init(GPIOB, &gpio_init);
}

unsigned char get_sensor()
{
	return GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14);
}

同样我们在头文件对以上函数进行声明,在主函数上对其调用就可以了,当我们检测到PB14口输入高电平时,我们开启LED灯,当我们检测到低电平时熄灭LED灯,通过这样的一个简单地输入输出IO口数据我们就实现了一个黑暗自动开灯的程序

五、总结

通过按键按下来操控LED和黑暗自动开灯程序。我们了解了GPIO口的输入函数,结合之前的知识,我们应该有了对IO口输入和输出的能力。

  • 8
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,这是一个很常见的任务,我可以为您提供一些代码示例来实现这个功能。 首先,您需要连接一个按键和一个LED到您的STM32开发板上。假设您将按键连接到引脚PA0,将LED连接到引脚PB0。 接下来,您需要在代码中初始化这些引脚。这可以通过以下方式完成: ```c GPIO_InitTypeDef GPIO_InitStruct; // 初始化PA0引脚为输入模式 GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // 初始化PB0引脚为输出模式 GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); ``` 在这个例子中,我们将PA0引脚初始化为输入模式,并启用上拉电阻。这意味着当按键没有按下时,PA0引脚将被拉高。当按键按下时,PA0引脚将会被拉低。我们将PB0引脚初始化为输出模式,这意味着我们可以通过在代码中设置它的状态来控制LED的亮度。 接下来,您需要配置外部中断。外部中断是一种特殊的中断,可以在引脚状态发生变化时触发。在这个例子中,我们将使用外部中断来检测按键是否被按下。这可以通过以下方式完成: ```c EXTI_HandleTypeDef EXTI_InitStruct; // 配置外部中断 EXTI_InitStruct.Pin = GPIO_PIN_0; EXTI_InitStruct.Mode = EXTI_MODE_INTERRUPT; EXTI_InitStruct.Trigger = EXTI_TRIGGER_FALLING; HAL_EXTI_SetConfigLine(&EXTI_InitStruct, EXTI_LINE_0); ``` 在这个例子中,我们将外部中断配置为检测PA0引脚的下降沿。这意味着当按键被按下时,外部中断将会触发。 最后,您需要实现中断处理函数,以便在按键被按下时切换LED的状态。这可以通过以下方式完成: ```c void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if (GPIO_Pin == GPIO_PIN_0) { // 切换LED的状态 HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0); } } ``` 在这个例子中,我们实现了一个名为`HAL_GPIO_EXTI_Callback`的中断处理函数。当外部中断被触发时,这个函数将被调用。在这个函数中,我们检查触发中断的引脚是否为PA0引脚。如果是,我们将使用`HAL_GPIO_TogglePin`函数来切换LED的状态。 以上就是使用stm32外部中断实现按键控制LED的示例代码。希望这能帮助到您!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值