历史上的今天
返回首页

历史上的今天

今天是:2025年06月24日(星期二)

正在发生

2019年06月24日 | STM32CubeMX下按键模块控制PWM蜂鸣器模块

2019-06-24 来源:eefocus

前言:之前的STM32L433CB单片机还有几个模块没有解决,最佳抽空把按键模块和PWM蜂鸣器模块调通了。


1.按键模块

按键模块重点是需要了解中断模式:

(1)中断简而言之是暂时中止当前的工作,而去处理更为急需处理的事情,把急需处理的事情处理完毕之后,再回头来继续原来的事情。

(2)stm32的中断分为抢占优先级和响应优先级。抢占优先级高的中断,可以打断抢占优先级低的中断。抢占优先级相同的中断,响应优先级高的可以优先执行。

(3)中断向量表:中断向量是中断服务程序的入口地址,在计算机中中断向量的地址存放一条跳转到中断服务程序的跳转指令。中断地址是存储中断向量的内存单元。中断向量表是用来存放中断向量

(4)嵌套中断:中断系统正在执行一个中断服务时,有另一个优先级更高的中断提出中断请求,这时会暂时终止当前正在执行的级别较低的中断源的服务程序,去处理级别更高的中断源,待处理完毕,再返回到被中断了的中断服务程序继续执行,这个过程就是中断嵌套。如果中断里调用HAL_Delay就会停在那里,因为根本不会进入那个级别更低的中断。CUBE生成的程序中, SysTick是中断型延时,SysTick是内核中断,优先级别默认最低。所以我后面的延时函数使用了SysTick。

了解中断之后就是STM32中的按键:

按键需要上拉电阻,当按键按下接地,低电平导通,CPU读取低电平

在这里插入图片描述

配置方法

使按键对应的PC13和PA15为GPIO模式,勾上修改,将GPIO mode 设置为下降沿触发中断,设置电阻为上拉电阻。

在这里插入图片描述

使能按键中断,两个按键中断优先级是一样的

在这里插入图片描述


2.PWM蜂鸣器模块

pwm波形产生的原理:

在这里插入图片描述

通用定时器可以利用GPIO引脚进行脉冲输出,在配置为比较输出、PWM输出功能时,捕获/比较寄存器TIMx_CCR被用作比较功能,下面把它简称为比较寄存器。

这里直接举例说明定时器的PWM输出工作过程:若配置脉冲计数器TIMx_CNT为向上计数,而重载寄存器TIMx_ARR被配置为N,即TIMx_CNT的当前计数值数值X在TIMxCLK时钟源的驱动下不断累加,当TIMx_CNT的数值X大于N时,会重置TIMx_CNT数值为0重新计数。

而在TIMxCNT计数的同时,TIMxCNT的计数值X会与比较寄存器TIMx_CCR预先存储了的数值A进行比较,当脉冲计数器TIMx_CNT的数值X小于比较寄存器TIMx_CCR的值A时,输出高电平(或低电平),相反地,当脉冲计数器的数值X大于或等于比较寄存器的值A时,输出低电平(或高电平)。

如此循环,得到的输出脉冲周期就为重载寄存器TIMx_ARR存储的数值(N+1)乘以触发脉冲的时钟周期,其脉冲宽度则为比较寄存器TIMx_CCR的值A乘以触发脉冲的时钟周期,即输出PWM的占空比为 A/(N+1) 。

在这里插入图片描述

(1)当 PA1 输出高电平的时候,蜂鸣器将发声, 当 PA1 输出低电平的时候,蜂鸣器停止发声。R10U为了防止蜂鸣器误发声,下拉输出,推挽输出

(2)有源蜂鸣器内含振荡源,只要一通电就发声,但发生频率固定,音色单一;无源蜂鸣器内部不含振荡源,内部结构相当于电磁场扬声器,可以通过给他输出一定频率的信号才能发声。

(3)人耳能听到的频率范围在20Hz–20kHz之间,通过STM32的GPIO引脚快速切换高低电平输出就能实现无源蜂鸣器的发声,切换的频率不同,发出的音调就不一样。当CNT达到ARR值的时候,重新归零,然后重新向上计数,依次循环。改变CCRx的值,就可以改变PWM输出的占空比;改变ARR的值,就可以改变PWM输出的频率。

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

时钟树配置为80MHz,可知PWM的时钟为80MHz

PWM频率为80MHz/ARR,周期为1*ARR/80MHz,占空比为CRRx/ARR


修改工程名,路径和编译工具


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

生成代码:

stm32l4_it.c文件:


void EXTI15_10_IRQHandler(void)

{

  /* USER CODE BEGIN EXTI15_10_IRQn 0 */

delay_ms(10);        //延时消抖

  /* USER CODE END EXTI15_10_IRQn 0 */

  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13);

  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_15);

  /* USER CODE BEGIN EXTI15_10_IRQn 1 */


  /* USER CODE END EXTI15_10_IRQn 1 */

}


