打印
[N32L4xx]

基于国民技术N32L40xx的PWM输出

[复制链接]
91|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Zuocidian|  楼主 | 2025-8-1 09:56 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
完整代码如下
H文件源码
#ifndef __BSP_PWM_H__
#define __BSP_PWM_H__

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

#include "n32l40x.h"

typedef enum
{
    TIM_CH_01 = 0,
    TIM_CH_02,
    TIM_CH_03,
    TIM_CH_04
}tim_channel_e;


typedef enum
{
    GPIO_TIM1_AF_CH_1 = GPIO_AF2_TIM1,  // PA8
    GPIO_TIM1_AF_CH_2 = GPIO_AF2_TIM1,  // PA9
    GPIO_TIM1_AF_CH_3 = GPIO_AF2_TIM1,  // PA10
    GPIO_TIM1_AF_CH_4 = GPIO_AF2_TIM1,  // PA11

    GPIO_TIM1_AF_CHN_1_01 = GPIO_AF2_TIM1,  // PB13
    GPIO_TIM1_AF_CHN_1_02 = GPIO_AF5_TIM1,  // PA7
    GPIO_TIM1_AF_CHN_1_03 = GPIO_AF2_TIM1,  // PC13

    GPIO_TIM1_AF_CHN_2_01 = GPIO_AF2_TIM1,  // PB14
    GPIO_TIM1_AF_CHN_2_02 = GPIO_AF5_TIM1,  // PB0
    GPIO_TIM1_AF_CHN_2_03 = GPIO_AF7_TIM1,  // PB6

    GPIO_TIM1_AF_CHN_3_01 = GPIO_AF2_TIM1,  // PB15
    GPIO_TIM1_AF_CHN_3_02 = GPIO_AF5_TIM1,  // PB1
    GPIO_TIM1_AF_CHN_3_03 = GPIO_AF2_TIM1,  // PD14

    GPIO_TIM2_AF_CH_1_01 = GPIO_AF2_TIM2,  // PA0
    GPIO_TIM2_AF_CH_1_02 = GPIO_AF5_TIM2,  // PA15

    GPIO_TIM2_AF_CH_2_01 = GPIO_AF2_TIM2,  // PA1
    GPIO_TIM2_AF_CH_2_02 = GPIO_AF2_TIM2,  // PB3

    GPIO_TIM2_AF_CH_3_01 = GPIO_AF2_TIM2,  // PA2
    GPIO_TIM2_AF_CH_3_02 = GPIO_AF2_TIM2,  // PB10

    GPIO_TIM2_AF_CH_4 = GPIO_AF2_TIM2,  // PB11

    GPIO_TIM3_AF_CH_1_01 = GPIO_AF2_TIM3,  // PA6
    GPIO_TIM3_AF_CH_1_02 = GPIO_AF2_TIM3,  // PB4
    GPIO_TIM3_AF_CH_1_03 = GPIO_AF2_TIM3,  // PC6

    GPIO_TIM3_AF_CH_2_01 = GPIO_AF2_TIM3,  // PA7
    GPIO_TIM3_AF_CH_2_02 = GPIO_AF4_TIM3,  // PB5
    GPIO_TIM3_AF_CH_2_03 = GPIO_AF2_TIM3,  // PC7

    GPIO_TIM3_AF_CH_3_01 = GPIO_AF2_TIM3,  // PB0
    GPIO_TIM3_AF_CH_3_02 = GPIO_AF2_TIM3,  // PC8

    GPIO_TIM3_AF_CH_4_01 = GPIO_AF2_TIM3,  // PB1
    GPIO_TIM3_AF_CH_4_02 = GPIO_AF2_TIM3,  // PC9

    GPIO_TIM4_AF_CH_1 = GPIO_AF2_TIM4,  // PB6
    GPIO_TIM4_AF_CH_2 = GPIO_AF2_TIM4,  // PB7
    GPIO_TIM4_AF_CH_3 = GPIO_AF2_TIM4,  // PB8
    GPIO_TIM4_AF_CH_4 = GPIO_AF2_TIM4,  // PB9

    GPIO_TIM5_AF_CH_1 = GPIO_AF1_TIM5,  // PA0
    GPIO_TIM5_AF_CH_2 = GPIO_AF7_TIM5,  // PA1
    GPIO_TIM5_AF_CH_3 = GPIO_AF6_TIM5,  // PA2
    GPIO_TIM5_AF_CH_4 = GPIO_AF7_TIM5,  // PA3

    GPIO_TIM8_AF_CH_1 = GPIO_AF6_TIM8,  // PC6
    GPIO_TIM8_AF_CH_2 = GPIO_AF6_TIM8,  // PC7
    GPIO_TIM8_AF_CH_3 = GPIO_AF6_TIM8,  // PC8
    GPIO_TIM8_AF_CH_4 = GPIO_AF6_TIM8,  // PC9

    GPIO_TIM8_AF_CHN_1 = GPIO_AF6_TIM8,  // PA7
    GPIO_TIM8_AF_CHN_2 = GPIO_AF7_TIM8,  // PC0
    GPIO_TIM8_AF_CHN_3 = GPIO_AF0_TIM8,  // PC1

    GPIO_TIM9_AF_CH_1 = GPIO_AF1_TIM9,  // PB12
    GPIO_TIM9_AF_CH_2 = GPIO_AF1_TIM9,  // PB13
    GPIO_TIM9_AF_CH_3 = GPIO_AF1_TIM9,  // PB14
    GPIO_TIM9_AF_CH_4 = GPIO_AF1_TIM9,  // PB15
}pwm_gpio_af_e;

