GPIO输出控制之LED闪烁、LED流水灯以及蜂鸣器应用案例

系列文章目录

STM32之GPIO(General Purpose Input/Output,通用型输入输出)



前言

提示:本文主要用作在学习江协科大STM32入门教程后做的归纳总结笔记,旨在学习记录,如有侵权请联系作者

本文主要探讨stm32的GPIO输出控制模式,最后通过几个简单的应用案例(LED闪烁、LED流水灯以及蜂鸣器)实现了GPIO的输出控制功能。


一、LED和蜂鸣器简介

1.1 LED

LED是一种发光二极管,它正向通电点亮,反向通电不亮 。LED电路符号如下,左边是正级,右边是负极。
在这里插入图片描述

如下为LED的实物图,LED内部较小的是正极,较大的是负极。

在这里插入图片描述

1.2 蜂鸣器

蜂鸣器分有源蜂鸣器、无源蜂鸣器两种。

有源蜂鸣器: 内部自带振荡源,将正负极接上直流电压即可持续发声,频率固定。
无源蜂鸣器: 内部不带振荡源,需要控制器提供振荡脉冲才可发声,调整提供振荡脉冲的频率,可发出不同频率的声音。

如上左图所示就是有源蜂鸣器的内部电路图,这里用了一个PNP型的三极管开关电路进行驱动,将VCC和GND分别接上正负极的供电。如果引脚2接低电平,蜂鸣器就会响。反之,接高电平,蜂鸣器就关闭。

1.3 面包板

简单讲一下面包板,如下所示分别为面包板的正反面以及内部金属爪的示例图。

面包板正面如下:

在这里插入图片描述

面包板背面如下:

在这里插入图片描述

金属爪示意图如下:

在这里插入图片描述

对于面包板,我们只需要知道上面两排以及下面两排打横是连通的,中间竖着的是连通的即可。至于内部就是上面看到的金属爪了,当我们插入一个电子元器件的时候就会夹住从而接入电路了。

二、LED硬件电路

使用stm32的GPIO口驱动LED电路有两种方式,分别是低电平驱动以及高电平驱动。

这里的限流电阻一般都是要接的,一方面它可以防止LED因为电流过大而烧毁,另一方面它可以调整LED的亮度,如果你觉得LED太亮可以适当的增大限流电阻的阻值。

要选择哪一种电平驱动方式就得看IO口高低电平的驱动能力如何了。在前面GPIO的章节里有讲到,在GPIO的推挽输出模式下,高低电平均有较强的驱动能力,所以两种方式都可以。在单片机的电路里,一般倾向使用低电平驱动的方式。

2.1 低电平驱动电路

在这里插入图片描述
上图所示为低电平驱动电路结构图,LED正极接3.3v,负极通过一个限流电阻接到PA0上。当PA0输出低电平时,LED两端就会产生电压差,就会形成正向导通的电流,这样LED就会点亮。当PA0输出高电平时,因为LED两端都是3.3v的电压,不会形成电流,所以高电平LED就会熄灭。这就是低电平驱动电路啦。

2.2 高电平驱动电路

在这里插入图片描述
上图所示为高电平驱动电路结构图,LED负极接到GND,正极通过一个限流电阻接到PA0上。当PA0输出高电平时,LED两端就会产生电压差,就会形成正向导通的电流,这样LED就会点亮。当PA0输出低电平时,因为LED两端都是GND,不会形成电流,所以低电平LED就会熄灭。这就是高电平驱动电路啦。

三、蜂鸣器硬件电路

这里使用了三极管开关的驱动方案。三极管开关是最简单的驱动电路了,对于功率稍微大一点的 ,直接用IO口驱动会导致STM32负担过重,这时可以用一个三极管驱动电路来完成驱动任务。

需要注意的是,PNP型的三极管最好接在上边,NPN型的三极管最好接到下边,这是因为三极管的通断是需要在发射极和基极产生一定的开启电压的,如果将负载接在发射极这边,可能会导致三极管不能开启。

3.1 PNP型三极管驱动电路

在这里插入图片描述

上图所示为PNP型三极管的驱动电路,三极管的左边是基极(b),带箭头的是发射极(e),剩下的是集电极c。当基极(b)给低电平时,三极管就会导通,再通过3.3V和GND就可以给蜂鸣器提供驱动电流了。当基极(b)给高电平时,三极管截止,蜂鸣器没有电流。

3.2 NPN型三极管驱动电路