/* USER CODE BEGIN 1 */

void delay_ms(uint32_t nms)   //利用SysTick写一个延时函数

 {

  uint32_t temp;

  SysTick->LOAD = 8000*nms;

  SysTick->VAL=0X00;

  SysTick->CTRL=0X01;

  do

  {

      temp=SysTick->CTRL;

  }

    while((temp&0x01)&&(!(temp&(1<<16))));

     SysTick->CTRL=0x00; 

     SysTick->VAL =0X00; 

 }

/* USER CODE END 1 */


stm32l4_it.h文件:


/* Private includes ----------------------------------------------------------*/

/* USER CODE BEGIN Includes */

#include "stdint.h"

/* USER CODE END Includes */


/* USER CODE BEGIN EFP */

void delay_ms(uint32_t nms);

/* USER CODE END EFP */


tim.c文件:


/* USER CODE BEGIN 1 */

int tone[]={247,262,294,330,349,392,440,294,523,587,659,698,784,1000};//音调对应的频率


int yindiao[]=             //音调

5,5,6,8,7,6,5,6,13,13,

5,5,6,8,7,6,5,3,13,13,

2,2,3,5,3,5,6,3,2,1,

6,6,5,6,5,3,6,5,13,13,

5,5,6,8,7,6,5,6,13,13,

5,5,6,8,7,6,5,3,13,13,

2,2,3,5,3,5,6,3,2,1,

6,6,5,6,5,3,6,1,

13,8,9,10,10,9,8,10,9,8,6,

13,6,8,9,9,8,6,9,8,6,5,

13,2,3,5,5,3,5,5,6,8,7,6,

6,10,9,9,8,6,5,6,8

};


int dtime[]=               //节拍

{

2,4,2,2,2,2,2,8,4, 4,

2,4,2,2,2,2,2,8,4, 4,

2,4,2,4,2,2,4,2,2,8,

2,4,2,2,2,2,2,8,4 ,4, 

2,4,2,2,2,2,2,8,4, 4,

2,4,2,2,2,2,2,8,4, 4, 

2,4,2,4,2,2,4,2,2,8,

2,4,2,2,2,2,2,8,

4, 2,2,2, 4, 2,2,2, 2,2,8,

4, 2,2,2, 4, 2,2,2, 2,2,8,

4, 2,2,2,4,2,2,5,2,6,2,4,

2,2 ,2,4,2,4,2,2,12

};


void sound(int freq)

{

if(freq!=1000)

{

int Arr;

TIM_OC_InitTypeDef sConfigOC = {0};

Arr = 500000/freq;

htim2.Init.Period = Arr;//改变频率来改变计数器周期

HAL_TIM_PWM_Init(&htim2);

sConfigOC.Pulse = Arr/4;

sConfigOC.OCMode = TIM_OCMODE_PWM1;

sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;

sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;

if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)

{

Error_Handler();

}

HAL_TIM_MspPostInit(&htim2);

    

}

HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);  //使能PWM定时器

}



void buzzer_quit()

{

HAL_TIM_PWM_Stop(&htim2,TIM_CHANNEL_2);//停止PWM定时器

}


void play_mus()//播放音乐

{

int i;

for(i=0;i {

sound(tone[yindiao[i]]);

delay_ms(150*dtime[i]);

buzzer_quit();

delay_ms(20);

}

}

/* USER CODE END 1 */


tim.h文件:


/* USER CODE BEGIN Prototypes */

void sound(int freq);

void start_pwm();

void buzzer_quit();

void play_mus();

/* USER CODE END Prototypes */


gpio.c文件:


/* USER CODE BEGIN 2 */

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)//中断回调函数,当按键按下跳入

{

switch(GPIO_Pin)

{

case GPIO_PIN_13:          //按下PC13对应按键播放音乐            

   play_mus();

       

break; 

case GPIO_PIN_15:              //按下PA15按键停止播放

   buzzer_quit(); 

      

    break;

}

}

/* USER CODE END 2 */


由于两个按键优先级一样,中断不能被另一个打断。


gpio.h文件:


/* USER CODE BEGIN Includes */

#include "tim.h"         //包含tim.h头文件

/* USER CODE END Includes */



推荐阅读

史海拾趣

C-MAX Time Solutions公司的发展小趣事

C-MAX Time Solutions公司在发展过程中,逐渐认识到深耕细分市场的重要性。公司针对工业控制、安防监控等特定领域,推出了定制化的时间同步解决方案。这些方案不仅满足了客户的特殊需求,也提高了C-MAX在这些细分市场的占有率。通过不断积累口碑和经验,C-MAX逐渐在电子行业中树立起了专业、可靠的形象。

Excelitas公司的发展小趣事

