定时器输出比较功能

1.翻转模式

原理:当捕获/比较寄存器与计数器的值相等时发生翻转(高电平变低电平,低电平变高电平)

看CubeMX的配置:

 

代码里捕获/比较寄存器的值设置为100,当计数值计数到100就会翻转。开启更新中断然后重新去设置捕获比较寄存器的值。比如第一次溢出设置600。那么下次CNT到600又会翻转。持续不断每次进中断比上一次多加500。就会产生连续的方波。但这样CNT的肯定会溢出(16位:65535 )。捕获比较寄存器的值是16位的设置的值不能超过65535 如果超过那么会自动减65535(溢出)。又重复从0~65535。所以一直有方波产生。

main.c

int main(void)
{
  /* 复位所有外设,初始化Flash接口和系统滴答定时器 */
  HAL_Init();
  /* 配置系统时钟 */
  SystemClock_Config();
  
  /* 高级定时器初始化*/
  ADVANCED_TIMx_Init();
  
  /* 启动CH1比较输出并开启中断 */
  HAL_TIM_OC_Start_IT(&htimx,TIM_CHANNEL_1);
  
  /* 无限循环 */
  while (1){}
}
/* 定时器的更新中断 */
void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)  // CNT 500+500=1000  f = 2Mh(分频后的频率)/1000 = 2khz  可以用示波器去捕获
{
  __IO uint16_t count = 0; // 因为捕获比较寄存器的值是16位的设置的值不能超过65535 如果超过那么会自动减65535(溢出)
  count = __HAL_TIM_GetCounter(htim); // 获取捕获比较寄存器的值
  __HAL_TIM_SET_COMPARE(htim,TIM_CHANNEL_1,count+499); // 重新设置捕获比较寄存器的值
}

定时器的.h 文件 这里方便移植写成了板级支持包

#define ADVANCED_TIMx                       TIM8
#define ADVANCED_TIMx_GPIO_AF               GPIO_AF3_TIM8
#define ADVANCED_TIM_RCC_CLK_ENABLE()       __HAL_RCC_TIM8_CLK_ENABLE()
#define ADVANCED_TIM_RCC_CLK_DISABLE()      __HAL_RCC_TIM8_CLK_DISABLE()
#define ADVANCED_TIM_GPIO_RCC_CLK_ENABLE()  __HAL_RCC_GPIOI_CLK_ENABLE()
  
#define ADVANCED_TIM_OC_IRQn                TIM8_CC_IRQn
#define ADVANCED_TIM_OC_IRQHANDLER          TIM8_CC_IRQHandler
  
#define ADVANCED_TIM_CH1_PORT               GPIOI
#define ADVANCED_TIM_CH1_PIN                GPIO_PIN_5
#define ADVANCED_TIM_CH2_PORT               GPIOI
#define ADVANCED_TIM_CH2_PIN                GPIO_PIN_6
#define ADVANCED_TIM_CH3_PORT               GPIOI
#define ADVANCED_TIM_CH3_PIN                GPIO_PIN_7
#define ADVANCED_TIM_CH4_PORT               GPIOI
#define ADVANCED_TIM_CH4_PIN                GPIO_PIN_2

#endif 

// 定义定时器预分频,定时器实际时钟频率为:168MHz/(ADVANCED_TIMx_PRESCALER+1)
#define ADVANCED_TIM_PRESCALER            83  // 实际时钟频率为:2MHz

// 定义定时器周期,当定时器开始计数到ADVANCED_TIMx_PERIOD值并且重复计数寄存器为0时更新定时器并生成对应事件和中断
#define ADVANCED_TIM_PERIOD               0xFFFF  // 定时器产生中断频率为:1MHz/(35536)=1KHz,即1ms定时周期
// 定义高级定时器重复计数寄存器值,
#define ADVANCED_TIM_REPETITIONCOUNTER    0

// 最终定时器频率计算为: 168MHz/(ADVANCED_TIMx_PRESCALER+1)/(ADVANCED_TIM_REPETITIONCOUNTER+1)/(ADVANCED_TIMx_PERIOD+1)
// 比如需要产生1ms周期定时,可以设置为: 168MHz/(167+1)/(0+1)/(999+1)=1KHz,即1ms周期
// 这里设置 ADVANCED_TIMx_PRESCALER=167;ADVANCED_TIM_REPETITIONCOUNTER=0;ADVANCED_TIMx_PERIOD=999;

/* 扩展变量 ------------------------------------------------------------------*/
extern TIM_HandleTypeDef htimx;
/* 函数声明 ------------------------------------------------------------------*/
void ADVANCED_TIMx_Init(void);

