1 硬件原理
下图为蜂鸣器的电路图,分析这个电路,想让蜂鸣器发声,则需要有电流流过蜂鸣器。当BEEP(即PB8)为高电平时,三极管导通,电流流过蜂鸣器,蜂鸣器发声;反之,当BEEP(即PB8)为低电平时,三极管截止,蜂鸣器不发声。所以控制蜂鸣器的发声,只需要控制PB8管脚的输出电平即可。
![](https://img-blog.csdnimg.cn/img_convert/63dd6b71de303aa0eb640a82db39f3da.png)
![4630e61281d919e794111fe6c8298df4.png](https://img-blog.csdnimg.cn/img_convert/4630e61281d919e794111fe6c8298df4.png)
2 IO输出配置
STM32F10系列的IO口结构以及输出模式可参考这篇博客STM32 I/O端口基本结构理解_弦续北上i的博客-CSDN博客_stm32io口结构,本文不再赘述,本文主要介绍具体的实现。
配置IO口的输出,需要三个步骤:
(1) 使能PB时钟;
(2) 设置引脚为输出模式;
(3) 设置电平高低。
2.1 使能PB时钟
如下图所示:PB端口使能寄存器为RCC_APB2ENR,对应bit3,所以,代码为:
//使能GPIOB时钟
RCC_APB2ENR |= (1<<3);
![](https://img-blog.csdnimg.cn/img_convert/fb7acb95530765c2770eb24a475a5142.png)
![](https://img-blog.csdnimg.cn/img_convert/2ed35cc3bf0e7fc886981b9eb3a59aa0.png)
2.2 设置引脚为输出模式
配置引脚输出模式使用的寄存器为 GPIOB_CRH,这里将配置为:通用推挽输出模式、最大速度10MHz,即:
GPIOB_CRH&= ~(15<<0);//清零寄存器相关位
GPIOB_CRH|=1<<0;//设置输出模式为通用推挽输出,频率为10MHz
![](https://img-blog.csdnimg.cn/img_convert/700c4634b1fbbb020286ea096f58bc11.png)
2.3 设置电平高低
设置GPIOB端口输出电平高低的寄存器为GPIOB_ODR,PB8输出电平高低的设置方法为:
//设置PB8输出高电平
GPIOB_ODR |= (1<<8);
//设置PB8输出低电平
GPIOB_ODR &= ~(1<<8);
![](https://img-blog.csdnimg.cn/img_convert/8472229832eb45495996c36984e78303.png)
3 完整代码
结合上一节所说的定义寄存器的方法,可以得到STM32F1上的完整代码如下:
//寄存器定义
#define RCC_APB2ENR (*(volatile unsigned int*)(0x40021018))
#define GPIOB_CRL (*(volatile unsigned int*)(0x40010c00))
#define GPIOB_CRH (*(volatile unsigned int*)(0x40010c04))
#define GPIOB_ODR (*(volatile unsigned int*)(0x40010c0c))
//类型定义
#define uint16_t unsigned short
//函数声明
void BEEP_Init(void);
void Delay(void);
int main()
{
//系统初始化
BEEP_Init();
//间隔发声
while(1)
{
//设置PB8输出高电平,蜂鸣器发声
GPIOB_ODR |= (1<<8);
//延时
Delay();
//设置PB8输出低电平,蜂鸣器不发声
GPIOB_ODR &= ~(1<<8);
//延时
Delay();
}
}
void BEEP_Init()
{
//使能GPIOB时钟
RCC_APB2ENR |= (1<<3);
//设置PB8的工作模式为输出
GPIOB_CRH&= ~(15<<0);//清零寄存器相关位
GPIOB_CRH|=1<<0;//设置输出模式为通用推挽输出,频率为10MHz
//设置PB8输出低电平,初始状态为不发声
GPIOB_ODR &= ~(1<<8);
return;
}
void Delay()
{
uint16_t i,j;
for(i=0;i<1000;i++)
for(j=0;j<3000;j++);
return;
}
欧启标老师课上STM32F4上的完整代码如下:
/*定义寄存器*/
#define GPIOF_MODER (*(volatile unsigned *)0x40021400) //模式配置,=00 输入,=01 输出
#define GPIOF_OTYPER (*(volatile unsigned *)0x40021404) //输出电路类型配置寄存器。=0 推挽输出
#define GPIOF_OSPEEDR (*(volatile unsigned *)0x40021408) //x 输出速度配置寄存器。=00,2MHz.
#define GPIOF_PUPDR (*(volatile unsigned *)0x4002140C) //上下拉配置寄存器。=00 无上下拉,=01 上拉
#define GPIOF_ODR (*(volatile unsigned *)0x40021414) //输出数据寄存器,=0 低电平,=1 输出高电平
//时钟系统相关寄存器的定义
#define RCC_AHB1ENR (*(volatile unsigned *)0x40023830) //外设时钟使能寄存器。=1 对应外设时钟使能
/*函数声明*/
void Delay(void);
void Beep_Init(void);
/*主函数*/
int main(void)
{
Beep_Init(); //初始化蜂鸣器接口
while(1)
{
GPIOF_ODR &= ~(1<<8); //关闭蜂鸣器
Delay(); //延时
GPIOF_ODR |= (1<<8); //打开蜂鸣器
Delay(); //延时
}
}
/*蜂鸣器*/
void Beep_Init(void)
{
RCC_AHB1ENR |= 1<<5; //使能 PORTF 时钟
GPIOF_MODER &= ~(3<<(8*2)); //配置 PF8 引脚相关位 bit16,bit17 为 0 –--清 0
GPIOF_MODER |= (1<<(8*2)); //配置 PF8 为输出----设置值
GPIOF_OTYPER &= ~(1<<8); //电路工作方式为推挽
GPIOF_OSPEEDR &= ~(3<<(8*2));//对应位清 0
GPIOF_OSPEEDR |= (2<<(8*2)); //响应速度 50M,其他值亦可
}
/*延时函数定义*/ void Delay(void)
{
int i, j;
for(i = 0; i < 200; i ++)
for(j = 0; j < 300; j ++);
}