ESK32-21001扩展板上带有一个无源蜂鸣器,根据无源蜂鸣器的驱动原理我们需要使用MCU的PWM资源来控制,可以是通过GPTM定时器来实现硬件输出PWM,也可以通过GPTM定时器来控制GPIO的输出电平翻来实现软件输出PWM,从控制方式来说,硬件PWM更加节省软件资源,相比于软件PWM的实现方式,阻塞更少。
HT32F54253通用功能定时器GPTM
▆16-bit 向上 / 向下自动重载计数器▆ 定时器多达 4 个独立通道
▆ 16-bit 可编程预分频器,可以对其时钟源进行 1 ~ 65536 之间的任意数值的分频产生计数
器时钟频率
▆ 输入捕捉功能
▆ 比较匹配输出
▆ PWM 波形产生功能,具有边沿对齐和中心对齐两种计数模式
▆ 单脉冲输出模式
▆ 内建可处理编码器接口信号的带两个输入口的正交解码器
通用定时器包括一个 16-bit 向上 / 向下计数器,四个 16-bit 捕捉 / 比较寄存器 (CCR),一个 16-bit计数器重载寄存器 (CRR) 和多个控制 / 状态寄存器。它们可用于多种用途,包括通用计时、输入信号脉冲宽度测量、输出波形产生,如单脉冲波形产生或 PWM 输出。 GPTM 还内建可处理编码器接口信号的带两个输入口的正交解码器。
原理图
引脚复用
实现功能
参考官方例程,通过GPTM定时器的PWM输出引脚,实现对BUZZER的控制,让其输出声响。
实现代码
/*******************************************************************************
* [url=home.php?mod=space&uid=288409]@file[/url] BUZZER.c
* [url=home.php?mod=space&uid=187600]@author[/url] King
* [url=home.php?mod=space&uid=895143]@version[/url] V1.00
* [url=home.php?mod=space&uid=212281]@date[/url] 07-Oct-2022
* [url=home.php?mod=space&uid=247401]@brief[/url] ......
*******************************************************************************/
/* Define to prevent recursive inclusion -------------------------------------*/
#define __BUZZER_C__
/* Includes ------------------------------------------------------------------*/
#include "BUZZER.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define BEE_TM_PRE (4)
#define BEE_SYS_CLK (LIBCFG_MAX_SPEED) // Calculate with fix value (#define)
#define BEE_DUTY (40) // 40%
/* Private macro -------------------------------------------------------------*/
#define BEE_TIME_MS(t, f) ((f) * (t) / 1000)
/* Private variables ---------------------------------------------------------*/
volatile uint16_t BUZZER_Times;
volatile uint16_t BUZZER_Active;
volatile uint16_t BUZZER_InActive;
volatile uint32_t BUZZER_Count;
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/* Exported variables --------------------------------------------------------*/
/* Exported function prototypes ----------------------------------------------*/
/*******************************************************************************
* @brief
* @param
* @retval
* [url=home.php?mod=space&uid=93590]@Attention[/url]
*******************************************************************************/
void BUZZER_Init(uint32_t uFrequency)
{
/* Enable peripheral clock */
CKCU_PeripClockConfig_TypeDef CKCUClock = {{ 0 }};
CKCUClock.Bit.AFIO = 1;
CKCUClock.Bit.GPTM0 = 1;
CKCU_PeripClockConfig(CKCUClock, ENABLE);
/* Configure AFIO mode as TM function */
AFIO_GPxConfig(GPIO_PC, AFIO_PIN_12, AFIO_FUN_GPTM0);
uint32_t Reload = (BEE_SYS_CLK / BEE_TM_PRE / uFrequency) - 1;
/* Time base configuration */
TM_TimeBaseInitTypeDef TimeBaseInit;
TimeBaseInit.Prescaler = BEE_TM_PRE - 1;
TimeBaseInit.CounterReload = Reload;
TimeBaseInit.RepetitionCounter = 0;
TimeBaseInit.CounterMode = TM_CNT_MODE_UP;
TimeBaseInit.PSCReloadTime = TM_PSC_RLD_IMMEDIATE;
TM_TimeBaseInit(HT_GPTM0, &TimeBaseInit);
TM_ClearFlag(HT_GPTM0, TM_FLAG_UEV);
/* Channel n output configuration */
TM_OutputInitTypeDef OutputInit;
OutputInit.Channel = TM_CH_2;
OutputInit.OutputMode = TM_OM_PWM2;
OutputInit.Control = TM_CHCTL_DISABLE;
OutputInit.ControlN = TM_CHCTL_DISABLE;
OutputInit.Polarity = TM_CHP_NONINVERTED;
OutputInit.PolarityN = TM_CHP_NONINVERTED;
OutputInit.IdleState = MCTM_OIS_LOW;
OutputInit.IdleStateN = MCTM_OIS_HIGH;
OutputInit.Compare = ((Reload + 1) * (100 - BEE_DUTY)) / 100;
OutputInit.AsymmetricCompare = 0;
TM_OutputInit(HT_GPTM0, &OutputInit);
/* Enable TM interrupt */
NVIC_EnableIRQ(GPTM0_IRQn);
}
/*******************************************************************************
* @brief
* @param
* @retval
* @attention
*******************************************************************************/
void BUZZER_Start(uint16_t Times, uint16_t Frequency, uint16_t Active_ms, uint16_t InActive_ms)
{
uint32_t Reload = (BEE_SYS_CLK / BEE_TM_PRE / Frequency) - 1;
uint32_t Compare = ((Reload + 1) * (100 - BEE_DUTY)) / 100;
BUZZER_Times = Times;
BUZZER_Active = BEE_TIME_MS(Active_ms, Frequency);
BUZZER_InActive = BEE_TIME_MS(InActive_ms, Frequency);
BUZZER_Count = BUZZER_Active + BUZZER_InActive;
TM_SetCounterReload(HT_GPTM0, Reload);
TM_SetCaptureCompare(HT_GPTM0, TM_CH_2, Compare);
TM_IntConfig(HT_GPTM0, TM_INT_UEV, ENABLE);
TM_ChannelConfig(HT_GPTM0, TM_CH_2, TM_CHCTL_ENABLE);
TM_Cmd(HT_GPTM0, ENABLE);
}
/*******************************************************************************
* @brief
* @param
* @retval
* @attention
*******************************************************************************/
uint32_t BUZZER_IsFinish(void)
{
return (BUZZER_Times ? FALSE : TRUE);
}
/*******************************************************************************
* @brief
* @param
* @retval
* @attention
*******************************************************************************/
void GPTM0_IRQHandler(void)
{
TM_ClearFlag(HT_GPTM0, TM_INT_UEV);
if(BUZZER_Count)
{
BUZZER_Count--;
if(BUZZER_Count == BUZZER_InActive)
{
TM_ChannelConfig(HT_GPTM0, TM_CH_2, TM_CHCTL_DISABLE);
}
if(BUZZER_Count == 0)
{
BUZZER_Count = BUZZER_Active + BUZZER_InActive;
TM_ChannelConfig(HT_GPTM0, TM_CH_2, TM_CHCTL_ENABLE);
if(BUZZER_Times)
{
BUZZER_Times--;
}
if(BUZZER_Times == 0)
{
TM_Cmd(HT_GPTM0, DISABLE);
}
}
}
}
/*******************************************************************************
* @brief
* @param
* @retval
* @attention
*******************************************************************************/
void BUZZER_Demo(void)
{
/* BUZZER 4 times, 3 kHz, active 50 ms, inactive 50 ms */
BUZZER_Init(0);
BUZZER_Start(4, 3000, 50, 50);
while(BUZZER_IsFinish() == FALSE);
/* BUZZER 2 times, 800 Hz, active 1000 ms, inactive 500 ms */
BUZZER_Init(0);
BUZZER_Start(2, 800, 1000, 500);
while(BUZZER_IsFinish() == FALSE);
}
运行结果
上电后,蜂鸣器先是以3kHz的频率间隔50ms快速响4声音,然后再以800Hz的频率响1秒停顿0.5秒的节奏循环响2个周期。
软件工程源代码
Project.zip
(845.42 KB)
|