要开启定时器的四个通道,并且用的高级定时器。

定时器的.c文件

#include "AdvancedTIM/bsp_AdvancedTIM.h" 

/* 私有类型定义 --------------------------------------------------------------*/
/* 私有宏定义 ----------------------------------------------------------------*/
/* 私有变量 ------------------------------------------------------------------*/
TIM_HandleTypeDef htimx; /* 句柄结构体 */

void HAL_TIM_OC_MspInit(TIM_HandleTypeDef* htim)
{
  GPIO_InitTypeDef GPIO_InitStruct;
  if(htim->Instance==ADVANCED_TIMx)
  {  
    /* 定时器通道功能引脚端口时钟使能 */
    ADVANCED_TIM_GPIO_RCC_CLK_ENABLE();
    
    /* 定时器通道1功能引脚IO初始化 */
    GPIO_InitStruct.Pin = ADVANCED_TIM_CH1_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = ADVANCED_TIMx_GPIO_AF;
    HAL_GPIO_Init(ADVANCED_TIM_CH1_PORT, &GPIO_InitStruct);
    
    /* 定时器通道2功能引脚IO初始化 */
    GPIO_InitStruct.Pin = ADVANCED_TIM_CH2_PIN;
    HAL_GPIO_Init(ADVANCED_TIM_CH2_PORT, &GPIO_InitStruct);
    
    /* 定时器通道3功能引脚IO初始化 */
    GPIO_InitStruct.Pin = ADVANCED_TIM_CH3_PIN;
    HAL_GPIO_Init(ADVANCED_TIM_CH3_PORT, &GPIO_InitStruct);
    
    /* 定时器通道4功能引脚IO初始化 */
    GPIO_InitStruct.Pin = ADVANCED_TIM_CH4_PIN;
    HAL_GPIO_Init(ADVANCED_TIM_CH4_PORT, &GPIO_InitStruct);
    
    HAL_NVIC_SetPriority(ADVANCED_TIM_OC_IRQn,1,0); /* 输出比较中断 */
    HAL_NVIC_EnableIRQ(ADVANCED_TIM_OC_IRQn); /* 输出比较中断使能 */
  }
}


void ADVANCED_TIMx_Init(void)
{
  TIM_ClockConfigTypeDef sClockSourceConfig; /* 定时器时钟结构体 */
  TIM_MasterConfigTypeDef sMasterConfig;     /* 主模式配置结构体 */
  TIM_OC_InitTypeDef sConfigOC; /* 输出比较结构体 */
  
  /* 定时器外设时钟使能 */
  ADVANCED_TIM_RCC_CLK_ENABLE();
  
  htimx.Instance = ADVANCED_TIMx;
  htimx.Init.Prescaler = ADVANCED_TIM_PRESCALER;
  htimx.Init.CounterMode = TIM_COUNTERMODE_UP;
  htimx.Init.Period = ADVANCED_TIM_PERIOD;
  htimx.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;
  htimx.Init.RepetitionCounter = ADVANCED_TIM_REPETITIONCOUNTER;//重复计数为0+1
  HAL_TIM_OC_Init(&htimx);

  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;//选择内部时钟
  HAL_TIM_ConfigClockSource(&htimx, &sClockSourceConfig);
  
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  HAL_TIMEx_MasterConfigSynchronization(&htimx, &sMasterConfig);


  sConfigOC.OCMode = TIM_OCMODE_TOGGLE;   // 比较输出翻转模式
  sConfigOC.Pulse = 100;                 // CH1当CNT计数到100时 电平翻转
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; /* 输出极性的选择 */
  sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH; /* 互补输出极性的选择 */
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;  // 快速模式
  sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET; // 空闲状态
  sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET; // 互补的空闲状态
  
  /* 配置CH1为比较输出模式 */
  HAL_TIM_OC_ConfigChannel(&htimx, &sConfigOC, TIM_CHANNEL_1);
  /* 配置CH2为比较输出模式 */
  sConfigOC.Pulse = 200;     // CH2当CNT计数到200时 电平翻转
  HAL_TIM_OC_ConfigChannel(&htimx, &sConfigOC, TIM_CHANNEL_2);
  /* 配置CH3为比较输出模式 */
  sConfigOC.Pulse = 300;     // CH2当CNT计数到300时 电平翻转
  HAL_TIM_OC_ConfigChannel(&htimx, &sConfigOC, TIM_CHANNEL_3);
  /* 配置CH4为比较输出模式 */
  sConfigOC.Pulse = 400;     // CH2当CNT计数到400时 电平翻转
  HAL_TIM_OC_ConfigChannel(&htimx, &sConfigOC, TIM_CHANNEL_4 );
}

