HAL库教程10:定时器的PWM模式应用

发布者:SereneHarmony最新更新时间:2019-05-30 来源: eefocus关键字:HAL库  定时器  PWM模式 手机看文章 扫描二维码
随时随地手机看文章

  本节通过定时器的PWM模式驱动无源蜂鸣器,来演奏一段音乐。本博客在掌机的系列教程中介绍过蜂鸣器的驱动原理,感兴趣的可以参考电子琴


无源蜂鸣器驱动电路

  蜂鸣器按照有无震荡源(不是电源),可以分为有源蜂鸣器和无源蜂鸣器。有源蜂鸣器上电就能工作,控制简单,但是只有一个音调。无源蜂鸣器需要单片机提供震荡源,虽然控制稍微复杂一点,但是可以发出不同频率的声音。


在这里插入图片描述

PWM原理

  根据我们的电路,引脚输出高电平时,驱动电路为蜂鸣器提供了闭合回路,则引脚给高电平,蜂鸣器就能响。然而,只给高电平,无源蜂鸣器不能持续发出声音,只有一瞬间有声音;需要马上给低电平,然后再给一个高电平。即在一个很短的周期内,无源蜂鸣器在高电平持续期间工作,在低电平持续期间休息。周期的倒数就是频率。

  无源蜂鸣器可以用高电平持续的时间调整音量,在一个周期中,高电平持续的时间越长,蜂鸣器声音越大;高电平持续的时间越短,蜂鸣器的声音越小。


  STM32的定时器自带PWM输出模式。为了方便理解PWM,我们想象一个场景:语文老师、数学老师和体育老师带着小白和小黑两个小朋友在玩游戏。语文老师说一个数字x;数学老师负责从0数到x,数到x以后再从0开始,周而复始;体育老师负责说出一个数字y,如果数学老师报的数字比y小,则小白要举手,否则小白把手放下;直到数学老师报数跟y一样大,小白才把手放下,同时小黑举起手来。但是小黑要时刻注意,如果数到最大的数字时,就要做好准备放下手,因为接下来的数字是0。

  例如语文老师说的数字是9,数学老师说的数字是6,即x=9,y=6,那么在一个游戏周期内,小白和小黑举手的情况如下:


数学老师 0 1 2 3 4 5 6 7 8 9

小白 举 举 举 举 举 举

小黑 举 举 举 举

  通过这个例子,我们来重新理解定时器输出PWM的一些概念:

  语文老师报的数字是9,9就是自动重装值(AutoReload),代表计数周期(Counter Period)。

  数学老师从0数到9,所以称数学老师报的数字是计数值(counter)。9就是最大周期,由于从0开始计数,故一共数了10个数字。数学老师数数的速度,由时钟(84Mhz)和分频(Prescaler)决定。

  体育老师说的数字是6,6就叫做比较值(compare),比较值除以自动重装值得到占空比,6÷10=60%就是占空比。

  在PWM模式1下,小白举手代表引脚输出高电平,小白举手时间占总时间的比例,就是占空比。小黑举手就是引脚输出低电平。PWM模式2与1逻辑相反。

在PWM驱动蜂鸣器的案例中,语文老师报的数字,由音调的频率决定;体育老师报的数字,可以控制音量。小白与小黑是不是需要举手,无需写判断语句,

STM32定时器PWM模式可以自动判断计数值与比较值什么时候相等。


使用CubeMX配置定时器为PWM模式

在这里插入图片描述
在这里插入图片描述


在定时器2的初始化代码中,增加开启定时器PWM模式的代码


static void MX_TIM2_Init(void)

{

  /* USER CODE BEGIN TIM2_Init 2 */

    HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);

  /* USER CODE END TIM2_Init 2 */

}


从音调与音量到定时器的设置

  音调与频率是对应的。

在这里插入图片描述

我们先写一个函数,用于根据音调与音量,设置定时器。思路如下:

在这里插入图片描述

  溢出时间 = (自动重装值+1)/12000000,频率是时间的倒数,音调与频率有关,所以知道音调(频率)以后,可用以下方法计算自动重装值:

  Autoreload=(12000000/usFraq)-1; //频率变为自动重装值

  在无声时,让counter与0比较,counter始终大于0,则引脚电平始终为低,蜂鸣器不会响,即可以达到静音的目的。

  比较值决定音量,比较值要比自动重装值小,可以用后者乘以小于1的系数得到。实际上把自动重装值右移也是让比较值小于自动重装值的一个方法,效果更好一点。因为即便只有10%的占空比,蜂鸣器还是很响。

  新建Beep.h用于存放宏定义,新建Beep.c编写演奏函数。


//Beep.c

/**

  * @brief 根据频率让蜂鸣器发出声音

  * @param 频率,音量

  * @note  音量建议范围2~10,2是最大,10几乎听不清了

  * @retval None

  */    

void Beep_Sound(unsigned short usFraq,unsigned char volume_level)   //usFraq是发声频率,即真实世界一个音调的频率。

{

    u16 Autoreload;

    if((usFraq20000))//太低与太高的频率都当做无声

    {

        __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,0);//音量

        __HAL_TIM_SET_COUNTER(&htim2,0);

    }

    else

    {

        Autoreload=(12000000/usFraq)-1;  //频率变为自动重装值,设置的定时器时钟源为12Mhz

        __HAL_TIM_SET_AUTORELOAD(&htim2,Autoreload);

        __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,Autoreload>>volume_level);//音量

        __HAL_TIM_SET_COUNTER(&htim2,0);//在不使用缓冲的情况下,必须把计数值清零,否则可能出现计数值大于自动重装值以后,必须数到最大值的情况

    }

}

