SN_PWM.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573
  1. #include "SN_PWM.h"
  2. /*
  3. 文件名:SN_PWM.c/.h
  4. 作者: SN_FAE_黄泽洪
  5. 免责声明:无版权,可随意传播和篡改,该代码仅供开发参考,如需使用请自行验证
  6. 本人不担负商业使用上带来的风险。
  7. */
  8. /* SN_PWM_TIM3_OUT_init模块的使用方法:
  9. 方法一:初始定时器3的pwm输出:
  10. int main(void){
  11. SN_SYSCLK_set(SYSCLK_48MHZ);
  12. std_delay_init();
  13. SN_PWM_TIM3_OUT_init(TIM3_CH1_PA0|TIM3_CH2_PA4 ,1000); //设置定时器3通道1 和 通道2 输出占空比数是1000的方波,输出io分别是PA0 ,PA4
  14. while(1){
  15. std_delayms(500);
  16. SN_PWM_TIMx_CH_Duty(TIM3,TIM_CHANNEL_1,3000); //调整通道1 输出的占空比大小
  17. }
  18. }
  19. 方法二:初始定时器1的pwm输出:
  20. int main(void){
  21. SN_SYSCLK_set(SYSCLK_48MHZ);
  22. std_delay_init();
  23. SN_PWM_TIM1_OUT_init(TIM1_CH1_PA0|TIM1_CH2_PA1 ,1000); //设置定时器3通道1 和 通道2 输出占空比数是1000的方波,输出io分别是PA0 ,PA4
  24. while(1){
  25. std_delayms(500);
  26. SN_PWM_TIMx_CH_Duty(TIM1,TIM_CHANNEL_1,3000); //调整通道1 输出的占空比大小
  27. }
  28. }
  29. 方法三: 初始定时器1 的互补PWM输出
  30. //注意:相关死区时间和空闲电平要在SN_PWM.h 文件中设定
  31. main.c文件:
  32. uint16_t EN = 0 ; //仿真中修改该变量,控制PWM输出或关闭
  33. uint32_t DUT = 1;
  34. int main(void){
  35. SN_SYSCLK_set(SYSCLK_48MHZ);
  36. std_delay_init();
  37. SN_PWM_TIM1_OUT_Complementary(TIM1_CH2N_PA0); //设置互补通道,注意要先设定互补通道后,才能初始化pwm输出
  38. SN_PWM_TIM1_OUT_init(TIM1_CH2_PA1,1000); //设置定时器3通道1 和 通道2 输出占空比数是1000的方波,输出io分别是PA0 ,PA4
  39. while(1){
  40. std_delayms(500);
  41. if(EN){
  42. SN_PWM_TIMx_CH_Duty(TIM1,TIM_CHANNEL_2,100*(DUT++)); //调整通道2 输出的占空比大小
  43. SN_TIM_PWM_Start(TIM1,TIM_CHANNEL_2);
  44. }else{
  45. SN_TIM_PWM_Stop(TIM1,TIM_CHANNEL_2);
  46. }
  47. }
  48. }
  49. */
  50. //全局变量是否开启tim1的pwm互补通道
  51. static uint8_t SN_G_OUTPUT_NEGTIVE = 0;
  52. //TIM3通道和io映射表
  53. const static uint16_t TIM3_CH_list[10] = {
  54. GPIO_PIN_0,
  55. GPIO_PIN_3,
  56. GPIO_PIN_4,
  57. GPIO_PIN_5,
  58. GPIO_PIN_6,
  59. GPIO_PIN_7,
  60. GPIO_PIN_0,
  61. GPIO_PIN_4,
  62. GPIO_PIN_5
  63. };
  64. /*
  65. 函数名称:SN_PWM_TIM3_OUT_init()
  66. 功能: 初始化PWM多通道输出
  67. @参数:通道编码 :
  68. @TIM3_CH1_PA0
  69. @TIM3_CH3_PA3
  70. @TIM3_CH2_PA4
  71. @TIM3_CH1_PA5
  72. @TIM3_CH3_PA6
  73. @TIM3_CH2_PA7
  74. @TIM3_CH1_PB0
  75. @TIM3_CH4_PB4
  76. @TIM3_CH3_PB5
  77. @TIM3_CH1_x|TIM3_CH1_y|TIM3_CH1_z
  78. @参数:占空比
  79. 0x0000 - 0xffff
  80. @返回值: 开启的通道
  81. 注意:同时初始化两个相同通道的不同io,最开始初始的那个有效
  82. */
  83. uint8_t SN_PWM_TIM3_OUT_init(uint16_t CHANNEL,uint32_t Duty_value){
  84. //设置IO
  85. uint8_t i ,CH = 0 ;
  86. uint16_t CHANNEL1 = CHANNEL;
  87. std_gpio_init_t tim3_gpio_init = {0};
  88. //前6个是PA ,后面3个是PB,最后一个是PC
  89. if(( CHANNEL & 0X003F )!= 0){std_rcc_gpio_clk_enable(RCC_PERIPH_CLK_GPIOA);}
  90. if(( CHANNEL & 0X01F0 )!= 0){std_rcc_gpio_clk_enable(RCC_PERIPH_CLK_GPIOB);}
  91. tim3_gpio_init.mode = GPIO_MODE_ALTERNATE;
  92. tim3_gpio_init.pull = GPIO_NOPULL;
  93. tim3_gpio_init.alternate = GPIO_AF3_TIM3;
  94. for(i = 0 ; i < 10 ; i++){
  95. if((CHANNEL1 & 0x0001 ) == 1 ){
  96. if(i < 6){
  97. tim3_gpio_init.pin = TIM3_CH_list[i];
  98. std_gpio_init(GPIOA, &tim3_gpio_init);
  99. }else if(i > 6 && i < 9){
  100. tim3_gpio_init.pin = TIM3_CH_list[i];
  101. std_gpio_init(GPIOB, &tim3_gpio_init);
  102. }else{
  103. tim3_gpio_init.pin = TIM3_CH_list[i];
  104. std_gpio_init(GPIOC, &tim3_gpio_init);
  105. }
  106. }
  107. CHANNEL1 >>= 1;
  108. }
  109. //设置定时器3
  110. std_tim_basic_init_t basic_init_struct = {0};
  111. std_tim_output_compare_init_t oc_config_struct = {0};
  112. /* TIM3时钟使能 */
  113. std_rcc_apb1_clk_enable(RCC_PERIPH_CLK_TIM3);
  114. /* 配置TIM3计数器参数 */
  115. basic_init_struct.prescaler = TIM3_PRESCALER_VALUE; //设置定时器的预分频
  116. basic_init_struct.period = TIM3_PERIOD_VALUE; //设置定时器的周期
  117. basic_init_struct.clock_div = TIM3_CLOCK_DTS_DIVx; //设置定时器的分频
  118. std_tim_init(TIM3, &basic_init_struct); //初始化定时器
  119. /* 配置TIM3为工作模式1 */
  120. std_tim_work_mode1_enable(TIM3);
  121. /* 配置通道1输出模式为PWM1模式 */
  122. oc_config_struct.output_compare_mode = TIM_OUTPUT_MODE_PWM1; //使用PWM模式一
  123. oc_config_struct.output_pol = TIM_OUTPUT_POL_HIGH; //设设置PWM输出的有效电平极性
  124. oc_config_struct.pulse = Duty_value; //设置通道1PWM的占空比 默认初始化 0
  125. oc_config_struct.output_state = TIM_OUTPUT_ENABLE; //设能通道
  126. if(( CHANNEL & 0x0049 ) != 0){
  127. std_tim_output_compare_init(TIM3, &oc_config_struct, TIM_CHANNEL_1);
  128. CH |= 0x01;
  129. }
  130. if(( CHANNEL & 0x0024 ) != 0){
  131. std_tim_output_compare_init(TIM3, &oc_config_struct, TIM_CHANNEL_2);
  132. CH |= 0x02;
  133. }
  134. if(( CHANNEL & 0x0112 ) != 0){
  135. std_tim_output_compare_init(TIM3, &oc_config_struct, TIM_CHANNEL_3);
  136. CH |= 0x04;
  137. }
  138. if(( CHANNEL & 0x0080 ) != 0){
  139. std_tim_output_compare_init(TIM3, &oc_config_struct, TIM_CHANNEL_4);
  140. CH |= 0x08;
  141. }
  142. std_tim_enable(TIM3);
  143. return CH;
  144. }
  145. //TIM1通道和io映射表
  146. const static uint16_t TIM1_CH_list[10] = {
  147. GPIO_PIN_0, //PA0 0
  148. GPIO_PIN_1, //PA1 1
  149. GPIO_PIN_1, //PA1 2
  150. GPIO_PIN_5, //PA5 3
  151. GPIO_PIN_0, //PB0 4
  152. GPIO_PIN_1, //PB1 5
  153. GPIO_PIN_2, //PB2 6
  154. GPIO_PIN_2, //PB2 7
  155. GPIO_PIN_7, //PB7 8
  156. GPIO_PIN_1, //PC1 9
  157. };
  158. /*
  159. 函数名称:SN_PWM_TIM1_OUT_init()
  160. 功能: 初始化PWM多通道输出
  161. @参数:通道编码 :
  162. TIM1_CH1_PA0
  163. TIM1_CH2_PA1
  164. TIM1_CH3_PA1
  165. TIM1_CH2_PA5
  166. TIM1_CH2_PB0
  167. TIM1_CH4_PB1
  168. TIM1_CH1_PB2
  169. TIM1_CH3_PB2
  170. TIM1_CH4_PB7
  171. TIM1_CH2_PC1
  172. 支持并集
  173. @参数: 开启的默认占空比(所有的通道pwm占空比一样)
  174. @参数: 是否使能互补PWM通道
  175. @返回值: 开启的通道
  176. 注意:同时初始化两个相同通道的不同io,最开始初始的那个有效
  177. */
  178. uint8_t SN_PWM_TIM1_OUT_init(uint16_t CHANNEL,uint32_t Duty_value){
  179. //设置IO
  180. uint8_t i ,CH = 0 ;
  181. uint16_t CHANNEL1 = CHANNEL;
  182. std_gpio_init_t tim1_gpio_init = {0};
  183. //选择不同的IO时钟
  184. if(( CHANNEL & 0X000F )!= 0){std_rcc_gpio_clk_enable(RCC_PERIPH_CLK_GPIOA);}
  185. if(( CHANNEL & 0X01F0 )!= 0){std_rcc_gpio_clk_enable(RCC_PERIPH_CLK_GPIOB);}
  186. if(( CHANNEL & 0x0200 )!= 0){std_rcc_gpio_clk_enable(RCC_PERIPH_CLK_GPIOC);}
  187. tim1_gpio_init.mode = GPIO_MODE_ALTERNATE;
  188. tim1_gpio_init.pull = GPIO_NOPULL;
  189. for( i = 0; i < 10; i++){
  190. if(CHANNEL1 & 0x0001){
  191. if(i<4){
  192. if(i == 2){tim1_gpio_init.alternate = GPIO_AF4_TIM1;}else{tim1_gpio_init.alternate = GPIO_AF2_TIM1;}
  193. tim1_gpio_init.pin = TIM1_CH_list[i];
  194. std_gpio_init(GPIOA, &tim1_gpio_init);
  195. }else if(i > 3 && i < 9 ){
  196. if(i == 4 || i == 6){tim1_gpio_init.alternate = GPIO_AF2_TIM1;}else{tim1_gpio_init.alternate = GPIO_AF4_TIM1;}
  197. tim1_gpio_init.pin = TIM1_CH_list[i];
  198. std_gpio_init(GPIOB, &tim1_gpio_init);
  199. }else if(i == 9){
  200. tim1_gpio_init.alternate = GPIO_AF2_TIM1;
  201. tim1_gpio_init.pin = TIM1_CH_list[i];
  202. std_gpio_init(GPIOC, &tim1_gpio_init);
  203. }
  204. }
  205. CHANNEL1 >>= 1;
  206. }
  207. //TIM1
  208. std_tim_basic_init_t basic_init = {0};
  209. std_tim_output_compare_init_t output_init = {0};
  210. std_tim_break_init_t break_config = {0};
  211. /* TIM1时钟使能 */
  212. std_rcc_apb2_clk_enable(RCC_PERIPH_CLK_TIM1);
  213. /* 配置TIM1计数器参数 */
  214. basic_init.counter_mode = TIM_COUNTER_MODE_UP;
  215. basic_init.period = TIM1_PERIOD_VALUE;
  216. basic_init.clock_div = TIM1_CLOCK_DTS_DIV1;
  217. basic_init.prescaler = TIM1_PRESCALER_VALUE;
  218. std_tim_init(TIM1, &basic_init);
  219. /* 配置通道1输出模式为PWM1模式 */
  220. output_init.output_compare_mode = TIM_OUTPUT_MODE_PWM_x; //PWM模式
  221. output_init.pulse = Duty_value; //pwm占空比
  222. output_init.output_pol = TIM_OUTPUT_POL_x; //通道输出有效极性
  223. output_init.output_negtive_pol = TIM_OUTPUT_NEGTIVE_POL_x; //互补输出有效极性
  224. output_init.output_idle_state = TIM_OUTPUT_IDLE_x; //通道输出空闲电平
  225. output_init.output_negtive_idle_state = TIM_OUTPUT_NEGTIVE_IDLE_x; //互补通道输出空闲电平
  226. output_init.output_state = TIM_OUTPUT_ENABLE;
  227. if(SN_G_OUTPUT_NEGTIVE){
  228. output_init.output_negtive_state = TIM_OUTPUT_NEGTIVE_ENABLE;
  229. }else{
  230. output_init.output_negtive_state = TIM_OUTPUT_NEGTIVE_DISABLE;
  231. }
  232. if((CHANNEL & 0x0041) != 0){
  233. std_tim_output_compare_init(TIM1, &output_init, TIM_CHANNEL_1);
  234. std_tim_ccxn_channel_enable(TIM1, TIM_CHANNEL_1);
  235. CH |= 0x01;
  236. }
  237. if((CHANNEL & 0x021A) != 0){
  238. std_tim_output_compare_init(TIM1, &output_init, TIM_CHANNEL_2);
  239. std_tim_ccxn_channel_enable(TIM1, TIM_CHANNEL_2);
  240. CH |= 0x02;
  241. }
  242. if((CHANNEL & 0x0084) != 0){
  243. std_tim_output_compare_init(TIM1, &output_init, TIM_CHANNEL_3);
  244. std_tim_ccxn_channel_enable(TIM1, TIM_CHANNEL_3);
  245. CH |= 0x04;
  246. }
  247. if((CHANNEL & 0x0120) != 0){
  248. std_tim_output_compare_init(TIM1, &output_init, TIM_CHANNEL_4);
  249. std_tim_ccxn_channel_enable(TIM1, TIM_CHANNEL_4);
  250. CH |= 0x08;
  251. }
  252. // /* 配置断路输入源为GPIO */
  253. std_tim_brk_source_enable(TIM1, TIM_BREAK_INPUT_SRC_COMP2);
  254. std_tim_set_brk_pol(TIM1, TIM_BREAK_INPUT_SRC_COMP2, TIM_BREAK_INPUT_POL_HIGH);
  255. /* 配置断路输入参数 */
  256. break_config.off_state_run_mode = TIM_OSSR_ENABLE;
  257. break_config.off_state_idle_mode = TIM_OSSI_ENABLE;
  258. break_config.lock_level = TIM_LOCK_LEVEL_OFF;
  259. break_config.dead_time = 0x3F; //死区时间
  260. break_config.break_state = TIM_BREAK_ENABLE ; // TIM_BREAK_ENABLE TIM_BREAK_DISABLE
  261. std_tim_bdt_init(TIM1, &break_config);
  262. std_tim_arrpreload_enable(TIM1); /* 使能自动重加载 */
  263. std_tim_moen_enable(TIM1); /* 使能输出 */
  264. std_tim_onepulse_disable(TIM1); /* 关闭单脉冲输出 */
  265. std_tim_enable(TIM1); /* 使能计数 */
  266. return CH;
  267. }
  268. //TIM1互补通道和io映射表
  269. const static uint16_t TIM1_CHN_list[10] = {
  270. GPIO_PIN_0, //PA0 0
  271. GPIO_PIN_0, //PA0 1
  272. GPIO_PIN_3, //PA3 2
  273. GPIO_PIN_4, //PA4 3
  274. GPIO_PIN_1, //PB1 4
  275. GPIO_PIN_1, //PB1 5
  276. GPIO_PIN_2, //PB2 6
  277. GPIO_PIN_5, //PB2 7
  278. GPIO_PIN_7, //PB7 8
  279. GPIO_PIN_7, //PB7 9
  280. };
  281. /*
  282. 函数名称:SN_PWM_TIM1_OUT_Complementary
  283. 功能: 初始化PWM多通道互补输出
  284. @参数:通道编码 :
  285. TIM1_CH2N_PA0
  286. TIM1_CH3N_PA0
  287. TIM1_CH3N_PA3
  288. TIM1_CH2N_PA4
  289. TIM1_CH1N_PB1
  290. TIM1_CH2N_PB1
  291. TIM1_CH1N_PB2
  292. TIM1_CH3N_PB5
  293. TIM1_CH2N_PB7
  294. TIM1_CH1N_PB7
  295. @返回值: 开启的通道
  296. 注意:同时初始化两个相同通道的不同io,最开始初始的那个有效
  297. */
  298. void SN_PWM_TIM1_OUT_Complementary(uint16_t CHANNEL_N){
  299. uint8_t i ;
  300. uint16_t CHANNEL1 = CHANNEL_N;
  301. std_gpio_init_t gpio_init = {0};
  302. //初始gpio时钟
  303. if( CHANNEL_N & 0x000f ){std_rcc_gpio_clk_enable(RCC_PERIPH_CLK_GPIOA);}
  304. if( CHANNEL_N & 0x03f0 ){std_rcc_gpio_clk_enable(RCC_PERIPH_CLK_GPIOB);}
  305. gpio_init.mode = GPIO_MODE_ALTERNATE;
  306. gpio_init.pull = GPIO_NOPULL;
  307. //设置复用选项
  308. for(i = 0 ; i < 10 ;i++){
  309. if(CHANNEL1 & 0x0001){
  310. if(i<4){
  311. gpio_init.alternate = GPIO_AF2_TIM1;
  312. if(i == 0){gpio_init.alternate = GPIO_AF4_TIM1;}
  313. if(i == 1){gpio_init.alternate = GPIO_AF5_TIM1;}
  314. gpio_init.pin = TIM1_CHN_list[i];
  315. std_gpio_init(GPIOA, &gpio_init);
  316. }else if(i > 3 && i < 10 ){
  317. if(i == 5 || i == 6 || i == 9){gpio_init.alternate = GPIO_AF3_TIM1;}else{gpio_init.alternate = GPIO_AF2_TIM1;}
  318. gpio_init.pin = TIM1_CHN_list[i];
  319. std_gpio_init(GPIOB, &gpio_init);
  320. }
  321. }
  322. CHANNEL1 >>= 1;
  323. }
  324. SN_G_OUTPUT_NEGTIVE = 1;
  325. }
  326. /*
  327. 函数名称:TIM1_PWM_Start
  328. 功能:开启tim的PWM输出
  329. 参数:定时器 @TIM1
  330. @TIM3
  331. 参数:通道名称
  332. @TIM_CHANNEL_1
  333. @TIM_CHANNEL_2
  334. @TIM_CHANNEL_3
  335. @TIM_CHANNEL_4
  336. 返回值:无
  337. */
  338. void SN_TIM_PWM_Start(TIM_t *timx ,uint8_t TIM_CHANNEL_x){
  339. std_tim_ccx_channel_enable(timx, TIM_CHANNEL_x);
  340. if(timx == TIM1)std_tim_ccxn_channel_enable(TIM1, TIM_CHANNEL_x);
  341. std_tim_enable(timx);
  342. }
  343. /*
  344. 函数名称:TIM1_PWM_Start
  345. 功能:关闭tim的PWM输出
  346. 参数:定时器 @TIM1
  347. @TIM3
  348. 参数:通道名称
  349. @TIM_CHANNEL_1
  350. @TIM_CHANNEL_2
  351. @TIM_CHANNEL_3
  352. @TIM_CHANNEL_4
  353. 返回值:无
  354. */
  355. void SN_TIM_PWM_Stop(TIM_t *timx,uint8_t TIM_CHANNEL_x){
  356. std_tim_ccx_channel_disable(timx, TIM_CHANNEL_x);
  357. if(timx == TIM1)std_tim_ccxn_channel_disable(TIM1, TIM_CHANNEL_x);
  358. std_tim_disable(timx);
  359. }
  360. /*
  361. 函数名称:SN_PWM_TIMx_CH_Duty()
  362. 功能: 设置单通道占空比
  363. @参数: 定时器
  364. @参数: 设置通道号
  365. @TIM_CHANNEL_1
  366. @TIM_CHANNEL_2
  367. @TIM_CHANNEL_3
  368. @TIM_CHANNEL_4
  369. @参数: 占空比数
  370. 0x0000 - 0xffff
  371. @返回值: 无
  372. */
  373. void SN_PWM_TIMx_CH_Duty(TIM_t *timx,uint32_t TIM_CHANNEL_x ,uint32_t Duty_value){
  374. std_tim_set_ccx_value(timx, TIM_CHANNEL_x , Duty_value);
  375. }
  376. /*
  377. 函数名称:SN_PWM_TIM3_CH_mode(uint8_t mod)
  378. 功能: 设置定时器3,PWM精度,和通道数量
  379. @参数:
  380. @TIM3_CH_MOD_16BIT_CH1_2
  381. @TIM3_CH_MOD_8BIT_CH1_1_2_3_4
  382. 0:工作模式 0,2 通道输入,2 通道输出模式,精度为 16bit
  383. 默认:1:工作模式 1,2 通道输入,4 通道输出模式,精度为 8bit
  384. @返回值: 无
  385. */
  386. void SN_PWM_TIM3_CH_mode(uint8_t mod){
  387. if(mod){
  388. std_tim_work_mode1_enable(TIM3);
  389. }else{
  390. std_tim_work_mode1_disable(TIM3);
  391. }
  392. }