PWM

硬件配置

使用硬件PWM,通过定时器生成PWM波
1.首先确定自己需要输出的端口,然后找到其对应的定时器和通道
在这里插入图片描述
选择通道模式为PWM Generation,时钟选择为内部时钟
2.配置一些参数
在这里插入图片描述
a.预分频系数Prescaler,71,减少频率
b.计数模式,一般都使用向上计数
c.重装载值Arr,99
PWM频率的计算公式为:频率/(Prescaler+1)/(Arr+1)
3.其他一些参数
在这里插入图片描述
a.PWM输出模式
在这里插入图片描述
在这里插入图片描述
注意这里所说的高电平其实是有效电平,有效电平可以由CH Polarity设置!
b.脉冲值Pulse,决定占空比,duty=Pulse/(Arr+1)
c.CH Polarity,设为High就是高电平为有效值,设为Low就是低电平为有效值
d.CH Idle State 作用为决定当该通道不输出PWM波时,电平为高或低

函数编写(简易)

设置占空比

void pwm_set_duty(float Duty)
{
    // 根据占空比计算捕获/比较寄存器的值
    TIM2->CCR2 = (TIM2->ARR + 1) * (Duty / 100.0f);
}

设置频率

void pwm_set_frequency(int Frequency)
{
    // 获取定时器的时钟频率(假设TIM2使用的时钟频率为TIM2_CLK)
    uint32_t TIM2_CLK = 72000000;  // 例如72MHz, 需要根据实际情况调整,这里的值为经过预分频后的时钟频率

    // 根据输入的频率计算自动重装载寄存器的值
    uint32_t ARR_Value = (TIM2_CLK / Frequency) - 1;

    // 设置自动重装载寄存器
    TIM2->ARR = ARR_Value;

    // 更新捕获/比较寄存器CCR2,保持当前占空比不变
    TIM2->CCR2 = (ARR_Value + 1) * (TIM2->CCR2 / (float)(TIM2->ARR + 1));
    
    // 触发更新事件,刷新寄存器
    TIM2->EGR = TIM_EGR_UG;
}

API介绍

HAL_TIM_PWM_Start()

启动函数,需要自己调用

HAL_StatusTypeDef HAL_TIM_PWM_Start(TIM_HandleTypeDef *htim, uint32_t
Channel);

输入参数为定时器句柄和定时器通道

HAL_TIM_PWM_Stop()

HAL_StatusTypeDef HAL_TIM_PWM_Stop(TIM_HandleTypeDef *htim, uint32_t
Channel);

HAL_TIM_PWM_Start_IT()

HAL_TIM_PWM_Start_IT 函数⽤于启动指定定时器通道的PWM输出,并启⽤中断。

HAL_TIM_PWM_Stop_IT()

HAL_TIM_PWM_Stop_IT 函数⽤于停⽌指定定时器通道的PWM输出,并禁⽤中断.

输入捕获

基本原理

输⼊捕获是⼀种利⽤定时器外部输⼊信号触发定时器事件的功能。在STM32等微控制器中,定时器模块可以配置为在检测到输⼊信号的边沿(上升沿或下降沿)时,将当前定时器的计数值保存到捕获寄存器中,并触发中断或DMA请求。通过读取这些捕获值,可以计算输⼊信号的周期或脉宽

硬件框图

在这里插入图片描述
从硬件可以看出输入通道为PA15和PB4,那么就需要找到这两个端口对应的定时器比较通道

HAL库配置

在这里插入图片描述
Slave Mode设置为Reset Mode模式,Trigger Source 触发源设置为TI1FP1(这个就看那个端口对应的通道是哪个,就配置哪个通道就行了),Clock Source配置为内部时钟即可,在设置预分频系数和捕获的边沿

添加DMA进行读取
在这里插入图片描述
选择DMA通道
设置模式为循环读取模式
字宽设置为一个字宽

底层函数编写

首先需要初始化

  HAL_TIM_IC_Start_DMA(&htim3,TIM_CHANNEL_1,tim_ic_buffer,64);
uint32_t tim_ic_buffer[64];// 定义存储输入捕获值的缓冲区

然后是读取和计算频率的部分代码

/**
 * @brief 处理输入捕获数据
 * 
 * 此函数用于处理输入捕获数据。它计算tim_ic_buffer中所有捕获值的平均值,
 * 然后将其转换为对应的频率值(单位为Hz),并存储在tim_ic_val中。
 * 最后,调用limit_value函数对tim_ic_val进行限制,确保其在1到20000之间。
 */
void ic_proc(void)
{
    tim_ic_temp = 0;
    
    // 对缓冲区中的捕获值求和
    for (int i = 0; i < 64; i++)
    {
        tim_ic_temp += tim_ic_buffer[i];
    }

    // 计算平均值
    tim_ic_temp /= 64;

    // 计算频率值,单位为Hz
    tim_ic_val = (int)((float)(1000.0f * 1000.0f) / (float)tim_ic_temp);

    // 将计算得到的频率值限制在1到20000之间
    limit_value(&tim_ic_val, 1, 500, 20000);
}

完成!

Logo

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。

更多推荐