typedef struct
{
    uint16_t        gpio_pin;  /* gpio引脚编号 */
    pwm_gpio_af_e   gpio_af;   /* gpio复用编号 */
    GPIO_Module*    gpio_port; /* GPIO端口 */
}pwm_gpio_t;

typedef struct
{
    TIM_Module*     tim_n;   /* 定时器编号 */
    tim_channel_e   tim_ch;  /* 定时器输出通道 */
    FunctionalState enable;  /* 是否使能定时器 */
}pwm_tim_t;

typedef struct
{
    uint32_t freq;        /* PWM信号频率,单位Hz 0 表示禁止输出 */
    uint32_t duty_cycle;  /* PWM信号占空比,单位:万分之一。如5000,表示50.00%的占空比 */
}pwm_param_t;

void bsp_pwm_output(pwm_gpio_t *gpio, pwm_tim_t *tim, pwm_param_t *param);
void bsp_pwm_output_n(pwm_gpio_t *gpio, pwm_tim_t *tim, pwm_param_t *param);

void bsp_pwm_output_init(void);

#endif




C文件源码
#include "bsp.h"

/***************************************************************************************************
* @fn      get_tim_rcc
*
* @brief   获取定时器的RCC初始化值
*
* @param   tim 定时器地址编号
*
* @return  定时器的RCC初始化值
*/
uint32_t get_tim_rcc(TIM_Module* tim)
{
    uint32_t rcc = 0;

    if (TIM1 == tim)
    {
        rcc = RCC_APB2_PERIPH_TIM1;
    }
    else if (TIM8 == tim)
    {
        rcc = RCC_APB2_PERIPH_TIM8;
    }
    else if (TIM2 == tim)
    {
        rcc = RCC_APB1_PERIPH_TIM2;
    }
    else if (TIM3 == tim)
    {
        rcc = RCC_APB1_PERIPH_TIM3;
    }
    else if (TIM4 == tim)
    {
        rcc = RCC_APB1_PERIPH_TIM4;
    }
    else if (TIM5 == tim)
    {
        rcc = RCC_APB1_PERIPH_TIM5;
    }
    else if (TIM9 == tim)
    {
        rcc = RCC_APB1_PERIPH_TIM9;
    }

    return rcc;
}

