STM32 GPIO控制蜂鸣器的方法详解
文章目录
01. 蜂鸣器简介
蜂鸣器是一种一体化结构的电子讯响器,采用直流电压供电,广泛应用于计算机、打印机、复印机、报警器、电子玩具、汽车电子设备、电话机、定时器等电子产品中作发声器件。蜂鸣器主要分为压电式蜂鸣器和电磁式蜂鸣器两种类型。
探索者 STM32F4 开发板板载的蜂鸣器是电磁式的有源蜂鸣器,如图 7.1.1 所示:
这里的有源不是指电源的“源”,而是指有没有自带震荡电路,有源蜂鸣器自带了震荡电路,一通电就会发声;无源蜂鸣器则没有自带震荡电路,必须外部提供 2~5Khz 左右的方波驱动,才能发声。
02. 硬件设计
蜂鸣器在硬件上也是直接连接好了的,不需要经过任何设置,直接编写代码就可以了。蜂鸣器的驱动信号连接在 STM32F4 的 PF8 上。
03. 程序示例一
蜂鸣器不叫
beep.h文件
#ifndef __BEEP_H__
#define __BEEP_H__
#include "sys.h"
//蜂鸣器初始化
void BEEP_Init(void);
#define BEEP PFout(8)
#endif /*__BEEP_H__*/
beep.c文件
#include "beep.h"
//蜂鸣器初始化
void BEEP_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN;
//使能时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
//初始化GPIO
GPIO_Init(GPIOF, &GPIO_InitStruct);
//设置默认低电平
GPIO_ResetBits(GPIOF, GPIO_Pin_8);
}
main.c文件
#include "stm32f4xx.h"
#include "delay.h"
#include "led.h"
#include "beep.h"
int main(void)
{
//初始化
delay_init(168);
LED_Init();
BEEP_Init();
//蜂鸣器不叫
GPIO_ResetBits(GPIOF, GPIO_Pin_8);
}
04. 程序示例二
蜂鸣器叫
main.c文件
#include "stm32f4xx.h"
#include "delay.h"
#include "led.h"
#include "beep.h"
int main(void)
{
//初始化
delay_init(168);
LED_Init();
BEEP_Init();
GPIO_SetBits(GPIOF, GPIO_Pin_8);
}
05. 程序实例三
蜂鸣器循环叫1秒 不叫1秒
main.c
#include "stm32f4xx.h"
#include "delay.h"
#include "led.h"
#include "beep.h"
int main(void)
{
//初始化
delay_init(168);
LED_Init();
BEEP_Init();
//蜂鸣器不叫
GPIO_ResetBits(GPIOF, GPIO_Pin_8);
GPIO_ResetBits(GPIOF, GPIO_Pin_9);
delay_ms(1000);
//蜂鸣器叫
GPIO_SetBits(GPIOF, GPIO_Pin_8);
GPIO_SetBits(GPIOF, GPIO_Pin_9);
delay_ms(1000);
}
位带操作
main.c文件
#include "stm32f4xx.h"
#include "delay.h"
#include "led.h"
#include "beep.h"
int main(void)
{
//初始化
delay_init(168);
LED_Init();
BEEP_Init();
//蜂鸣器不叫
LED2 = 0;
BEEP = 0;
delay_ms(1000);
//蜂鸣器叫
LED2 = 1;
BEEP = 1;
delay_ms(1000);
}
学习心得:
不得不说STM32真的是一款非常复杂的单片机,一直以来接触的51单片机等等也只是用了一些常用基本的功能,今天在PWM上也花了不少时间,用库函数的话也是基本的函数调用初始化PWM。不过因为对定时器理解不是很深入,今天回过头去看定时器的内容,理解好定时器频率、重装值对溢出时间的影响是十分重要的。感觉学习还是手握一本相对详细的教材,单从视频例程和手册看来的知识比较片面。越是强大的功能就越是需要复杂的技术来配置它,刚解除stm32的时候我一直再抱怨连用个IO口都如此繁琐,其实我只是没有熟悉stm32的开发方式。不是每一行代码都得你自己去写,能复制粘贴实现功能也是自己的本事。
在学习stm32外设的时候应该注意一个很重要的事情,我们应该在用一个工程中通过添加.C和.h文件的形式来学习外设的使用,不可像学51那样一个工程一个实验。因为stm32功能众多我们做实验可能需要多个外设协同工作,做LCD现实实验可能我们需要LED现实状态,需要SPI连接传感器,需要key来控制状态。我们把在学习的过程中就大胆地把各个外设封装成文件,当我们完成所有外设学习的时候,这个工程就是我们的一个模板工程。需要做项目的时候直接COPY出来,去粗取精,稍作修改就能直接使用。如此看来stm32的发开也会变得十分方便快捷,估计以后接触更先进的芯片也应该采用这样的学习开发模式。毕竟芯片是越来越先进的,规模也是越来越复杂,只有在学习的时候就写好一个属于你自己的工程,日后做项目开发才能游刃有余。
对于学习stm32采用寄存器还是库函数,这个争议很多。个人认为两者并不冲突。首先库函数是st官方提供,整体来说它是一份优秀的代码。绝大部分情况下全部使用库函数来发开也能达到我们的目的。很多人说寄存器开发,代码效率很高,其实并不见得,我们打开官方库函数查看,会发现许多寄存器的配置都是写的十分棒的,初学者自己用寄存器写程序不见得会比库函数有力。那我们是不是就可以直接从库函数傻瓜式复杂粘贴代码来学习stm32呢?显然不是,寄存器可以帮助我们理解stm的硬件结构和工作方式,当库函数在某些情况不能实现我们想要的功能的时候我们可以通过查阅手册,用寄存器方式实现甚至改写官方库函数组成自己的库。要知道官方的东西不是绝对正确,也不是绝对适合自己的实际使用。在这情况下寄存器就有优势了。
作为初学者和日常开发来说,库函数的优势很明显,不仅代码可读性高,便于日后开发项目的再修改。试想我配置好的外设我在用的时候还需要查看手册,算一下寄存器的多少位要置1所以根据目前的学习进度和经验,我认为,在学习最基本的GPIO的时候我们可以先从操作寄存器入手,了解好stm32寄存器如何操作,学习如何使用,等操作符来修改寄存器。当可以用寄存器使用GPIO的所有功能的时候我们就可以开始愉快的库函数之旅了。日后我们想修改其他外设库函数或者实现某些功能,查询手册里相关寄存器配置就好。每次学习外设可以先把该外设的相关寄存器浏览一下不用记住,可以往后学习库函数开发,日后需要用到寄存器的时候再看手册修改。
(20210320021-李照恩)