在这里插入图片描述
上图所示为NPN型三极管的驱动电路,同样,左边是基极(b),带箭头的是发射极(b),剩下的是集电极c。它的驱动逻辑和上面的是相反的,当基极(b)给高电平时,三极管导通。当基极(b)给低电平时,三极管断开。

有关三极管的NPN型与PNP型的更加详细介绍可以参考一下我的另一篇文章:三极管(NPN型、PNP型)工作原理

四、GPIO输出控制案例

4.1 LED闪烁

本案例实现了一个通过控制GPIO的PA0引脚输出高低电平实现LED闪烁的功能。

4.1.1 电路接线图

在这里插入图片描述

4.1.2 应用案例代码

延时头文件Delay.h:

#ifndef __DELAY_H
#define __DELAY_H

void Delay_us(uint32_t us);
void Delay_ms(uint32_t ms);
void Delay_s(uint32_t s);

#endif

延时实现文件Delay.c:

#include "stm32f10x.h"

/**
  * @brief  微秒级延时
  * @param  xus 延时时长,范围:0~233015
  * @retval 无
  */
void Delay_us(uint32_t xus)
{
	SysTick->LOAD = 72 * xus;				//设置定时器重装值
	SysTick->VAL = 0x00;					//清空当前计数值
	SysTick->CTRL = 0x00000005;				//设置时钟源为HCLK,启动定时器
	while(!(SysTick->CTRL & 0x00010000));	//等待计数到0
	SysTick->CTRL = 0x00000004;				//关闭定时器
}

/**
  * @brief  毫秒级延时
  * @param  xms 延时时长,范围:0~4294967295
  * @retval 无
  */
void Delay_ms(uint32_t xms)
{
	while(xms--)
	{
		Delay_us(1000);
	}
}
 
/**
  * @brief  秒级延时
  * @param  xs 延时时长,范围:0~4294967295
  * @retval 无
  */
void Delay_s(uint32_t xs)
{
	while(xs--)
	{
		Delay_ms(1000);
	}
} 

主程序文件main.c:

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

int main(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_0;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	while (1)
	{
		GPIO_ResetBits(GPIOA, GPIO_Pin_0);
		Delay_ms(500);
		GPIO_SetBits(GPIOA, GPIO_Pin_0);
		Delay_ms(500);
		
		GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET);
		Delay_ms(500);
		GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET);
		Delay_ms(500);
		
		GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)0);
		Delay_ms(500);
		GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)1);
		Delay_ms(500);
	}
}

4.1.3 应用案例分析

以上代码实现了通过GPIOA的PA0引脚控制一个LED灯闪烁的功能。主要使用了STM32标准外设库函数来配置GPIO端口,以下是对代码的详细分析:

1. 配置时钟:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); 使能GPIOA端口的时钟。在STM32中,任何外设在使用前都需要先使能其时钟。

2. GPIO初始化:

  1. 定义了一个GPIO_InitTypeDef结构体变量GPIO_InitStructure,并通过它来配置GPIOA的PA0引脚。
  2. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 设置PA0为推挽输出模式。
  3. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; 指定配置的是GPIOA的PA0引脚。
  4. GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz; 设置GPIO的输出速度为50MHz,尽管这个速度对于简单的LED闪烁来说可能过高,但它不会影响LED的功能。
  5. GPIO_Init(GPIOA, &GPIO_InitStructure); 将上述配置应用到GPIOA上。

3. LED闪烁循环:

  1. 程序进入一个无限循环,通过改变PA0引脚的状态来控制LED的亮灭。
  2. GPIO_ResetBits(GPIOA, GPIO_Pin_0); 和 GPIO_SetBits(GPIOA, GPIO_Pin_0); 分别用于将PA0引脚置为低电平(LED熄灭)和高电平(LED点亮)。
  3. GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET); 和 GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET); 是另一种写入单个GPIO引脚的方法,效果与上面的函数相同。
  4. GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)0); 和 GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)1); 使用了枚举类型BitAction来指定引脚状态,这里(BitAction)0和(BitAction)1分别对应Bit_RESET和Bit_SET。
  5. Delay_ms(500);:每次状态改变后,程序都会暂停500毫秒,以实现闪烁效果。

总结: 这段代码通过配置GPIOA的PA0引脚为推挽输出模式,并在一个无限循环中交替地将其置为高电平和低电平,从而控制连接在该引脚上的LED灯闪烁。同时,代码中展示了两种设置GPIO引脚状态的方法。

4.2 LED流水灯

本案例实现了一个简单的LED流水灯功能。

4.2.1 电路接线图

在这里插入图片描述

4.2.2 应用案例代码

主程序文件main.c:

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