在这里最核心的就是定时器输出比较结构体的配置:

  sConfigOC.OCMode = TIM_OCMODE_TOGGLE;   // 比较输出翻转模式
  sConfigOC.Pulse = 100;                 // CH1当CNT计数到100时 电平翻转
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; /* 输出极性的选择 */
  sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH; /* 互补输出极性的选择 */
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;  // 快速模式
  sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET; // 空闲状态
  sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET; // 互补的空闲状态

代码中定时器的CH1为100,CH2为200,CH3为300,CH4为400.当用示波器去捕捉。

2.定时器PWM输出

PWM就是用数字信号达到模拟信号的效果。要理解占空比的概念:在一个周期内高电平的持续时间。

下面是CubeMX的配置:

 

 在这里配置PWM1的模式(与PWM2是相反的会一个可以了)

TM32 定时器的 PWM 存在两种模式,即 PWM1 模式与 PWM2 模式,两种模式相似却又恰恰相反。

PWM1 模式:向上计数,当 TIMx_CNT < TIMx_CCRn 时,定时器 TIMx 的通道 n 为有效电平,否则为无效电平;向下计数,当 TIMx_CNT > TIMx_CCRn 时,定时器 TIMx 的通道 n 为无效电平,否则为有效电平。

PWM2 模式:向上计数,当 TIMx_CNT < TIMx_CCRn 时,定时器 TIMx 的通道 n 为无效电平,否则为有效电平;向下计数,当 TIMx_CNT > TIMx_CCRn 时,定时器 TIMx 的通道 n 为有效电平,否则为无效电平。

其实在定时器的输出比较就是CNT不停跟捕获/比较寄存器的值做比较。

main.c

int main(void)
{
  /* 复位所有外设,初始化Flash接口和系统滴答定时器 */
  HAL_Init();
  /* 配置系统时钟 */
  SystemClock_Config();
    /* 初始化串口并配置串口中断优先级 */
  MX_DEBUG_USART_Init();
  /* 通用定时器初始化并配置PWM输出功能 */
  GENERAL_TIMx_Init();
  
  /* 启动通道PWM输出并且使能定时器 */
  HAL_TIM_PWM_Start(&htimx,TIM_CHANNEL_1);  // 20%的高电平 80%的低电平
  HAL_TIM_PWM_Start(&htimx,TIM_CHANNEL_2);  // 40%的高电平 60%的低电平
  HAL_TIM_PWM_Start(&htimx,TIM_CHANNEL_3);  // 60%的高电平 40%的低电平
  HAL_TIM_PWM_Start(&htimx,TIM_CHANNEL_4);  // 80%的高电平 20%的低电平
  /* 无限循环 */
  while (1)
  {
  }
}

定时器的.h

#define GENERAL_TIMx                        TIM2
#define GENERAL_TIM_GPIO_AF                 GPIO_AF1_TIM2
#define GENERAL_TIM_RCC_CLK_ENABLE()        __HAL_RCC_TIM2_CLK_ENABLE()
#define GENERAL_TIM_RCC_CLK_DISABLE()       __HAL_RCC_TIM2_CLK_DISABLE()
#define GENERAL_TIM_GPIO_RCC_CLK_ENABLE()   {__HAL_RCC_GPIOA_CLK_ENABLE();__HAL_RCC_GPIOB_CLK_ENABLE();}
#define GENERAL_TIM_CH1_PORT                GPIOA
#define GENERAL_TIM_CH1_PIN                 GPIO_PIN_15
#define GENERAL_TIM_CH2_PORT                GPIOB
#define GENERAL_TIM_CH2_PIN                 GPIO_PIN_3
#define GENERAL_TIM_CH3_PORT                GPIOB
#define GENERAL_TIM_CH3_PIN                 GPIO_PIN_10
#define GENERAL_TIM_CH4_PORT                GPIOB
#define GENERAL_TIM_CH4_PIN                 GPIO_PIN_11

// 定义定时器预分频,定时器实际时钟频率为:84MHz/(GENERAL_TIMx_PRESCALER+1)
#define GENERAL_TIM_PRESCALER            41  // 实际时钟频率为:1MHz

