STM32 HAL库 高级定时器输出指定个数PWM实验

本文详细描述了如何使用STM32定时器8的通道1实现2HzPWM信号,控制LED1的亮灭,并涉及了定时器的基础配置、中断服务函数以及GPIO的连接。
摘要由CSDN通过智能技术生成

 实验要求:

通过定时器8通道1实现指定个数PWM输出,用于控制LED1的亮灭

1,确定PWM波的周期/频率,2Hz为例,PSC=7199,ARR=4999

     Tout= ((arr+1)*(psc+1))/Tclk= ((4999+1)*(7199+1))/72000000=0.5s

2,配置输出比较模式为:PWM模式1

      通道输出极性为:高电平有效

      占空比:50% 

硬件知识:

由原理图可知 定时器8通道1 连接在PC6,LED1连接在PE5上,所以要在开发板上用杜邦线将PC6PE5引脚连接起来。

配置步骤:

1,配置定时器基础工作参数 

        HAL_TIM_PWM_Init()

2,定时器PWM输出MSP初始化

        HAL_TIM_PWM_MspInit()   配置NVIC、CLOCK、GPIO等

3,配置PWM模式/比较值等   

        HAL_TIM_PWM_ConfigChannel()

4,设置优先级,使能中断   

        HAL_NVIC_SetPriority()、 HAL_NVIC_EnableIRQ()

5,使能定时器更新中断   

         __HAL_TIM_ENABLE_IT()

6,使能输出、主输出、计数器   

        HAL_TIM_PWM_Start()

7,编写中断服务函数  

        TIMx_IRQHandler()等    HAL_TIM_IRQHandler()

8,编写更新中断回调函数   

        HAL_TIM_PeriodElapsedCallback()

 源码

atim.c

#include "./BSP/TIMER/atim.h"

TIM_HandleTypeDef g_timx_npwm_chy_handle;           //定时器8句柄

static uint8_t g_npwm_remain = 0;
//高级定时器TIMX 通道Y 输出指定个数PWM 初始化函数
void atim_timx_npwm_chy_init(uint16_t psc, uint16_t arr)
{
    TIM_OC_InitTypeDef timx_oc_npwm_chy = {0};
    
    g_timx_npwm_chy_handle.Instance = TIM8;                     //定时器8
    g_timx_npwm_chy_handle.Init.Prescaler = psc;                //定时器分频
    g_timx_npwm_chy_handle.Init.Period = arr;                   //自动重装载值
    g_timx_npwm_chy_handle.Init.CounterMode = TIM_COUNTERMODE_UP;//递增计数模式
    g_timx_npwm_chy_handle.Init.RepetitionCounter = 0;          //重复计数器初始值
    HAL_TIM_PWM_Init(&g_timx_npwm_chy_handle);
    
    timx_oc_npwm_chy.OCMode = TIM_OCMODE_PWM1;                  //模式选择PWM1
    timx_oc_npwm_chy.OCPolarity = TIM_OCPOLARITY_HIGH;          //输出比较极性为高
    timx_oc_npwm_chy.Pulse = arr / 2;                           //设置比较值
                                                                //设置为arr的一半得到占空比为50%
    HAL_TIM_PWM_ConfigChannel(&g_timx_npwm_chy_handle, &timx_oc_npwm_chy, TIM_CHANNEL_1);
    
    __HAL_TIM_ENABLE_IT(&g_timx_npwm_chy_handle, TIM_IT_UPDATE);     //使能定时器更新中断
    HAL_TIM_PWM_Start(&g_timx_npwm_chy_handle, TIM_CHANNEL_1);
}
//定时器 PWM输出 MSP初始化函数
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{
    if(htim->Instance == TIM8)
    {
     GPIO_InitTypeDef gpio_init_struct;
     __HAL_RCC_GPIOC_CLK_ENABLE();
     __HAL_RCC_TIM8_CLK_ENABLE(); 

    gpio_init_struct.Pin = GPIO_PIN_6;
    gpio_init_struct.Mode = GPIO_MODE_AF_PP;            /* 推挽式复用 */
    gpio_init_struct.Pull = GPIO_PULLUP;                    /* 上拉 */
    gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;          /* 高速 */
    HAL_GPIO_Init(GPIOC, &gpio_init_struct);
    
    HAL_NVIC_SetPriority(TIM8_UP_IRQn, 1, 3);
    HAL_NVIC_EnableIRQ(TIM8_UP_IRQn);
    }
}
//高级定时器TIMX NPWM设置PWM个数函数
void atim_timx_npwm_chy_set(uint8_t npwm)
{
    if(npwm == 0)
    {
        return ;
    }
    else
    {
        g_npwm_remain = npwm;
        HAL_TIM_GenerateEvent(&g_timx_npwm_chy_handle, TIM_EVENTSOURCE_UPDATE);//软件的更新事件
        __HAL_TIM_ENABLE(&g_timx_npwm_chy_handle);  //使能定时器更新中断
    }
}

//定时器8中断服务函数
void TIM8_UP_IRQHandler(void)
{
    HAL_TIM_IRQHandler(&g_timx_npwm_chy_handle);
}

