#include "SN_PWM.h" /* 文件名:SN_PWM.c/.h 作者: SN_FAE_黄泽洪 免责声明:无版权,可随意传播和篡改,该代码仅供开发参考,如需使用请自行验证 本人不担负商业使用上带来的风险。 */ /* SN_PWM_TIM3_OUT_init模块的使用方法: 方法一:初始定时器3的pwm输出: int main(void){ SN_SYSCLK_set(SYSCLK_48MHZ); std_delay_init(); SN_PWM_TIM3_OUT_init(TIM3_CH1_PA0|TIM3_CH2_PA4 ,1000); //设置定时器3通道1 和 通道2 输出占空比数是1000的方波,输出io分别是PA0 ,PA4 while(1){ std_delayms(500); SN_PWM_TIMx_CH_Duty(TIM3,TIM_CHANNEL_1,3000); //调整通道1 输出的占空比大小 } } 方法二:初始定时器1的pwm输出: int main(void){ SN_SYSCLK_set(SYSCLK_48MHZ); std_delay_init(); SN_PWM_TIM1_OUT_init(TIM1_CH1_PA0|TIM1_CH2_PA1 ,1000); //设置定时器3通道1 和 通道2 输出占空比数是1000的方波,输出io分别是PA0 ,PA4 while(1){ std_delayms(500); SN_PWM_TIMx_CH_Duty(TIM1,TIM_CHANNEL_1,3000); //调整通道1 输出的占空比大小 } } 方法三: 初始定时器1 的互补PWM输出 //注意:相关死区时间和空闲电平要在SN_PWM.h 文件中设定 main.c文件: uint16_t EN = 0 ; //仿真中修改该变量,控制PWM输出或关闭 uint32_t DUT = 1; int main(void){ SN_SYSCLK_set(SYSCLK_48MHZ); std_delay_init(); SN_PWM_TIM1_OUT_Complementary(TIM1_CH2N_PA0); //设置互补通道,注意要先设定互补通道后,才能初始化pwm输出 SN_PWM_TIM1_OUT_init(TIM1_CH2_PA1,1000); //设置定时器3通道1 和 通道2 输出占空比数是1000的方波,输出io分别是PA0 ,PA4 while(1){ std_delayms(500); if(EN){ SN_PWM_TIMx_CH_Duty(TIM1,TIM_CHANNEL_2,100*(DUT++)); //调整通道2 输出的占空比大小 SN_TIM_PWM_Start(TIM1,TIM_CHANNEL_2); }else{ SN_TIM_PWM_Stop(TIM1,TIM_CHANNEL_2); } } } */ //全局变量是否开启tim1的pwm互补通道 static uint8_t SN_G_OUTPUT_NEGTIVE = 0; //TIM3通道和io映射表 const static uint16_t TIM3_CH_list[10] = { GPIO_PIN_0, GPIO_PIN_3, GPIO_PIN_4, GPIO_PIN_5, GPIO_PIN_6, GPIO_PIN_7, GPIO_PIN_0, GPIO_PIN_4, GPIO_PIN_5 }; /* 函数名称:SN_PWM_TIM3_OUT_init() 功能: 初始化PWM多通道输出 @参数:通道编码 : @TIM3_CH1_PA0 @TIM3_CH3_PA3 @TIM3_CH2_PA4 @TIM3_CH1_PA5 @TIM3_CH3_PA6 @TIM3_CH2_PA7 @TIM3_CH1_PB0 @TIM3_CH4_PB4 @TIM3_CH3_PB5 @TIM3_CH1_x|TIM3_CH1_y|TIM3_CH1_z @参数:占空比 0x0000 - 0xffff @返回值: 开启的通道 注意:同时初始化两个相同通道的不同io,最开始初始的那个有效 */ uint8_t SN_PWM_TIM3_OUT_init(uint16_t CHANNEL,uint32_t Duty_value){ //设置IO uint8_t i ,CH = 0 ; uint16_t CHANNEL1 = CHANNEL; std_gpio_init_t tim3_gpio_init = {0}; //前6个是PA ,后面3个是PB,最后一个是PC if(( CHANNEL & 0X003F )!= 0){std_rcc_gpio_clk_enable(RCC_PERIPH_CLK_GPIOA);} if(( CHANNEL & 0X01F0 )!= 0){std_rcc_gpio_clk_enable(RCC_PERIPH_CLK_GPIOB);} tim3_gpio_init.mode = GPIO_MODE_ALTERNATE; tim3_gpio_init.pull = GPIO_NOPULL; tim3_gpio_init.alternate = GPIO_AF3_TIM3; for(i = 0 ; i < 10 ; i++){ if((CHANNEL1 & 0x0001 ) == 1 ){ if(i < 6){ tim3_gpio_init.pin = TIM3_CH_list[i]; std_gpio_init(GPIOA, &tim3_gpio_init); }else if(i > 6 && i < 9){ tim3_gpio_init.pin = TIM3_CH_list[i]; std_gpio_init(GPIOB, &tim3_gpio_init); }else{ tim3_gpio_init.pin = TIM3_CH_list[i]; std_gpio_init(GPIOC, &tim3_gpio_init); } } CHANNEL1 >>= 1; } //设置定时器3 std_tim_basic_init_t basic_init_struct = {0}; std_tim_output_compare_init_t oc_config_struct = {0}; /* TIM3时钟使能 */ std_rcc_apb1_clk_enable(RCC_PERIPH_CLK_TIM3); /* 配置TIM3计数器参数 */ basic_init_struct.prescaler = TIM3_PRESCALER_VALUE; //设置定时器的预分频 basic_init_struct.period = TIM3_PERIOD_VALUE; //设置定时器的周期 basic_init_struct.clock_div = TIM3_CLOCK_DTS_DIVx; //设置定时器的分频 std_tim_init(TIM3, &basic_init_struct); //初始化定时器 /* 配置TIM3为工作模式1 */ std_tim_work_mode1_enable(TIM3); /* 配置通道1输出模式为PWM1模式 */ oc_config_struct.output_compare_mode = TIM_OUTPUT_MODE_PWM1; //使用PWM模式一 oc_config_struct.output_pol = TIM_OUTPUT_POL_HIGH; //设设置PWM输出的有效电平极性 oc_config_struct.pulse = Duty_value; //设置通道1PWM的占空比 默认初始化 0 oc_config_struct.output_state = TIM_OUTPUT_ENABLE; //设能通道 if(( CHANNEL & 0x0049 ) != 0){ std_tim_output_compare_init(TIM3, &oc_config_struct, TIM_CHANNEL_1); CH |= 0x01; } if(( CHANNEL & 0x0024 ) != 0){ std_tim_output_compare_init(TIM3, &oc_config_struct, TIM_CHANNEL_2); CH |= 0x02; } if(( CHANNEL & 0x0112 ) != 0){ std_tim_output_compare_init(TIM3, &oc_config_struct, TIM_CHANNEL_3); CH |= 0x04; } if(( CHANNEL & 0x0080 ) != 0){ std_tim_output_compare_init(TIM3, &oc_config_struct, TIM_CHANNEL_4); CH |= 0x08; } std_tim_enable(TIM3); return CH; } //TIM1通道和io映射表 const static uint16_t TIM1_CH_list[10] = { GPIO_PIN_0, //PA0 0 GPIO_PIN_1, //PA1 1 GPIO_PIN_1, //PA1 2 GPIO_PIN_5, //PA5 3 GPIO_PIN_0, //PB0 4 GPIO_PIN_1, //PB1 5 GPIO_PIN_2, //PB2 6 GPIO_PIN_2, //PB2 7 GPIO_PIN_7, //PB7 8 GPIO_PIN_1, //PC1 9 }; /* 函数名称:SN_PWM_TIM1_OUT_init() 功能: 初始化PWM多通道输出 @参数:通道编码 : TIM1_CH1_PA0 TIM1_CH2_PA1 TIM1_CH3_PA1 TIM1_CH2_PA5 TIM1_CH2_PB0 TIM1_CH4_PB1 TIM1_CH1_PB2 TIM1_CH3_PB2 TIM1_CH4_PB7 TIM1_CH2_PC1 支持并集 @参数: 开启的默认占空比(所有的通道pwm占空比一样) @参数: 是否使能互补PWM通道 @返回值: 开启的通道 注意:同时初始化两个相同通道的不同io,最开始初始的那个有效 */ uint8_t SN_PWM_TIM1_OUT_init(uint16_t CHANNEL,uint32_t Duty_value){ //设置IO uint8_t i ,CH = 0 ; uint16_t CHANNEL1 = CHANNEL; std_gpio_init_t tim1_gpio_init = {0}; //选择不同的IO时钟 if(( CHANNEL & 0X000F )!= 0){std_rcc_gpio_clk_enable(RCC_PERIPH_CLK_GPIOA);} if(( CHANNEL & 0X01F0 )!= 0){std_rcc_gpio_clk_enable(RCC_PERIPH_CLK_GPIOB);} if(( CHANNEL & 0x0200 )!= 0){std_rcc_gpio_clk_enable(RCC_PERIPH_CLK_GPIOC);} tim1_gpio_init.mode = GPIO_MODE_ALTERNATE; tim1_gpio_init.pull = GPIO_NOPULL; for( i = 0; i < 10; i++){ if(CHANNEL1 & 0x0001){ if(i<4){ if(i == 2){tim1_gpio_init.alternate = GPIO_AF4_TIM1;}else{tim1_gpio_init.alternate = GPIO_AF2_TIM1;} tim1_gpio_init.pin = TIM1_CH_list[i]; std_gpio_init(GPIOA, &tim1_gpio_init); }else if(i > 3 && i < 9 ){ if(i == 4 || i == 6){tim1_gpio_init.alternate = GPIO_AF2_TIM1;}else{tim1_gpio_init.alternate = GPIO_AF4_TIM1;} tim1_gpio_init.pin = TIM1_CH_list[i]; std_gpio_init(GPIOB, &tim1_gpio_init); }else if(i == 9){ tim1_gpio_init.alternate = GPIO_AF2_TIM1; tim1_gpio_init.pin = TIM1_CH_list[i]; std_gpio_init(GPIOC, &tim1_gpio_init); } } CHANNEL1 >>= 1; } //TIM1 std_tim_basic_init_t basic_init = {0}; std_tim_output_compare_init_t output_init = {0}; std_tim_break_init_t break_config = {0}; /* TIM1时钟使能 */ std_rcc_apb2_clk_enable(RCC_PERIPH_CLK_TIM1); /* 配置TIM1计数器参数 */ basic_init.counter_mode = TIM_COUNTER_MODE_UP; basic_init.period = TIM1_PERIOD_VALUE; basic_init.clock_div = TIM1_CLOCK_DTS_DIV1; basic_init.prescaler = TIM1_PRESCALER_VALUE; std_tim_init(TIM1, &basic_init); /* 配置通道1输出模式为PWM1模式 */ output_init.output_compare_mode = TIM_OUTPUT_MODE_PWM_x; //PWM模式 output_init.pulse = Duty_value; //pwm占空比 output_init.output_pol = TIM_OUTPUT_POL_x; //通道输出有效极性 output_init.output_negtive_pol = TIM_OUTPUT_NEGTIVE_POL_x; //互补输出有效极性 output_init.output_idle_state = TIM_OUTPUT_IDLE_x; //通道输出空闲电平 output_init.output_negtive_idle_state = TIM_OUTPUT_NEGTIVE_IDLE_x; //互补通道输出空闲电平 output_init.output_state = TIM_OUTPUT_ENABLE; if(SN_G_OUTPUT_NEGTIVE){ output_init.output_negtive_state = TIM_OUTPUT_NEGTIVE_ENABLE; }else{ output_init.output_negtive_state = TIM_OUTPUT_NEGTIVE_DISABLE; } if((CHANNEL & 0x0041) != 0){ std_tim_output_compare_init(TIM1, &output_init, TIM_CHANNEL_1); std_tim_ccxn_channel_enable(TIM1, TIM_CHANNEL_1); CH |= 0x01; } if((CHANNEL & 0x021A) != 0){ std_tim_output_compare_init(TIM1, &output_init, TIM_CHANNEL_2); std_tim_ccxn_channel_enable(TIM1, TIM_CHANNEL_2); CH |= 0x02; } if((CHANNEL & 0x0084) != 0){ std_tim_output_compare_init(TIM1, &output_init, TIM_CHANNEL_3); std_tim_ccxn_channel_enable(TIM1, TIM_CHANNEL_3); CH |= 0x04; } if((CHANNEL & 0x0120) != 0){ std_tim_output_compare_init(TIM1, &output_init, TIM_CHANNEL_4); std_tim_ccxn_channel_enable(TIM1, TIM_CHANNEL_4); CH |= 0x08; } // /* 配置断路输入源为GPIO */ std_tim_brk_source_enable(TIM1, TIM_BREAK_INPUT_SRC_COMP2); std_tim_set_brk_pol(TIM1, TIM_BREAK_INPUT_SRC_COMP2, TIM_BREAK_INPUT_POL_HIGH); /* 配置断路输入参数 */ break_config.off_state_run_mode = TIM_OSSR_ENABLE; break_config.off_state_idle_mode = TIM_OSSI_ENABLE; break_config.lock_level = TIM_LOCK_LEVEL_OFF; break_config.dead_time = 0x3F; //死区时间 break_config.break_state = TIM_BREAK_ENABLE ; // TIM_BREAK_ENABLE TIM_BREAK_DISABLE std_tim_bdt_init(TIM1, &break_config); std_tim_arrpreload_enable(TIM1); /* 使能自动重加载 */ std_tim_moen_enable(TIM1); /* 使能输出 */ std_tim_onepulse_disable(TIM1); /* 关闭单脉冲输出 */ std_tim_enable(TIM1); /* 使能计数 */ return CH; } //TIM1互补通道和io映射表 const static uint16_t TIM1_CHN_list[10] = { GPIO_PIN_0, //PA0 0 GPIO_PIN_0, //PA0 1 GPIO_PIN_3, //PA3 2 GPIO_PIN_4, //PA4 3 GPIO_PIN_1, //PB1 4 GPIO_PIN_1, //PB1 5 GPIO_PIN_2, //PB2 6 GPIO_PIN_5, //PB2 7 GPIO_PIN_7, //PB7 8 GPIO_PIN_7, //PB7 9 }; /* 函数名称:SN_PWM_TIM1_OUT_Complementary 功能: 初始化PWM多通道互补输出 @参数:通道编码 : TIM1_CH2N_PA0 TIM1_CH3N_PA0 TIM1_CH3N_PA3 TIM1_CH2N_PA4 TIM1_CH1N_PB1 TIM1_CH2N_PB1 TIM1_CH1N_PB2 TIM1_CH3N_PB5 TIM1_CH2N_PB7 TIM1_CH1N_PB7 @返回值: 开启的通道 注意:同时初始化两个相同通道的不同io,最开始初始的那个有效 */ void SN_PWM_TIM1_OUT_Complementary(uint16_t CHANNEL_N){ uint8_t i ; uint16_t CHANNEL1 = CHANNEL_N; std_gpio_init_t gpio_init = {0}; //初始gpio时钟 if( CHANNEL_N & 0x000f ){std_rcc_gpio_clk_enable(RCC_PERIPH_CLK_GPIOA);} if( CHANNEL_N & 0x03f0 ){std_rcc_gpio_clk_enable(RCC_PERIPH_CLK_GPIOB);} gpio_init.mode = GPIO_MODE_ALTERNATE; gpio_init.pull = GPIO_NOPULL; //设置复用选项 for(i = 0 ; i < 10 ;i++){ if(CHANNEL1 & 0x0001){ if(i<4){ gpio_init.alternate = GPIO_AF2_TIM1; if(i == 0){gpio_init.alternate = GPIO_AF4_TIM1;} if(i == 1){gpio_init.alternate = GPIO_AF5_TIM1;} gpio_init.pin = TIM1_CHN_list[i]; std_gpio_init(GPIOA, &gpio_init); }else if(i > 3 && i < 10 ){ if(i == 5 || i == 6 || i == 9){gpio_init.alternate = GPIO_AF3_TIM1;}else{gpio_init.alternate = GPIO_AF2_TIM1;} gpio_init.pin = TIM1_CHN_list[i]; std_gpio_init(GPIOB, &gpio_init); } } CHANNEL1 >>= 1; } SN_G_OUTPUT_NEGTIVE = 1; } /* 函数名称:TIM1_PWM_Start 功能:开启tim的PWM输出 参数:定时器 @TIM1 @TIM3 参数:通道名称 @TIM_CHANNEL_1 @TIM_CHANNEL_2 @TIM_CHANNEL_3 @TIM_CHANNEL_4 返回值:无 */ void SN_TIM_PWM_Start(TIM_t *timx ,uint8_t TIM_CHANNEL_x){ std_tim_ccx_channel_enable(timx, TIM_CHANNEL_x); if(timx == TIM1)std_tim_ccxn_channel_enable(TIM1, TIM_CHANNEL_x); std_tim_enable(timx); } /* 函数名称:TIM1_PWM_Start 功能:关闭tim的PWM输出 参数:定时器 @TIM1 @TIM3 参数:通道名称 @TIM_CHANNEL_1 @TIM_CHANNEL_2 @TIM_CHANNEL_3 @TIM_CHANNEL_4 返回值:无 */ void SN_TIM_PWM_Stop(TIM_t *timx,uint8_t TIM_CHANNEL_x){ std_tim_ccx_channel_disable(timx, TIM_CHANNEL_x); if(timx == TIM1)std_tim_ccxn_channel_disable(TIM1, TIM_CHANNEL_x); std_tim_disable(timx); } /* 函数名称:SN_PWM_TIMx_CH_Duty() 功能: 设置单通道占空比 @参数: 定时器 @参数: 设置通道号 @TIM_CHANNEL_1 @TIM_CHANNEL_2 @TIM_CHANNEL_3 @TIM_CHANNEL_4 @参数: 占空比数 0x0000 - 0xffff @返回值: 无 */ void SN_PWM_TIMx_CH_Duty(TIM_t *timx,uint32_t TIM_CHANNEL_x ,uint32_t Duty_value){ std_tim_set_ccx_value(timx, TIM_CHANNEL_x , Duty_value); } /* 函数名称:SN_PWM_TIM3_CH_mode(uint8_t mod) 功能: 设置定时器3,PWM精度,和通道数量 @参数: @TIM3_CH_MOD_16BIT_CH1_2 @TIM3_CH_MOD_8BIT_CH1_1_2_3_4 0:工作模式 0,2 通道输入,2 通道输出模式,精度为 16bit 默认:1:工作模式 1,2 通道输入,4 通道输出模式,精度为 8bit @返回值: 无 */ void SN_PWM_TIM3_CH_mode(uint8_t mod){ if(mod){ std_tim_work_mode1_enable(TIM3); }else{ std_tim_work_mode1_disable(TIM3); } }