// 定义定时器周期,当定时器开始计数到GENERAL_TIMx_PERIOD值是更新定时器并生成对应事件和中断
#define GENERAL_TIM_PERIOD               999  // 定时器产生中断频率为:1MHz/(999+1)=1KHz,即1ms定时周期(改变捕获比较寄存器的值周期不会改变只会改变占空比)

#define GENERAL_TIM_CH1_PULSE            200   // 定时器通道1占空比为:GENERAL_TIM_CH1_PULSE/GENERAL_TIM_PERIOD*100%=200/1000*100%=20%
#define GENERAL_TIM_CH2_PULSE            400   // 定时器通道2占空比为:GENERAL_TIM_CH2_PULSE/GENERAL_TIM_PERIOD*100%=400/1000*100%=40%
#define GENERAL_TIM_CH3_PULSE            600   // 定时器通道3占空比为:GENERAL_TIM_CH3_PULSE/GENERAL_TIM_PERIOD*100%=600/1000*100%=60%
#define GENERAL_TIM_CH4_PULSE            800   // 定时器通道4占空比为:GENERAL_TIM_CH4_PULSE/GENERAL_TIM_PERIOD*100%=800/1000*100%=80%


/* 扩展变量 ------------------------------------------------------------------*/
extern TIM_HandleTypeDef htimx;

/* 函数声明 ------------------------------------------------------------------*/
void GENERAL_TIMx_Init(void);

定时器的.c

TIM_HandleTypeDef htimx;

/* 扩展变量 ------------------------------------------------------------------*/
/* 私有函数原形 --------------------------------------------------------------*/
/* 函数体 --------------------------------------------------------------------*/
/**
  * 函数功能: 定时器硬件初始化配置
  * 输入参数: htim:定时器句柄类型指针
  * 返 回 值: 无
  * 说    明: 该函数被GENERAL_TIMx_Init函数调用
  */
void HAL_GeneralTIM_MspPostInit(void)
{
  GPIO_InitTypeDef GPIO_InitStruct;
  
  /* 基本定时器外设时钟使能 */
  GENERAL_TIM_RCC_CLK_ENABLE();
  /* 定时器通道功能引脚端口时钟使能 */
  GENERAL_TIM_GPIO_RCC_CLK_ENABLE();
  
  /* 定时器通道1功能引脚IO初始化 */
  GPIO_InitStruct.Pin = GENERAL_TIM_CH1_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  GPIO_InitStruct.Alternate = GENERAL_TIM_GPIO_AF;
  HAL_GPIO_Init(GENERAL_TIM_CH1_PORT, &GPIO_InitStruct);

  /* 定时器通道2功能引脚IO初始化 */
  GPIO_InitStruct.Pin = GENERAL_TIM_CH2_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  GPIO_InitStruct.Alternate = GENERAL_TIM_GPIO_AF;
  HAL_GPIO_Init(GENERAL_TIM_CH2_PORT, &GPIO_InitStruct);

  /* 定时器通道3功能引脚IO初始化 */
  GPIO_InitStruct.Pin = GENERAL_TIM_CH3_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  GPIO_InitStruct.Alternate = GENERAL_TIM_GPIO_AF;
  HAL_GPIO_Init(GENERAL_TIM_CH3_PORT, &GPIO_InitStruct);
  
  /* 定时器通道4功能引脚IO初始化 */
  GPIO_InitStruct.Pin = GENERAL_TIM_CH4_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  GPIO_InitStruct.Alternate = GENERAL_TIM_GPIO_AF;
  HAL_GPIO_Init(GENERAL_TIM_CH4_PORT, &GPIO_InitStruct);    
}

/**
  * 函数功能: 通用定时器初始化并配置通道PWM输出
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明: 无
  */
void GENERAL_TIMx_Init(void)
{
  TIM_ClockConfigTypeDef sClockSourceConfig;
  TIM_MasterConfigTypeDef sMasterConfig;
  TIM_OC_InitTypeDef sConfigOC;
  
  HAL_GeneralTIM_MspPostInit();
  
  htimx.Instance = GENERAL_TIMx;
  htimx.Init.Prescaler = GENERAL_TIM_PRESCALER;
  htimx.Init.CounterMode = TIM_COUNTERMODE_UP;
  htimx.Init.Period = GENERAL_TIM_PERIOD;
  htimx.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;
  HAL_TIM_Base_Init(&htimx);

  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;//选择内部时钟
  HAL_TIM_ConfigClockSource(&htimx, &sClockSourceConfig);

  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  HAL_TIMEx_MasterConfigSynchronization(&htimx, &sMasterConfig);
  
  sConfigOC.OCMode = TIM_OCMODE_PWM1;//选择PWM模式1
  sConfigOC.Pulse = GENERAL_TIM_CH1_PULSE;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; // 有效电平为高电平
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  HAL_TIM_PWM_ConfigChannel(&htimx, &sConfigOC, TIM_CHANNEL_1);

  sConfigOC.Pulse = GENERAL_TIM_CH2_PULSE;
  HAL_TIM_PWM_ConfigChannel(&htimx, &sConfigOC, TIM_CHANNEL_2);

  sConfigOC.Pulse = GENERAL_TIM_CH3_PULSE;
  HAL_TIM_PWM_ConfigChannel(&htimx, &sConfigOC, TIM_CHANNEL_3);

  sConfigOC.Pulse = GENERAL_TIM_CH4_PULSE;
  HAL_TIM_PWM_ConfigChannel(&htimx, &sConfigOC, TIM_CHANNEL_4);
  
}