注意,修改完ARR以后,必须手动清零计数器!

  然后主函数响几个音符:


//main()  

  while (1)

  {

    Beep_Sound(CM1,6);

    HAL_Delay(200);

    Beep_Sound(CM2,6);

    HAL_Delay(200);

    Beep_Sound(CM3,6);

    HAL_Delay(200);

    Beep_Sound(CM1,6);

    HAL_Delay(200);

    Beep_Sound(0,6);

    HAL_Delay(200);

  }


  下载程序,应当可以听到“两只老虎,两只老虎”循环播放。

  程序只要稍加修改,就能演奏音乐了。


关键字:HAL库  定时器  PWM模式 引用地址:HAL库教程10:定时器的PWM模式应用

上一篇:HAL库教程11:定时器的缓冲功能与影子寄存器
下一篇:HAL库教程9:串口接收不定长数据

推荐阅读最新更新时间:2024-11-06 16:09

定时器T1中断实验
定时器T1中断实验。 1、定时器中断实验。定时器产生10mS周期中断,通过计数让PB1电平产生周期变化。 2、内部1 M晶振。 3、进行此实验请插上JP1的所有8个短路块,JP7(LED_EN)短路块。 */ #include "iom16v.h" #include macros.h /*初始化定时器,产生10mS周期中断*/ void T1_Init(void) { OCR1A = 1250; /*计数周期为10mS,F=1M*/ TIMSK |= (1 OCIE1A); /*比较中断A允许*/ SREG = 0x80; TCCR1A = 0x00; TCCR1B = 0x08; /*定时器工作在CTC计数器模式*/ TC
[单片机]
STM32F407入门开发: 配置定时器输出PWM方波
第一章 定时器PWM功能介绍 STM32F407的定时器的 TIM6 和 TIM7 是普通定时器,除此之外,其他的定时器都可以用来产生 PWM 输出。其中高级定时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出。而通用定时器也能同时产生多达4路的PWM输出;在开发四轴无人机、机器人等需要控制大量电机的产品里运用起来非常方便。 第二章 PWM波形输出通道介绍 定时器3的硬件PWM通道:PA6 PA7 PB0 PB1 下面截图是介绍定时器3通道的复用IO口模式配置方式 第三章 配置PWM波形输出代码示例 3.1 在工程中增加pwm.c文件,写入以下代码 #include pwm.h
[单片机]
STM32F407入门开发: 配置<font color='red'>定时器</font>输出<font color='red'>PWM</font>方波
51单片机串口、定时器、中断
1、串口编程思路: 2、中断
[单片机]
51单片机串口、<font color='red'>定时器</font>、中断
STM8 定时器中断程序
系统功能 使用STM8定时器做1S定时,并使用LED作出简单指示! 硬件设计 本设计基于内部RC振荡器2M时钟作STM8定时器TIM4的时钟源进行1S定时! LED控制电路原理图 软件设计 /********************************************************************* 目标系统: 基于STM8单片机 应用软件: Cosmic CxSTM8 *********************************************************************/ /* ----------------------------
[单片机]
STM8 <font color='red'>定时器</font>中断程序
MSP430f2619学习—Timer_A定时器
1、定时器时钟图 2、Timer_A寄存器配置 (1)时钟源设置 TACTL |= TASSEL_2 + ID_3 + MC_1 + TACLR; 此处选择SMCLK,8分频,向上计数模式,TACLR位可清TAR计数值; (2)中断配置 MSP430f2619定时器A共有3个捕获/比较寄存器,中断配置涉及到的寄存器:TACTL/TACCTL0/TACCTL1/TACCTL2; 设置方法: TACTL |= TAIE;//溢出中断允许 TACCTL0 |= CCIE;//捕获/比较通道0中断允许 TACCTL1 |= CCIE;//捕获/比较通道1中断允许 TACCTL2 |= CCIE;//捕获/比较通道2中断允许 ,定时
[单片机]
MSP430f2619学习—Timer_A<font color='red'>定时器</font>
STM32应用简章之通用定时器
① 能定时器时钟。 RCC_APB1PeriphClockCmd(); ② 初始化定时器,配置ARR,PSC。 TIM_TimeBaseInit(); ③开启定时器中断,配置NVIC。 void TIM_ITConfig(); NVIC_Init(); ④ 使能定时器。 TIM_Cmd(); ⑥ 编写中断服务函数。 TIMx_IRQHandler(); void TIM3_Int_Init(u16 arr,u16 psc) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; NVIC_InitType
[单片机]
STM32之通用定时器
STM32中的定时器有多种,按功能分成2个高级控制器定时器,4个普通定时器,2个基本定时器,2个看门狗定时器,1个系统滴答定时器SysTick。 定时器的关键是定时时间的计算。比如用定时器控制继电器的开关的时候,需要延时一段时间才关闭或者开启,这时候离不开定时器定时。 通用定时器定时时间计算。1秒中断的基本实现: 通用定时器模块的入口时钟经过分频得到计数器的时钟,用CK_CNT表示,预分频器的系数为:TIMx_PSC,当TIMx_PSC=0时,表示不分频,=1时,2分频。以此类推。 公式为:CK_CNT=fclk_PSC/(PSC +1),其中PSC最大为65535. 其次是TIM5计数器的计数值的设置,TIM5计数器以
[单片机]
STM32之通用<font color='red'>定时器</font>
MSP430F249_TimerA定时器
/****************************************************************** ** ** File : TimerA.c | Timer Interrupt | ** Version : 1.0 ** Description: TimerA Interrupt ** Author : LightWu ** Date : 2013-4-16
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved