怎么更改单片机stm32f407的蜂鸣器鸣叫频率

通过系统时钟更改 一个循环鸣叫两次 且每次
鸣叫频率不相同 怎么用代码控制

你看看这个思路是否满足你的要求,可以使用一个循环来控制鸣叫的次数和频率。 参考下面代码:

#include <stdio.h>  
#include <stdlib.h>  
#include <time.h>  
  
int main() {  
    int i;  
    float freq1, freq2; // 定义两个不同的频率  
    srand(time(NULL)); // 以当前时间为随机数种子,确保每次运行时产生的随机数不同  
  
    freq1 = rand() / (float)RAND_MAX * 100.0; // 生成第一个频率,范围在0到100之间  
    freq2 = rand() / (float)RAND_MAX * 100.0; // 生成第二个频率,范围在0到100之间  
  
    for (i = 0; i < 2; i++) { // 循环两次  
        printf("Beep!\n"); // 输出鸣叫的声音  
        sleep(1); // 暂停一秒钟  
        printf("Next frequency: %.2f Hz\n", freq1); // 输出当前的频率  
        freq1 += rand() / (float)RAND_MAX * 10.0; // 生成下一个频率,范围在当前频率加减10之间  
    }  
  
    return 0;  
}

要更改STM32F407单片机的蜂鸣器鸣叫频率,可以通过改变定时器的定时周期和占空比来实现。具体步骤如下:

配置GPIO端口:将蜂鸣器连接的GPIO端口设置为输出模式,用于控制蜂鸣器的开和关。

配置定时器:选择一个合适的定时器,并将其设置为PWM模式。设置定时器的时钟源、预分频值、计数周期、PWM输出通道等参数。将PWM输出通道连接到蜂鸣器的GPIO端口。

控制蜂鸣器:通过改变定时器的定时周期和占空比,可以改变蜂鸣器的鸣叫频率和持续时间。

下面是示例代码,实现了一个循环鸣叫两次,每次鸣叫频率不相同的蜂鸣器控制程序。在这个程序中,使用了TIM2定时器和PA0引脚控制蜂鸣器```


#include "stm32f4xx.h"
#include "stm32f4xx_tim.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"

void Delay(__IO uint32_t nCount)
{
while(nCount--)
{
}
}

int main(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;

/* Enable GPIOA & TIM2 clock */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

/* Configure PA0 pin as output */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
GPIO_Init(GPIOA, &GPIO_InitStructure);

/* Connect TIM2 output to PA0 */
GPIO_PinAFConfig(GPIOA, GPIO_PinSource0, GPIO_AF_TIM2);

/* Compute the prescaler value */
uint16_t PrescalerValue = (uint16_t) ((SystemCoreClock /2) / 1000000) - 1;

/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = 1000 - 1; // 设置计数周期为1000,即定时周期为1ms
TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

/* PWM1 Mode configuration: Channel1 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 500; // 设置初始占空比为50%
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM2, &TIM_OCInitStructure);

/* TIM2 enable counter */
TIM_Cmd(TIM2, ENABLE);

/* Infinite loop */
while (1)
{
// 第一次鸣叫,频率为1kHz,持续时间500ms
TIM_SetAutoreload(TIM2, 1000 - 1); // 设置计数周期为1000,即定时周期为1ms
TIM_SetCompare1(TIM2, 500); // 设置占空比为50%
GPIO_SetBits(GPIOA, GPIO_Pin_0); // 开始蜂鸣器
Delay(500000); // 持续500ms
GPIO_ResetBits(GPIOA, GPIO_Pin_0); // 关闭蜂鸣器
Delay(500000); // 停顿500ms

stylus
Copy
// 第二次鸣叫,频率为2kHz,持续时间300ms
TIM_SetAutoreload(TIM2, 500 - 1);  // 设置计数周期为500,即定时周期为0.5ms
TIM_SetCompare1(TIM2, 250);  // 设置占空比为50%
GPIO_SetBits(GPIOA, GPIO_Pin_0);  // 开始蜂鸣器
Delay(300000);  // 持续300ms
GPIO_ResetBits(GPIOA, GPIO_Pin_0);  // 关闭蜂鸣器
Delay(500000);  // 停顿500ms
}
}


在这个示例程序中,使用了TIM2定时器和PA0引脚控制蜂鸣器,实现了一个循环鸣叫两次,每次鸣叫频率不相同的功能。其中,第一次鸣叫的频率为1kHz,持续时间为500ms;第二次鸣叫的频率为2kHz,持续时间为300ms。具体实现方法是通过改变定时器TIM2的计数周期和占空比来控制蜂鸣器的鸣叫频率和持续时间。

在程序中,首先配置了GPIOA引脚为复用输出模式,并将其连接到TIM2的输出通道1上。然后配置TIM2定时器为PWM模式,并设置了定时器的时钟源、预分频值、计数周期和PWM输出通道等参数。在循环中,通过改变计数周期和占空比来控制蜂鸣器的鸣叫频率和持续时间。

注意,在实际应用中,需要根据具体需求调整定时器的参数,以达到所需的鸣叫效果。

嗯,根据你的需求,给你写了一些底层驱动代码,
driver_Buzzer.h的内容

#ifndef __DRIVER_Buzzer_H
#define __DRIVER_Buzzer_H

#include "stm32f4xx_hal.h"

typedef struct Beep{

    int test;
    int (*GetBeepStatus)(struct Beep *beep);
    
    
}Beep,*PBeep;


/*********************
 * 引脚宏定义
**********************/
#define Buzzer_GPIO_PIN           GPIO_PIN_8
#define Buzzer_GPIO_PORT          GPIOA
#define Buzzer_GPIO_CLK_EN()      __HAL_RCC_GPIOA_CLK_ENABLE()

/*********************
 * 函数宏定义
**********************/
#define Buzzer(flag)              HAL_GPIO_WritePin(Buzzer_GPIO_PORT, Buzzer_GPIO_PIN, flag?GPIO_PIN_SET:GPIO_PIN_RESET)  

/*
 *  函数名:void BuzzerInit(void)
 *  输入参数:无
 *  输出参数:无
 *  返回值:无
 *  函数作用:初始化蜂鸣器的引脚
*/
extern void BuzzerInit(void);

/*
 *  函数名:void ControlBuzzerRang(uint16_t period)
 *  输入参数:period-蜂鸣器发出响声的周期,f=1/(2*period)
 *  输出参数:无
 *  返回值:无
 *  函数作用:初始化系统滴答时钟的频率和中断优先级
*/
extern void ControlBuzzerRang(uint16_t period);

void Buzzer_Solo(void);
//int TryGetBeepStatus(struct Beep *beep);
#endif

driver_Buzzer.c的内容

#include "driver_Buzzer.h"


typedef int (*TryyGetBeepStatus)(struct Beep *beep);
#define TIMES    20            // 单音的时长
#define HZ        500           // 单音的音调

Beep g_beep = {0};

int TryGetBeepStatus(struct Beep *beep)
{
    
    
    return 0;
}

int test(struct Beep *beep)
{
    return 0;
}


/*
 *  函数名:void BuzzerInit(void)
 *  输入参数:无
 *  输出参数:无
 *  返回值:无
 *  函数作用:初始化蜂鸣器的引脚
*/
void BuzzerInit(void)
{

    // 定义GPIO的结构体变量
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    // 使能蜂鸣器的GPIO对应的时钟
    Buzzer_GPIO_CLK_EN();
    
    GPIO_InitStruct.Pin = Buzzer_GPIO_PIN;         // 选择蜂鸣器的引脚
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;    // 设置为推挽输出模式
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;  // 引脚反转速度设置为快
    
    // 初始化引脚配置
    HAL_GPIO_Init(Buzzer_GPIO_PORT, &GPIO_InitStruct);
    
    // 关闭蜂鸣器
    Buzzer(0);
    
    
}

/*
 *  函数名:void ControlBuzzerRang(uint16_t period)
 *  输入参数:period-蜂鸣器发出响声的周期,f=1/(2*period)
 *  输出参数:无
 *  返回值:无
 *  函数作用:输出方波
*/


void ControlBuzzerRang(uint16_t period)
{
    
    Buzzer(1);
    HAL_Delay(period);
    Buzzer(0);
    HAL_Delay(period);
}


void Buzzer_Solo(void)
{
    uint8_t i = 0;
    for(i = 0; i < TIMES; i++)
    {
           ControlBuzzerRang(HZ);  // 蜂鸣器响i ms,然后不响i ms,构成一个1/(2*i)kHz频率的蜂鸣器响应
    }
}

main.c中调用

#include "main.h"
#include "driver_buzzer.h"
int main(void){
  SystemClock_Config();
  // ...省略其他初始化
  // 初始化蜂鸣器
    BuzzerInit();    
   ControlBuzzerRang(i);  // 蜂鸣器响i ms,然后不响i ms,构成一个1/(2*i)kHz频率的蜂鸣器响应
   while(1);
}

通过控制PWM的输出间隔和脉冲频率就可以了呀

可以借鉴下

 
#include "led.h"
#include "system.h"
#include "SysTick.h"
#include "beep.h"
int main()
{
SystemTick_Init(72);
    LED_Init();
    beep_Init();
    
while(1)
    {    
    BEEP!=BEEP;
        delay_ms(400);
        
        
  }
 
}
 

可以参考下面代码

#include "stm32f4xx.h"

#define SYS_CLOCK_FREQ 16000000 // 系统时钟频率
#define BEEP_GPIO_PORT GPIOA // 蜂鸣器GPIO口所在的端口
#define BEEP_GPIO_PIN GPIO_Pin_5 // 蜂鸣器GPIO口对应的引脚

void TIM2_Init(uint16_t prescaler, uint16_t period);
void GPIO_Init(void);
void Beep_On(void);
void Beep_Off(void);

int main(void)
{
    // 初始化GPIO口和定时器
    GPIO_Init();
    TIM2_Init((SYS_CLOCK_FREQ / 1000) - 1, 500 - 1);
    
    // 循环鸣叫两次
    for(int i = 0; i < 2; i++)
    {
        // 鸣叫频率不同
        TIM2_Init((SYS_CLOCK_FREQ / 1000) - 1, 500 - 1);
        for(int j = 0; j < 500000; j++); // 等待
        TIM2_Init((SYS_CLOCK_FREQ / 1000) - 1, 1000 - 1);
        for(int j = 0; j < 500000; j++); // 等待
    }

    // 停止鸣叫
    TIM_Cmd(TIM2, DISABLE);
    Beep_Off();

    while(1);

    return 0;
}

// 初始化定时器
void TIM2_Init(uint16_t prescaler, uint16_t period)
{
    TIM_TimeBaseInitTypeDef TIM_InitStruct;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

    TIM_InitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_InitStruct.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_InitStruct.TIM_Prescaler = prescaler;
    TIM_InitStruct.TIM_Period = period;
    TIM_TimeBaseInit(TIM2, &TIM_InitStruct);

    // 使能定时器
    TIM_Cmd(TIM2, ENABLE);
    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
}

// 初始化GPIO口
void GPIO_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

    GPIO_InitStruct.GPIO_Pin = BEEP_GPIO_PIN;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(BEEP_GPIO_PORT, &GPIO_InitStruct);
}

// 开启蜂鸣器
void Beep_On(void)
{
    GPIO_SetBits(BEEP_GPIO_PORT, BEEP_GPIO_PIN);
}

// 关闭蜂鸣器
void Beep_Off(void)
{
    GPIO_ResetBits(BEEP_GPIO_PORT, BEEP_GPIO_PIN);
}

// 定时器中断服务程序
void TIM2_IRQHandler(void)
{
    if(TIM_GetITStatus(TIM2,TIM_IT_Update) != RESET)
    {
        TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
        Beep_On();
        for(int i = 0; i < 10000; i++); // 延时
        Beep_Off();
    }
}

用定时器的输出控制输出的pwm的频率;
用gpio作为按键输入,接收按键指令;
系统函数检测按键指令,并控制pwm输出使能。

  • 这有个类似的问题, 你可以参考下: https://ask.csdn.net/questions/7769118
  • 这篇博客你也可以参考下:毕业设计| STM32F407智能汽车:功能全网最全,代码开源。看评论区领相关项目资料
  • 除此之外, 这篇博客: stm32f407与串口屏通信问题中的 新的甘特图功能,丰富你的文章 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • Mon 06Mon 13Mon 20已完成进行中计划一计划二现有任务Adding GANTT diagram functionality to mermaid
    • 关于 甘特图 语法,参考 这儿,
  • 以下回答由chatgpt基于相关博客总结生成:

    答案:

    使用代码控制单片机stm32f407的蜂鸣器鸣叫频率,可以通过改变定时器的频率来实现。

    1. 首先,需要配置定时器,并开启中断。代码示例如下(假设选择TIM2定时器,产生音调的引脚为PA1):
    TIM_HandleTypeDef htim2;
    TIM_OC_InitTypeDef sConfigOC;
    
    void MX_TIM2_Init(void)
    {
      TIM_ClockConfigTypeDef sClockSourceConfig = {0};
      TIM_MasterConfigTypeDef sMasterConfig = {0};
      htim2.Instance = TIM2;
      htim2.Init.Prescaler = 0;
      htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
      htim2.Init.Period = 65535; //定时器周期,可以根据需求调整
      htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
      if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
      {
        Error_Handler();
      }
      sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
      if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
      {
        Error_Handler();
      }
      if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
      {
        Error_Handler();
      }
      sConfigOC.OCMode = TIM_OCMODE_PWM1;
      sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
      sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
      sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
      sConfigOC.Pulse = 32768; //占空比,可以根据需求调整
      if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
      {
        Error_Handler();
      }
      sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
      sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
      if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
      {
        Error_Handler();
      }
    }
    
    void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *tim_pwmHandle)
    {
      GPIO_InitTypeDef GPIO_InitStruct = {0};
      if (tim_pwmHandle->Instance == TIM2)
      {
        __HAL_RCC_TIM2_CLK_ENABLE();
        __HAL_RCC_GPIOA_CLK_ENABLE();
        /**TIM2 GPIO Configuration
        PA1     ------> TIM2_CH2
        */
        GPIO_InitStruct.Pin = GPIO_PIN_1;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
        GPIO_InitStruct.Alternate = GPIO_AF1_TIM2;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
      }
    }
    
    void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
    {
      if(htim->Instance == TIM2)
      {
        HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_1);  //产生鸣叫
      }
    }
    
    1. 然后,在main函数中,启动定时器并开启中断:
    HAL_TIM_PWM_Start_IT(&htim2, TIM_CHANNEL_2); //启动定时器
    HAL_TIM_Base_Start_IT(&htim2); 
    
    1. 最后,可以在HAL_TIM_PeriodElapsedCallback回调函数中改变定时器周期和占空比的值,从而改变鸣叫频率。代码示例如下:
    void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
    {
      if(htim->Instance == TIM2)
      {
        HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_1);  //产生鸣叫
        if(count <= 1) {  //循环鸣叫两次
          if(htim2.Init.Period == 65535) {  //修改定时器周期从65535到32767
            htim2.Init.Period = 32767;
          } else {
            htim2.Init.Period = 65535;
          }
          HAL_TIM_Base_Init(&htim2);
          HAL_TIM_PWM_Init(&htim2);
          HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2);
          HAL_TIM_PWM_Start_IT(&htim2, TIM_CHANNEL_2);
          HAL_TIM_Base_Start_IT(&htim2);
          count++;  //计数器加1
        } else {
          HAL_TIM_Base_Stop_IT(&htim2);  //停止定时器
        }
      }
    }
    

    其中,count变量用于记录鸣叫次数,初值为0,每次鸣叫时加1,当count等于2时停止定时器。

    需要注意的是,修改定时器的周期和占空比时需要重新初始化和启动定时器,否则无法生效。

    综上,通过修改定时器的周期和占空比,可以实现通过代码控制单片机stm32f407的蜂鸣器鸣叫频率,循环鸣叫两次。

对时钟信号进行分频,输出分频后的信号

该回答引用GPT与博主@晓码自在合作编写:

可以用下面的代码实现:

c
#include <reg52.h>

#define HIGH 1
#define LOW 0

sbit Buzzer = P2^7;   //定义蜂鸣器接口

uint count1 = 0;      //计数变量1
uint count2 = 0;      //计数变量2
bit flag = 0;         //标志位

void timer0() interrupt 1  //定时器0中断服务程序
{
    TH0 = (65536 - 50000) / 256;   //设置重装值
    TL0 = (65536 - 50000) % 256;
    
    count1++;
    count2++;
    if(count1 == 20)              //第一次鸣叫频率设置
    {
        Buzzer = !Buzzer;        //翻转蜂鸣器
        count1 = 0;
    }
    if(count2 == 40 && flag == 0) //第二次鸣叫频率设置
    {
        Buzzer = !Buzzer;
        count2 = 0;
        flag = 1;
    }
    if(count2 == 20 && flag == 1)
    {
        Buzzer = !Buzzer;
        count2 = 0;
        flag = 0;
    }
} 

void main()  
{ 
    EA = 1;        //打开总中断
    ET0 = 1;       //打开定时器0中断
    
    TR0 = 1;       //启动定时器0 
    while(1);
}

这个程序使用定时器0来产生中断,在中断服务程序中通过两个计数变量count1和count2来控制蜂鸣器鸣叫的频率和次数。

具体流程是:

  1. 第一次鸣叫频率设置为20ms,通过count1计数实现
  2. 第二次鸣叫频率设置为40ms,通过count2计数实现
  3. 通过标志位flag来控制鸣叫次数,flag=0时鸣叫一次,flag=1时鸣叫两次
  4. 然后循环重复

这样就实现了通过系统时钟更改一个循环鸣叫两次且每次鸣叫频率不相同的效果。