int main(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_All;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	while (1)
	{
		GPIO_Write(GPIOA, ~0x0001);	//0000 0000 0000 0001
		Delay_ms(100);
		GPIO_Write(GPIOA, ~0x0002);	//0000 0000 0000 0010
		Delay_ms(100);
		GPIO_Write(GPIOA, ~0x0004);	//0000 0000 0000 0100
		Delay_ms(100);
		GPIO_Write(GPIOA, ~0x0008);	//0000 0000 0000 1000
		Delay_ms(100);
		GPIO_Write(GPIOA, ~0x0010);	//0000 0000 0001 0000
		Delay_ms(100);
		GPIO_Write(GPIOA, ~0x0020);	//0000 0000 0010 0000
		Delay_ms(100);
		GPIO_Write(GPIOA, ~0x0040);	//0000 0000 0100 0000
		Delay_ms(100);
		GPIO_Write(GPIOA, ~0x0080);	//0000 0000 1000 0000
		Delay_ms(100);
	}
}

延迟函数的实现以及头文件已经在上面的案例中贴过了,这里就不再累述了。

4.2.3 应用案例分析

该代码前面部分跟上一个LED闪烁的案例基本一致,其实操作GPIO的套路都是差不多的。首先是使能GPIO外设时钟,然后再初始化进行GPIO端口属性设置,最后就是对GPIO的某个端口进行读写设置。这里就不再累述了。

具体步骤如下

  • 使能GPIOA时钟:确保GPIOA引脚可以被配置和操作。
  • 配置GPIOA所有引脚为推挽输出模式。
  • 主循环中:依次设置GPIOA不同引脚的状态,并通过延时函数实现LED的流水效果。

总结: 这段代码实现了一个简单的LED流水灯效果,通过不断变化GPIOA引脚的状态,依次点亮连接在GPIOA的不同引脚上的LED,并通过延时函数控制LED点亮的时间间隔。

4.3 蜂鸣器

本案例实现了一个蜂鸣器按照一定的频率进行工作的功能。

4.3.1 电路接线图

在这里插入图片描述

4.3.2 应用案例代码

主程序文件main.c:

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

int main(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);
	
	while (1)
	{
		GPIO_ResetBits(GPIOB, GPIO_Pin_12);
		Delay_ms(100);
		GPIO_SetBits(GPIOB, GPIO_Pin_12);
		Delay_ms(100);
		GPIO_ResetBits(GPIOB, GPIO_Pin_12);
		Delay_ms(100);
		GPIO_SetBits(GPIOB, GPIO_Pin_12);
		Delay_ms(700);
	}
}

延迟函数的实现以及头文件已经在上面的案例中贴过了,这里就不再累述了。

4.3.3 应用案例分析