四个通道的占空比不是一样的,当周期是一样(没有改变ARR值所以不会改变周期)

如果要做呼吸灯那么可以通过不停改占空比比如:ARR = 1000, 可以在0~1000内设置一组指数曲线上升的值与指数曲线下降的值。(设置不同的捕获比较寄存器的值)在比较低内的时间内不停改变循环捕获比较寄存器的值就可以了。重点还是:定时器的输出比较就是CNT不停跟捕获/比较寄存器的值做比较。


 

  • 1
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是基于STM32使用HC-SR04超声波测距,同时使用定时器输出比较功能根据超声波测出的距离,距离障碍物越近,蜂鸣器响声越快的库函数。 首先,我们需要设置GPIO和定时器的相关参数,具体代码如下: ```c #include "stm32f10x.h" #define TRIG_PIN GPIO_Pin_0 #define ECHO_PIN GPIO_Pin_1 #define TRIG_PORT GPIOA #define ECHO_PORT GPIOA #define TIM2_PERIOD 0xFFFF void GPIO_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin = TRIG_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(TRIG_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = ECHO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(ECHO_PORT, &GPIO_InitStructure); } void TIM2_Configuration(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); TIM_TimeBaseStructure.TIM_Period = TIM2_PERIOD; TIM_TimeBaseStructure.TIM_Prescaler = 71; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 0; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC3Init(TIM2, &TIM_OCInitStructure); TIM_Cmd(TIM2, ENABLE); } int main(void) { GPIO_Configuration(); TIM2_Configuration(); while (1) { uint32_t duration, distance; GPIO_ResetBits(TRIG_PORT, TRIG_PIN); Delay_us(2); GPIO_SetBits(TRIG_PORT, TRIG_PIN); Delay_us(10); GPIO_ResetBits(TRIG_PORT, TRIG_PIN); while (GPIO_ReadInputDataBit(ECHO_PORT, ECHO_PIN) == RESET); duration = 0; while (GPIO_ReadInputDataBit(ECHO_PORT, ECHO_PIN) == SET) { duration++; Delay_us(2); } distance = duration / 58; if (distance <= 20) { TIM_SetCompare3(TIM2, TIM2_PERIOD * 20 / distance); } else { TIM_SetCompare3(TIM2, 0); } } } ``` 上面的代码中,我们首先定义了超声波模块的引脚和端口,以及定时器的周期。然后,在`GPIO_Configuration()`函数中,我们初始化了超声波模块的引脚,将TRIG引脚配置为输出模式,ECHO引脚配置为输入模式。在`TIM2_Configuration()`函数中,我们初始化了定时器2,设置了定时器的周期、分频系数、计数模式、PWM模式等。 在主函数中,我们通过超声波模块测量距离,并根据距离设置定时器的PWM输出。当距离小于等于20cm时,PWM输出的占空比会随着距离的减小而增大,从而使蜂鸣器发出更快的响声;当距离大于20cm时,PWM输出的占空比为0,蜂鸣器不响。 需要注意的是,`Delay_us()`函数需要自行实现,这里我们可以通过定时器的延时方式来实现,具体代码如下: ```c void Delay_us(uint32_t nus) { TIM_SetCounter(TIM3, 0); while (TIM_GetCounter(TIM3) < nus); } ``` 这里我们使用了另一个定时器TIM3来实现微秒级的延时。当然,也可以使用其他方式来实现延时,比如使用SysTick定时器或者循环延时等方式。 以上就是基于STM32使用HC-SR04超声波测距,同时使用定时器输出比较功能根据超声波测出的距离,距离障碍物越近,蜂鸣器响声越快的库函数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值