大家好,我是老耿,高职青椒一枚,一直从事单片机、嵌入式、物联网等课程的教学。对于高职的学生层次,同行应该都懂的,老师在课堂上教学几乎是没什么成就感的。正因如此,才有了借助 CSDN 平台寻求认同感和成就感的想法。在这里,我准备陆续把自己花了很多心思的教学设计分享出来,主要面向广大师生朋友,单片机老鸟就略过吧。欢迎点赞+关注,各位的支持是本人持续输出的动力,多谢多谢!
本篇我们延续上一章闪烁灯的主题,通过 STM32 的 IO 口来控制开发板上的有源蜂鸣器,实现发声控制。通过本篇的学习,你将进一步了解 STM32 的 IO 口作为输出口使用的方法。
【学习目标】
- 理解蜂鸣器的电路原理
- 续领悟 GPIO 的初始化和电平控制
- 会利用函数手册查找、使用函数
一、认识蜂鸣器
1.1 蜂鸣器的应用和分类
蜂鸣器是一种一体化结构的电子讯响器,采用直流供电,广泛应用于计算机、打印机、复印机、报警器、电子玩具、汽车电子设备、电话机等电子产品中作发声器件。蜂鸣器按构造方式的不同,可分为电磁式蜂鸣器和压电式蜂鸣器;按其驱动方式的不同,可分为有源蜂鸣器和无源蜂鸣器。我们开发板上的蜂鸣器是电磁式的有源蜂鸣器,如图1所示。
这里的有源或无源不是指电源的“源”,而是指有没有自带振荡源。有源蜂鸣器内部自带了振荡电路,一通电就会发声,声音频率固定;无源蜂鸣器则没有自带振荡电路,必须外部提供 2~5kHz 左右的方波驱动,才能发声,音调也会随驱动信号的频率变化而改变。
1.2 蜂鸣器的驱动电路
上一篇,我们利用 STM32 的 IO 口去直接驱动 LED。本章的蜂鸣器,是否也能直接驱动呢?让我们来简单分析下:STM32F1 的单个 IO 最大可以提供 25mA 电流(来自数据手册),而蜂鸣器的驱动电流大概是 30mA,两者十分相近,但是全盘考虑,STM32F1 整个芯片的电流,最大也就 150mA,如果用 IO 口直接驱动蜂鸣器,其他地方用电就得省着点了。因此,在开发板的电路设计上,是将 IO 口信号通过三极管扩流后再驱动蜂鸣器,如图2所示,这样只需要提供不到 1mA 的电流就足够了。
从上图可知,蜂鸣器的驱动信号连接在 STM32 的 PB3 引脚上,用一个 NPN 三极管 Q7 来驱动蜂鸣器,R55 主要用于防止蜂鸣器的误发声。当 PB3 输出高电平的时候,蜂鸣器发声;当 PB3 输出低电平的时,蜂鸣器停止发声。由此可见,IO 口使用虽然简单,但是和外部电路的匹配设计,还是十分讲究的,考虑越多,设计就越可靠,可能出现的问题也就越少。
二、蜂鸣器编程实践
2.1 任务描述
实验现象很简单,我们让开发板上的蜂鸣器发出“嘀”…“嘀”的鸣响。这个实验的目的在于进一步熟悉 IO 口的使用,如果大家明白了上面蜂鸣器的发声原理,就会发现这个实验的控制方式跟上一章的闪烁灯如出一辙,也是“高电平—延时—低电平—延时”的循环套路。然而,PB3 这个引脚跟其他 IO 口相比有点特殊,我们对它初始化的时候还有一些附加操作,详见下面的代码分析。
2.2 工程文件清单
按照上一章对工程文件的管理,控制一类新的硬件就增加一对与之匹配的驱动文件,即图3中的 beep.c 和 beep.h。
2.3 工程代码剖析
1. beep.h 源码剖析
和上一章控制 LED 类似,代码清单1里定义了两个宏:BEEP_ON 和 BEEP_OFF,用来实现向 PB3 输出高电平和低电平的操作,这样既简化了书写,还能见名知意。此外,头文件里肯定少不了函数声明,这里只有一个蜂鸣器端口初始化的函数。
//-----------------------------------------------------------------------
// 代码清单1:beep.h文件源码
//-----------------------------------------------------------------------
#ifndef _BEEP_H_
#define _BEEP_H_
#include "stm32f10x.h"
//------------------------------------------------------------------------
// 端口宏定义
//------------------------------------------------------------------------
#define BEEP_PIN GPIO_Pin_3
//------------------------------------------------------------------------
// 库函数操作宏定义
//------------------------------------------------------------------------
#define BEEP_ON GPIO_SetBits(GPIOB, BEEP_PIN)
#define BEEP_OFF GPIO_ResetBits(GPIOB, BEEP_PIN)
#define BEEP_TOG GPIO_WriteBit(GPIOB, BEEP_PIN, \
(BitAction)(1-GPIO_ReadOutputDataBit(GPIOB, BEEP_PIN)))
//------------------------------------------------------------------------
// 函数声明
//------------------------------------------------------------------------
void Beep_Init(void); //蜂鸣器端口初始化函数
#endif
2. beep.c 源码剖析
如代码清单2所示,该文件只有一个 Beep_Init() 函数,完成对蜂鸣器 IO 口的初始化。
/**
************************************************************************
* 代码清单2:beep.c
* 描 述:蜂鸣器驱动
* 平 台:OneNET STM32开发板V3.2
* 作 者:老耿
* 日 期:yyyy/mm/dd
* 固 件 库:ST3.5.0
* 版 本:V1.0
* 说 明:初始化即可
* 修改记录:无
************************************************************************
**/
//----------------------------------------------------------------------
// 必要的头文件
//----------------------------------------------------------------------
#include "beep.h"
/**
************************************************************************
* 函 数 名:Beep_Init
* 功 能:蜂鸣器IO口初始化
* 入口参数:无
* 出口参数:无
* 说 明:注意PB3引脚的特殊性
************************************************************************
**/
void Beep_Init(void)
{
//定义一个GPIO初始化对象(结构体)
GPIO_InitTypeDef gpio_initstruct;
//打开必要的外设时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE);
//PB3引脚有特殊性,需要禁用默认的JTAG功能
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
//填充初始化结构体,并执行生效
gpio_initstruct.GPIO_Pin = BEEP_PIN;
gpio_initstruct.GPIO_Mode = GPIO_Mode_Out_PP;
gpio_initstruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &gpio_initstruct);
//上电蜂鸣器关闭
BEEP_OFF;
}
大家应该看到了,上面的初始化跟上一章的 LED 端口初始化相比,还是有点不一样的。STM32F10x 系列的 MCU 复位后,PA13/14/15 以及 PB3/4 默认配置为 JTAG 功能。但是,这里的 PB3 并非 JTAG 调试引脚,于是就有了调用 GPIO_PinRemapConfig() 这个引脚重映射库函数,而参数
GPIO_Remap_SWJ_JTAGDisable 的意思是禁用 JTAG 调禁模式,使能 SW 调试模式。由于 SW调试模式并不使用 PB3 引脚,这样我们就即保障了程序可以正常地下载和调试,又可以用 PB3 作为普通 IO 口控制蜂鸣器了。
由此可见,PB3 已经不是单纯的 IO 口了,还附加了调试功能。因此,我们在初始化的时候还打开了IO口复用这个外设(RCC_APB2Periph_AFIO)的时钟。
3. main.c源码剖析
主程序很简单,见代码清单3,请结合注释来阅读。
/**
******************************************************
* 代码清单3:main.c
* 项 目:有源蜂鸣器
* 任务描述:上电后嘀嘀嘀
* 实验平台:OneNET STM32开发板V3.2
* 作 者:老耿
* 日 期:yyyy/mm/dd
******************************************************
**/
//-----------------------------------------------------
// 必要的头文件
//-----------------------------------------------------
#include "delay.h"
#include "beep.h"
//-----------------------------------------------------
// 主函数
//-----------------------------------------------------
int main()
{
delay_init(); //延时初始化
Beep_Init(); //蜂鸣器初始化
//主循环
while(1)
{
BEEP_ON;
delay_ms(300);
BEEP_OFF;
delay_ms(300);
//或者简化成以下两句
//BEEP_TOG;
//delay_ms(300);
}
}
三、验证与测试
同样,我们通过ST-Link下载代码,下载完成后,蜂鸣器开始“嘀嘀嘀”鸣响,间隔为0.3秒左右,符合预期设计。
至此,我们的本章的学习就结束了。作为 STM32 的入门第二个例子,进一步介绍了 GPIO 作为输出口的使用方法,同时巩固了前面知识的学习。希望大家在开发板上实际验证一下,从而加深印象。
(本文完)