基于国民技术N32L40xx的PWM输出
完整代码如下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端口地址编号
*
* @returnGPIO的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_tgpio;
/* 频率: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, ¶m);
/* 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, ¶m);
/* 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, ¶m);
// 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, ¶m);
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, ¶m);
}
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/qq_35698711/article/details/149133246
页:
[1]