/***************************************************************************************************
* @fn      get_gpio_rcc
*
* @brief   获取GPIO的RCC初始化值
*
* @param   gpio_port GPIO端口地址编号
*
* @return  GPIO的RCC初始化值
*/
uint32_t get_gpio_rcc(GPIO_Module* gpio_port)
{
    uint32_t rcc = 0;

    if (GPIOA == gpio_port)
    {
        rcc = RCC_APB2_PERIPH_GPIOA;
    }
    else if (GPIOB == gpio_port)
    {
        rcc = RCC_APB2_PERIPH_GPIOB;
    }
    else if (GPIOC == gpio_port)
    {
        rcc = RCC_APB2_PERIPH_GPIOC;
    }
    else if (GPIOD == gpio_port)
    {
        rcc = RCC_APB2_PERIPH_GPIOD;
    }

    return rcc;
}

/***************************************************************************************************
* @fn      config_gpio_pwm
*
* @brief   把GPIO配置成pwm输出的模式
*
* @param   gpio GPIO配置信息
*
* @return  无
*/
static void config_gpio_pwm(pwm_gpio_t *gpio)
{
    GPIO_InitType GPIO_Config;

    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE);
    RCC_EnableAPB2PeriphClk(get_gpio_rcc(gpio->gpio_port), ENABLE);

    GPIO_InitStruct(&GPIO_Config);

    GPIO_Config.Pin            = gpio->gpio_pin;
    GPIO_Config.GPIO_Mode      = GPIO_Mode_AF_PP;
    GPIO_Config.GPIO_Current   = GPIO_DC_4mA;
    GPIO_Config.GPIO_Alternate = gpio->gpio_af;
    GPIO_InitPeripheral(gpio->gpio_port, &GPIO_Config);
}

/***************************************************************************************************
* @fn      config_gpio_output
*
* @brief   把GPIO配置成通用的推挽输出模式
*
* @param   gpio GPIO配置信息
*
* @return  无
*/
static void config_gpio_output(pwm_gpio_t *gpio)
{
    GPIO_InitType GPIO_Config;

    RCC_EnableAPB2PeriphClk(get_gpio_rcc(gpio->gpio_port), ENABLE);

    GPIO_InitStruct(&GPIO_Config);

    GPIO_Config.Pin          = gpio->gpio_pin;
    GPIO_Config.GPIO_Current = GPIO_DC_4mA;
    GPIO_Config.GPIO_Pull    = GPIO_No_Pull;
    GPIO_Config.GPIO_Mode    = GPIO_Mode_Out_PP;
    GPIO_InitPeripheral(gpio->gpio_port, &GPIO_Config);
}