Excelitas公司自成立以来,一直致力于光电技术的研发与创新。在某次关键的技术突破中,公司成功研发出一种新型高效能LED灯,这种灯在紫外光固化领域具有显著优势。这一技术突破不仅为公司赢得了市场份额,还确立了Excelitas在光电领域的领先地位。公司随后围绕这一技术,推出了一系列相关产品,进一步巩固了市场地位。

Fedco_Batteries公司的发展小趣事

面对日新月异的市场需求和技术变革,Fedco_Batteries始终保持创新的步伐。公司加大了研发投入,不断推出新型电池产品,满足客户的多样化需求。同时,公司还积极探索新的应用领域,将电池技术应用于更多领域,如新能源汽车、智能家居等。这种创新驱动的发展战略,让Fedco_Batteries在行业中始终保持领先地位。

American Power Devices Inc公司的发展小趣事

在激烈的市场竞争中,APD公司始终坚持品质至上的原则。公司建立了严格的质量管理体系,从原材料采购到产品生产、检测等各个环节都严格把关。凭借卓越的产品品质和良好的售后服务,APD赢得了众多客户的信赖和支持。

CMOS Sensor Inc公司的发展小趣事

CMOS Sensor Inc公司起源于硅谷,由一群热衷于光电图像采集技术的工程师创立。他们看到了光电图像采集技术在多个领域的巨大潜力,于是决定投身于这一行业。在创立初期,公司面临着资金短缺、市场竞争激烈等诸多挑战。然而,凭借着对技术的执着和不懈努力,CMOS Sensor Inc公司逐渐在市场中站稳了脚跟。

福声科技(FUET)公司的发展小趣事

在稳固国内市场的同时,福声科技积极寻求国际合作机会,努力拓展海外市场。公司凭借其优质的产品和服务,成功吸引了日本、韩国、加拿大、美国等多个国家和地区的客户。通过与国际知名企业的合作与交流,福声科技不仅提升了自身的技术水平和品牌影响力,还进一步拓宽了国际市场渠道,为公司的全球化战略奠定了坚实基础。

问答坊 | AI 解惑

LED问题

我想用移位的方法是3个LED 循环点亮 可是调试的时候不能进入if语句中 #include \"inc\\44b.h\" #include \"inc\\option.h\" /*************************************************************************** 【功能说明】通用延时函数,延时tim ...…

查看全部问答>

【藏书阁】晶体管电路设计

目录: 第一章 概述  学习晶体管电路或FET电路的必要性  晶体管和FET的工作原理  晶体管和FET的近况 第二章 放大电路的工作  观察放大电路的波形  放大电路的设计   放大电路的性能  共发射极应用电路  第三章 增强输出的 ...…

查看全部问答>

请大家帮忙看看我的usb设备流驱动有什么问题?

对应DeviceIOControl函数写了如下的流驱动代码: BOOL  TES_IOControl (DWORD dwCtx, DWORD dwCode,                PBYTE pInpBuf, DWORD dwInpLen,       & ...…

查看全部问答>

vs2005中在c#的智能设备上实现显示地图

  请问,在c#的智能设备的模拟器上显示一副地图,需要什么控件,怎么导入?…

查看全部问答>

在wince上实现画图板的功能实现

请教各位大侠: 想实现画线功能,捕获 WM_MOUSEMOVE ,WM_LBUTTONDOWN 就可以拉,还是应该去实现驱动里发送的消息。。 …

查看全部问答>

哪位大侠能提供用GNU工具链开发Cortex-m3的启动代码???

各位大侠好啊,我的环境如下: 开发环境:Sourcery g++ Lite Edition ( 不是Personal Edition和Professional Edition ) 硬件环境:STM3210E-EVAL评估板 我刚接触cortex-m3不久,手头现有的资料都是基于IAR 和 Keil的 ,没有基于GNU工具链的开发 ...…

查看全部问答>

求DSP与ARM9(WINCE)串口通信的源代码(C++)、、、急用..谢谢啊。。。。

最近加入一个项目,需要DSP与ARM9的串口通信,可是本人实在是刚接触这嵌入式这块,不懂得该怎么办,又因为急着用,所以向各位大大求救。。谢谢啊。。我的邮箱是812786455@qq.com。。。。万分感谢。。…

查看全部问答>

H.264官方中文版

没钱了,卖点东西…

查看全部问答>

求STM32的USB例程

大家好:      我想用stm32的USB口和电脑通讯。有电脑发送查询信息,板子接收到以后根据相应的信息进行查询,将查询的结果返回给电脑。请问有相似的接收和发送的历程吗?有的请给我一份谢谢…

查看全部问答>

求助 测量水滴下落速度和水滴大小

光信号转换成电信号后 输入到DSP的AD端口,然后通过计算电压的变化和持续时间来反算水滴的大小和下落时间 思路大概是这样 选用的是TI28335  不知道要怎么采样 没啥头绪想找人问问…

查看全部问答>