本案例的实现代码基本思路是跟第一个案例是一致的,只不过是把控制LED变成了控制蜂鸣器的I/O,这里就不再累述了。

  • 34
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 这个问题是关于如何用Arduino控制蜂鸣器LED灯的。 需要使用Arduino板、蜂鸣器LED等器件进行连接和编程控制。具体的步骤包括连接电路、编写代码、上传程序等等。 关于具体操作细节,可以参考相关的Arduino教程和资料。 ### 回答2: arduino是一种高性能控制板,经常用于嵌入式开发。它可以通过编程实现各种功能。本文将介绍如何使用arduino控制蜂鸣器led灯。 首先,我们需要将蜂鸣器led灯连接到arduino板上。连接蜂鸣器不难,只需要将蜂鸣器的正极连接到数字引脚2,将负极连接到arduino板的GND。连接led灯也很简单,将正极连接到数字引脚9,将负极连接到GND。 在编程前,我们需要知道怎样控制输入和输出。在本例中,我们将使用digitalRead()输入读取和digitalWrite()输出信号。输入信号指的是按键按下的信号,输出信号指的是输出蜂鸣器led灯的信号。 在arduino中,数字输入和输出信号可以通过digitalRead()和digitalWrite()函数读取和写入。在连接了按键的电路中,按键被当做一个数字输入,读取它的状态之后控制蜂鸣器led灯。 以下是示例代码: int LED = 9; // 设置LED的数字引脚为9 int buzzer = 2; // 设置蜂鸣器的数字引脚为2 int button = 7; // 设置按键的数字引脚为7 void setup() { pinMode(buzzer, OUTPUT); // 将蜂鸣器引脚设置为输出 pinMode(LED, OUTPUT); // 将LED引脚设置为输出 pinMode(button, INPUT); // 将按键引脚设置为输入 } void loop() { int buttonVal = digitalRead(button); // 读取按键状态 if (buttonVal == HIGH) { // 如果按键按下 digitalWrite(LED, HIGH); // 点亮LED tone(buzzer, 1000); // 产生1000Hz的声音 } else { // 如果按键未按下 digitalWrite(LED, LOW); // 熄灭LED noTone(buzzer); // 不发声 } } 以上代码会在按键按下时点亮LED并发出声音。当按键未按下时,LED熄灭且蜂鸣器不发声。这是一个基本的arduino控制按键的例子,您可以根据需求进行变更,例如更改按键连线和数字引脚。 总之,使用arduino进行蜂鸣器LED灯的控制是一种非常实用的技能。如果您需要了解更多详细的借口实现,可以查看arduino官方文档。希望本文能对你的制作有所帮助! ### 回答3: Arduino按键控制蜂鸣器LED灯是一个非常简单而有趣的项目。首先,我们需要连接硬件,这包括连接一个蜂鸣器和一个LED灯,之后我们需要连接一个按钮。一旦我们将它们连接到Arduino板上,我们就可以开始编程。 我们需要使用Arduino IDE来开发代码,然后使用USB将代码上传到Arduino板中。下面是一些示例代码和解释: 首先,我们需要定义引脚来控制蜂鸣器LED灯,这可以通过以下代码完成: const int buzzerPin = 8; // 蜂鸣器引脚 const int ledPin = 13; // LED灯引脚 const int buttonPin = 2; // 按钮引脚 接下来,我们需要设置引脚模式,以便Arduino知道各个引脚的作用: void setup() { pinMode(buzzerPin, OUTPUT); // 设置蜂鸣器引脚为输出模式 pinMode(ledPin, OUTPUT); // 设置LED灯引脚为输出模式 pinMode(buttonPin, INPUT); // 设置按钮引脚为输入模式 } 现在,我们可以编写一个函数来控制蜂鸣器: void beep(int onTime, int offTime) { digitalWrite(buzzerPin, HIGH); // 设置蜂鸣器引脚为高电平,发出声音 delay(onTime); // 开启持续时间 digitalWrite(buzzerPin, LOW); // 关闭蜂鸣器引脚 delay(offTime); // 停止持续时间 } 接下来,我们可以编写一个函数来控制LED灯: void blink(int onTime, int offTime) { digitalWrite(ledPin, HIGH); // 设置LED灯引脚为高电平,发出亮光 delay(onTime); // 开启持续时间 digitalWrite(ledPin, LOW); // 关闭LED灯引脚 delay(offTime); // 停止持续时间 } 现在我们可以编写主程序了,通过按下按钮来控制蜂鸣器LED灯。当我们按下按钮时,蜂鸣器LED灯都会发出信号。以下是完整的代码: const int buzzerPin = 8; // 蜂鸣器引脚 const int ledPin = 13; // LED灯引脚 const int buttonPin = 2; // 按钮引脚 void setup() { pinMode(buzzerPin, OUTPUT); // 设置蜂鸣器引脚为输出模式 pinMode(ledPin, OUTPUT); // 设置LED灯引脚为输出模式 pinMode(buttonPin, INPUT); // 设置按钮引脚为输入模式 } void beep(int onTime, int offTime) { digitalWrite(buzzerPin, HIGH); // 设置蜂鸣器引脚为高电平,发出声音 delay(onTime); // 开启持续时间 digitalWrite(buzzerPin, LOW); // 关闭蜂鸣器引脚 delay(offTime); // 停止持续时间 } void blink(int onTime, int offTime) { digitalWrite(ledPin, HIGH); // 设置LED灯引脚为高电平,发出亮光 delay(onTime); // 开启持续时间 digitalWrite(ledPin, LOW); // 关闭LED灯引脚 delay(offTime); // 停止持续时间 } void loop() { int buttonStatus = digitalRead(buttonPin); // 读取按钮状态 if (buttonStatus == HIGH) { // 如果按钮被按下 beep(100, 100); // 发出蜂鸣器信号 blink(100, 100); // 发出LED灯信号 } } 简而言之,在该项目中,我们使用按钮控制蜂鸣器LED灯。当按下按钮时,Arduino会通过控制蜂鸣器发出声音,同时通过LED灯发出亮光,这个项目可以作为初学者了解Arduino编程的基础。如果你想进一步拓展这个项目,可以调整蜂鸣器LED灯的频率和持续时间,或者编写更高级的代码控制多个LED蜂鸣器,并且可以将其与其他传感器集成起来来控制更多的设备。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值