/***************************************************************************************************
* @fn      bsp_pwm_output
*
* @brief   pwm输出 正相(P相)
*
* @param   gpio GPIO配置信息
* @param   tim 定时器配置信息
* @param   param pwm输出参数
*
* @return  无
*/
void bsp_pwm_output(pwm_gpio_t *gpio, pwm_tim_t *tim, pwm_param_t *param)
{
        uint16_t period;
        uint16_t prescaler;
        uint32_t tim_n_clk;
    TIM_TimeBaseInitType TimeBase_Config;
    OCInitType TIM_OC_Config;

    /* 开启定时器时钟 */
    if (TIM8 == tim->tim_n || TIM1 == tim->tim_n)
    {
        RCC_EnableAPB2PeriphClk(get_tim_rcc(tim->tim_n), ENABLE);
    }
    else
    {
        RCC_EnableAPB1PeriphClk(get_tim_rcc(tim->tim_n), ENABLE);
    }

    if (param->duty_cycle == 0)
    {
        config_gpio_output(gpio);  /* 设置成推挽输出模式 */
        GPIO_ResetBits(gpio->gpio_port, gpio->gpio_pin);  /* GPIO输出低电平 */
        TIM_Enable(tim->tim_n, tim->enable);  /* 是否要关掉定时器 */
        return;
    }
    else if (param->duty_cycle == 10000)
    {
        config_gpio_output(gpio);  /* 设置成推挽输出模式 */
        GPIO_SetBits(gpio->gpio_port, gpio->gpio_pin);  /* GPIO输出高电平 */
        TIM_Enable(tim->tim_n, tim->enable);  /* 是否要关掉定时器 */
        return;
    }

    if (TIM8 == tim->tim_n || TIM1 == tim->tim_n)
    {
        tim_n_clk = SystemCoreClock;
    }
    else
    {
        tim_n_clk = SystemCoreClock / 2;
    }

    if (param->freq < 100)
    {
        prescaler = 10000 - 1;  /* 分频比 = 10000 */
        period =  (tim_n_clk / 10000) / param->freq  - 1;  /* 自动重装的值 */
    }
    else if (param->freq < 3000)
    {
        prescaler = 100 - 1;  /* 分频比 = 100 */
        period =  (tim_n_clk / 100) / param->freq  - 1;  /* 自动重装的值 */
    }
    else        /* 大于4K的频率,无需分频 */
    {
        prescaler = 0;  /* 分频比 = 1 */
        period = tim_n_clk / param->freq - 1;  /* 自动重装的值 */
    }

    /* 配置PWM输出引脚的GPIO */
    config_gpio_pwm(gpio);

    /* 基本定时器配置 */
    TIM_InitTimBaseStruct(&TimeBase_Config);   
    TimeBase_Config.Period    = period;
    TimeBase_Config.Prescaler = prescaler;
    TimeBase_Config.ClkDiv    = 0;
    TimeBase_Config.CntMode   = TIM_CNT_MODE_UP;
    TIM_InitTimeBase(tim->tim_n, &TimeBase_Config);

    /* 定时器OC配置 */
    TIM_InitOcStruct(&TIM_OC_Config);   
    TIM_OC_Config.OcMode       = TIM_OCMODE_PWM1;
    TIM_OC_Config.OutputState  = TIM_OUTPUT_STATE_ENABLE;
    TIM_OC_Config.OutputNState = TIM_OUTPUT_NSTATE_DISABLE;
    TIM_OC_Config.Pulse        = (param->duty_cycle * period) / 10000;;
    TIM_OC_Config.OcPolarity   = TIM_OC_POLARITY_HIGH;
    TIM_OC_Config.OcNPolarity  = TIM_OCN_POLARITY_HIGH;
    TIM_OC_Config.OcIdleState  = TIM_OC_IDLE_STATE_RESET;
    TIM_OC_Config.OcNIdleState = TIM_OCN_IDLE_STATE_RESET;

    /* 设置比较器的值 */
    if (TIM_CH_01 == tim->tim_ch)
    {
        TIM_InitOc1(tim->tim_n, &TIM_OC_Config);
        TIM_ConfigOc1Preload(tim->tim_n, TIM_OC_PRE_LOAD_ENABLE);
    }
    else if (TIM_CH_02 == tim->tim_ch)
    {
        TIM_InitOc2(tim->tim_n, &TIM_OC_Config);
        TIM_ConfigOc2Preload(tim->tim_n, TIM_OC_PRE_LOAD_ENABLE);
    }
    else if (TIM_CH_03 == tim->tim_ch)
    {
        TIM_InitOc3(tim->tim_n, &TIM_OC_Config);
        TIM_ConfigOc3Preload(tim->tim_n, TIM_OC_PRE_LOAD_ENABLE);
    }
    else if (TIM_CH_04 == tim->tim_ch)
    {
        TIM_InitOc4(tim->tim_n, &TIM_OC_Config);
        TIM_ConfigOc4Preload(tim->tim_n, TIM_OC_PRE_LOAD_ENABLE);
    }

    /* 开启自动重装载 */
    TIM_ConfigArPreload(tim->tim_n, ENABLE);

    TIM_EnableCtrlPwmOutputs(tim->tim_n, ENABLE);

    /* 是否要开启定时器 */
    TIM_Enable(tim->tim_n, tim->enable);  
}