//定时器更新中断回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if(htim->Instance == TIM8)
    {
        if(g_npwm_remain)
        {
            TIM8->RCR = g_npwm_remain - 1;
            HAL_TIM_GenerateEvent(&g_timx_npwm_chy_handle, TIM_EVENTSOURCE_UPDATE);//软件的更新事件
            __HAL_TIM_ENABLE(&g_timx_npwm_chy_handle);      //使能定时器更新中断     
            g_npwm_remain = 0;
        }
        else
        {
            TIM8->CR1 &= ~(1 << 0);             //关闭计数器
        }
    }
}

 atim.h

#ifndef __TIMER_H
#define __TIMER_H

#include "./SYSTEM/sys/sys.h"

void atim_timx_npwm_chy_set(uint8_t npwm);
void atim_timx_npwm_chy_init(uint16_t psc, uint16_t arr);

#endif

 main.c

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/delay/delay.h"
#include "./SYSTEM/usart/usart.h"
#include "./BSP/LED/led.h"
#include "./BSP/KEY/key.h"
#include "./BSP/TIMER/atim.h"

int main(void)
{
    uint8_t key;
    uint8_t t = 0;
    
    HAL_Init();                                 /* 初始化HAL库 */
    sys_stm32_clock_init(RCC_PLL_MUL9);         /* 设置时钟,72M */
    delay_init(72);                             /* 初始化延时函数 */
    led_init();                                 /* 初始化LED */
    key_init();
    usart_init(115200);
    
    
    atim_timx_npwm_chy_init(7200 - 1, 5000 - 1);
    atim_timx_npwm_chy_set(5);
    
    //把PE5设置为输入,避免与PC6冲突
     GPIO_InitTypeDef gpio_init_struct;
     __HAL_RCC_GPIOE_CLK_ENABLE();                                 /* LED0时钟使能 */

    gpio_init_struct.Pin = GPIO_PIN_5;                   /* LED0引脚 */
    gpio_init_struct.Mode = GPIO_MODE_INPUT;            /* 推挽输出 */
    gpio_init_struct.Pull = GPIO_PULLUP;                    /* 上拉 */
    gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;          /* 高速 */
    HAL_GPIO_Init(GPIOE, &gpio_init_struct);       /* 初始化LED0引脚 */
    
    while(1)
    {
        key = key_scan(0);
        if(key == KEY0_PRES)
        {
            atim_timx_npwm_chy_set(3);
        }
        
        t++;
        delay_ms(10);
        
        if(t > 50)
        {
            t = 0;
            LED0_TOGGLE();
        }
    }
}

  • 14
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
您可以使用STM32HAL库来配置定时器输出双极性SPWM波。下面是一个基本的示例代码,演示了如何使用STM32HAL库定时器来生成双极性SPWM波。 首先,您需要在CubeMX中配置定时器和引脚。在"Pinout & Configuration"选项卡中,选择定时器并将其配置为PWM输出模式。然后,将定时器的引脚连接到适当的输出引脚。 接下来,在您的代码中包含必要的头文件,并定义一些全局变量和宏: ```c #include "stm32f4xx_hal.h" // 定时器句柄 TIM_HandleTypeDef htim; // SPWM波的周期和占空比 uint16_t period = 2000; float dutyCycle = 0.5; // SPWM波的参数 float amplitude = 1000.0; float frequency = 50.0; ``` 然后,在`main`函数中初始化定时器和GPIO引脚: ```c int main(void) { // 初始化HAL库 HAL_Init(); // 配置系统时钟 SystemClock_Config(); // 初始化定时器 TIM_Config(); // 启动定时器 HAL_TIM_PWM_Start(&htim, TIM_CHANNEL_1); // 无限循环 while (1) { // 更新占空比 TIM_SetDutyCycle(dutyCycle); // 延时一段时间 HAL_Delay(10); } } ``` 接下来,在`TIM_Config`函数中进行定时器的配置: ```c void TIM_Config(void) { // 使能定时器时钟 __HAL_RCC_TIM1_CLK_ENABLE(); // 初始化定时器句柄 htim.Instance = TIM1; htim.Init.Prescaler = 0; htim.Init.CounterMode = TIM_COUNTERMODE_UP; htim.Init.Period = period - 1; htim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim.Init.RepetitionCounter = 0; HAL_TIM_PWM_Init(&htim); // 配置PWM通道 TIM_OC_InitTypeDef sConfigOC; sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = period * dutyCycle; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; HAL_TIM_PWM_ConfigChannel(&htim, &sConfigOC, TIM_CHANNEL_1); } ``` 最后,在`TIM_SetDutyCycle`函数中更新占空比: ```c void TIM_SetDutyCycle(float dutyCycle) { // 计算SPWM波的脉冲宽度 uint16_t pulseWidth = amplitude * (1 + sin(2 * PI * frequency * dutyCycle)) / 2; // 更新PWM通道的脉冲宽度 TIM_OC_InitTypeDef sConfigOC; sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = pulseWidth; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; HAL_TIM_PWM_ConfigChannel(&htim, &sConfigOC, TIM_CHANNEL_1); // 重新启动PWM通道 HAL_TIM_PWM_Start(&htim, TIM_CHANNEL_1); } ``` 这样,您就可以使用STM32HAL库定时器输出双极性SPWM波。请根据您的具体需求调整代码中的参数和配置。希望对您有所帮助!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

从糕手变成高手

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值