/***************************************************************************************************
* @fn      bsp_pwm_output_n
*
* @brief   pwm输出 反相(N相)
*
* @param   gpio GPIO配置信息
* @param   tim 定时器配置信息
* @param   param pwm输出参数
*
* @return  无
*/
void bsp_pwm_output_n(pwm_gpio_t *gpio, pwm_tim_t *tim, pwm_param_t *param)
{
        uint16_t period;
        uint16_t prescaler;
        uint32_t tim_n_clk;
    TIM_TimeBaseInitType TimeBase_Config;
    OCInitType TIM_OC_Config;

    /* 开启定时器时钟 */
    if (TIM8 == tim->tim_n || TIM1 == tim->tim_n)
    {
        RCC_EnableAPB2PeriphClk(get_tim_rcc(tim->tim_n), ENABLE);
    }
    else
    {
        RCC_EnableAPB1PeriphClk(get_tim_rcc(tim->tim_n), ENABLE);
    }

    if (param->duty_cycle == 0)
    {
        config_gpio_output(gpio);  /* 设置成推挽输出模式 */
        GPIO_ResetBits(gpio->gpio_port, gpio->gpio_pin);  /* GPIO输出低电平 */
        TIM_Enable(tim->tim_n, tim->enable);  /* 是否要关掉定时器 */
        return;
    }
    else if (param->duty_cycle == 10000)
    {
        config_gpio_output(gpio);  /* 设置成推挽输出模式 */
        GPIO_SetBits(gpio->gpio_port, gpio->gpio_pin);  /* GPIO输出高电平 */
        TIM_Enable(tim->tim_n, tim->enable);  /* 是否要关掉定时器 */
        return;
    }
   if (TIM8 == tim->tim_n || TIM1 == tim->tim_n)
    {
        tim_n_clk = SystemCoreClock;
    }
    else
    {
        tim_n_clk = SystemCoreClock / 2;
    }

    if (param->freq < 100)
    {
        prescaler = 10000 - 1;  /* 分频比 = 10000 */
        period =  (tim_n_clk / 10000) / param->freq  - 1;  /* 自动重装的值 */
    }
    else if (param->freq < 3000)
    {
        prescaler = 100 - 1;  /* 分频比 = 100 */
        period =  (tim_n_clk / 100) / param->freq  - 1;  /* 自动重装的值 */
    }
    else        /* 大于4K的频率,无需分频 */
    {
        prescaler = 0;  /* 分频比 = 1 */
        period = tim_n_clk / param->freq - 1;  /* 自动重装的值 */
    }

    /* 配置PWM输出引脚的GPIO */
    config_gpio_pwm(gpio);

    /* 基本定时器配置 */
    TIM_InitTimBaseStruct(&TimeBase_Config);   
    TimeBase_Config.Period    = period;
    TimeBase_Config.Prescaler = prescaler;
    TimeBase_Config.ClkDiv    = 0;
    TimeBase_Config.CntMode   = TIM_CNT_MODE_UP;
    TIM_InitTimeBase(tim->tim_n, &TimeBase_Config);

    /* 定时器OC配置 */
    TIM_InitOcStruct(&TIM_OC_Config);   
    TIM_OC_Config.OcMode       = TIM_OCMODE_PWM1;
    TIM_OC_Config.OutputState  = TIM_OUTPUT_STATE_DISABLE;
    TIM_OC_Config.OutputNState = TIM_OUTPUT_NSTATE_ENABLE;
    TIM_OC_Config.Pulse        = (param->duty_cycle * period) / 10000;;
    TIM_OC_Config.OcPolarity   = TIM_OC_POLARITY_HIGH;
    TIM_OC_Config.OcNPolarity  = TIM_OCN_POLARITY_HIGH;
    TIM_OC_Config.OcIdleState  = TIM_OC_IDLE_STATE_RESET;
    TIM_OC_Config.OcNIdleState = TIM_OCN_IDLE_STATE_RESET;

    /* 设置比较器的值 */
    if (TIM_CH_01 == tim->tim_ch)
    {
        TIM_InitOc1(tim->tim_n, &TIM_OC_Config);
        TIM_ConfigOc1Preload(tim->tim_n, TIM_OC_PRE_LOAD_ENABLE);
    }
    else if (TIM_CH_02 == tim->tim_ch)
    {
        TIM_InitOc2(tim->tim_n, &TIM_OC_Config);
        TIM_ConfigOc2Preload(tim->tim_n, TIM_OC_PRE_LOAD_ENABLE);
    }
    else if (TIM_CH_03 == tim->tim_ch)
    {
        TIM_InitOc3(tim->tim_n, &TIM_OC_Config);
        TIM_ConfigOc3Preload(tim->tim_n, TIM_OC_PRE_LOAD_ENABLE);
    }
    else if (TIM_CH_04 == tim->tim_ch)
    {
        TIM_InitOc4(tim->tim_n, &TIM_OC_Config);
        TIM_ConfigOc4Preload(tim->tim_n, TIM_OC_PRE_LOAD_ENABLE);
    }

    /* 开启自动重装载 */
    TIM_ConfigArPreload(tim->tim_n, ENABLE);

    TIM_EnableCtrlPwmOutputs(tim->tim_n, ENABLE);

    /* 是否要开启定时器 */
    TIM_Enable(tim->tim_n, tim->enable);  
}

/***************************************************************************************************
* @fn      bsp_pwm_output_init
*
* @brief   pwm输出初始化配置
*
* @param   无
*
* @return  无
*/
void bsp_pwm_output_init(void)
{
    pwm_param_t param;
    pwm_tim_t   tim;
    pwm_gpio_t  gpio;

    /* 频率:2K Hz,占空比:50% */
    param.freq       = 5000;
    param.duty_cycle = 8000;

    /* TIM5_CH_1 PA0 */
    tim.tim_n      = TIM5;  
    tim.enable     = ENABLE;
    tim.tim_ch     = TIM_CH_01;
    gpio.gpio_port = GPIOA;
    gpio.gpio_pin  = GPIO_PIN_0;
    gpio.gpio_af   = GPIO_TIM5_AF_CH_1;
    bsp_pwm_output(&gpio, &tim, &param);

    /* TIM5_CH_2 PA1 */
    tim.tim_n      = TIM5;  
    tim.tim_ch     = TIM_CH_02;
    gpio.gpio_port = GPIOA;
    gpio.gpio_pin  = GPIO_PIN_1;
    gpio.gpio_af   = GPIO_TIM5_AF_CH_2;
    bsp_pwm_output(&gpio, &tim, &param);

    /* TIM5_CH_3 PA2 */
    tim.tim_n      = TIM5;  
    tim.tim_ch     = TIM_CH_03;
    gpio.gpio_port = GPIOA;
    gpio.gpio_pin  = GPIO_PIN_2;
    gpio.gpio_af   = GPIO_TIM5_AF_CH_3;
    bsp_pwm_output(&gpio, &tim, &param);


//    tim.tim_n      = TIM3;  
//    tim.tim_ch     = TIM_CH_02;
//    gpio.gpio_port = GPIOB;
//    gpio.gpio_pin  = GPIO_PIN_5;
//    gpio.gpio_af   = GPIO_TIM3_AF_CH_2_02;
//    bsp_pwm_output(&gpio, &tim, &param);

    tim.tim_n      = TIM1;  
    tim.tim_ch     = TIM_CH_02;
    gpio.gpio_port = GPIOB;
    gpio.gpio_pin  = GPIO_PIN_6;
    gpio.gpio_af   = GPIO_TIM1_AF_CHN_2_03;
    bsp_pwm_output_n(&gpio, &tim, &param);
}

————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/qq_35698711/article/details/149133246

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

70

主题

213

帖子

0

粉丝