hw_pwm.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623
  1. #include "global.h"
  2. #include "hw_pwm.h"
  3. typedef struct
  4. {
  5. TIM_TypeDef *base; //对象实体
  6. int unit_in_hz; //1秒多少hz
  7. uint16_t ch; //通道选择
  8. uint16_t irqn; //中断源
  9. } hw_pwm_t;
  10. typedef struct
  11. {
  12. GPIO_TypeDef *pulse_port; //端口
  13. uint16_t pulse_pin; //引脚
  14. uint32_t remap; //复用功能位置
  15. GPIO_TypeDef *dir_port; //方向功能端口
  16. uint16_t dir_pin; //方向功能引脚
  17. //unsigned short dir_level; //有效电平 0时,表示高电平是正方向,低电平是反方向,1时表示高电平是反方向,低电平是正方向
  18. GPIO_TypeDef *en_port; //使能功能端口
  19. uint16_t en_pin; //使能功能引脚
  20. GPIO_TypeDef *alr_port; //报警功能端口
  21. uint16_t alr_pin; //报警功能引脚
  22. GPIO_TypeDef *clr_port; //报警清除功能端口
  23. uint16_t clr_pin; //报警清除功能引脚
  24. GPIO_TypeDef *tmode_port; //模式切换端口
  25. uint16_t tmode_pin; //模式切换引脚
  26. GPIO_TypeDef *tarr_port; //转矩达到端口
  27. uint16_t tarr_pin; //转矩达到引脚
  28. } hw_pwm_pin_t;
  29. static hw_pwm_pin_t pin_maps[HW_PWM_NUMBER] = {
  30. { GPIOC, 9, GPIO_FullRemap_TIM3, GPIOA, 8, GPIOA, 8,0,0,0,0,0,0,0,0 },
  31. { GPIOA, 8, 0, GPIOC, 9, GPIOC, 9,0,0,0,0,0,0,0,0 } //1
  32. };
  33. /* PWM分布
  34. GPIO_Remap_TIM4
  35. TIM4_CH1 PB6 PD12
  36. TIM4_CH2 PB7 PD13
  37. TIM4_CH3 PB8 PD14
  38. TIM4_CH4 PB9 PD15
  39. -------------------------------------
  40. GPIO_PartialRemap_TIM3 GPIO_FullRemap_TIM3
  41. TIM3_CH1 PA6 PB4 PC6
  42. TIM3_CH2 PA7 PB5 PC7
  43. TIM3_CH3 PB0 PB0 PC8
  44. TIM3_CH4 PB1 PB1 PC9
  45. -------------------------------------
  46. GPIO_PartialRemap1_TIM2 GPIO_PartialRemap2_TIM2 GPIO_FullRemap_TIM2
  47. TIM2_CH1 PA0 PA15 PA0 PA15
  48. TIM2_CH2 PA1 PB3 PA1 PB3
  49. TIM2_CH3 PA2 PA2 PC8 PC8
  50. TIM2_CH4 PA3 PA3 PC9 PC9
  51. -------------------------------------
  52. GPIO_FullRemap_TIM1
  53. TIM1_CH1 PA8 PE9
  54. TIM1_CH2 PA9 PE11
  55. TIM1_CH3 PA10 PE13
  56. TIM1_CH4 PA11 PE14
  57. -------------------------------------
  58. */
  59. static hw_pwm_t hw_pwm_maps[HW_PWM_NUMBER] = {
  60. { TIM3, 4000000, 4, TIM3_IRQn }, //TIM3_CH4 GPIOC_9
  61. { TIM1, 4000000, 1, TIM1_UP_IRQn } //TIM1_CH1 GPIOA_8
  62. };
  63. //周期寄存器表
  64. uint16_t *hw_pwm_period_registers[HW_PWM_NUMBER];
  65. //占空比寄存器表
  66. uint16_t *hw_pwm_dutycycle_registers[HW_PWM_NUMBER];
  67. //配置寄存器表
  68. uint16_t *hw_pwm_cr_registers[HW_PWM_NUMBER];
  69. //配置寄存器表
  70. uint16_t *hw_pwm_egr_registers[HW_PWM_NUMBER];
  71. //方向管脚读写表
  72. hw_pin_readwrite_t hw_pwm_dir_rw_map[HW_PWM_NUMBER];
  73. //使能管脚读写表
  74. hw_pin_readwrite_t hw_pwm_en_rw_map[HW_PWM_NUMBER];
  75. //回调函数,需要使用PWM前进行注册
  76. static pwm_handle pwm_handle_maps[HW_PWM_NUMBER];
  77. //回调参数
  78. static void *pwm_hanlde_parames[HW_PWM_NUMBER];
  79. //Y轴
  80. void TIM1_UP_IRQHandler(void)
  81. {
  82. if (TIM1->SR & (1 << 0)) {
  83. TIM1->SR &= ~(1 << 0);
  84. pwm_handle_maps[HW_PWM_2](pwm_hanlde_parames[HW_PWM_2]);
  85. }
  86. }
  87. //X轴
  88. void TIM3_IRQHandler(void)
  89. {
  90. if (TIM3->SR & (1 << 0))
  91. {
  92. TIM3->SR &= ~(1 << 0);
  93. pwm_handle_maps[HW_PWM_1](pwm_hanlde_parames[HW_PWM_1]);
  94. }
  95. }
  96. /**
  97. * 默认指针函数
  98. *
  99. * @author LXZ (121919)
  100. *
  101. * @param handler
  102. */
  103. void hw_pwm_default_handler(void *handler) {
  104. }
  105. /**
  106. * 设置方向
  107. *
  108. * @author lxz
  109. *
  110. * @param no
  111. * @param dir
  112. */
  113. void hw_pwm_set_dir(unsigned char no, int dir) {
  114. hw_pwm_pin_t *pwm_pin = &pin_maps[no];
  115. unsigned char DIR_TYPE;//类型
  116. unsigned char DIR_CH;//通道
  117. if(no==0)//X轴
  118. {
  119. DIR_TYPE=SET_XDIR_TYPE;
  120. DIR_CH=SET_XDIR_CH;
  121. }
  122. else if(no==1)//Y轴
  123. {
  124. DIR_TYPE=SET_YDIR_TYPE;
  125. DIR_CH=SET_YDIR_CH;
  126. }
  127. switch(DIR_TYPE)
  128. {
  129. //脉冲输出类型
  130. case PULSE_OUTPUT_TYPE:
  131. if (pwm_pin->dir_port != (void *)0) {
  132. if (dir) {
  133. pwm_pin->dir_port->BSRR = 1 << (pwm_pin->dir_pin + 16);
  134. } else {
  135. pwm_pin->dir_port->BSRR = 1 << (pwm_pin->dir_pin);
  136. }
  137. }
  138. break;
  139. //Y输出类型
  140. case Y_OUTPUT_TYPE:
  141. switch(DIR_CH)
  142. {
  143. case 0:
  144. if(dir) {Y00=1; M0304=1;}else {Y00=0; M0304=0;}break;
  145. case 1:
  146. if(dir) {Y01=1; M0305=1;}else {Y01=0; M0305=0;}break;
  147. case 2:
  148. if(dir) {Y02=1; M0306=1;}else {Y02=0; M0306=0;}break;
  149. case 3:
  150. if(dir) {Y03=1; M0307=1;}else {Y03=0; M0307=0;}break;
  151. case 4:
  152. if(dir) {Y04=1; M0308=1;}else {Y04=0; M0308=0;}break;
  153. case 5:
  154. if(dir) {Y05=1; M0309=1;}else {Y05=0; M0309=0;}break;
  155. case 6:
  156. if(dir) {Y06=1; M0310=1;}else {Y06=0; M0310=0;}break;
  157. case 7:
  158. if(dir) {Y07=1; M0311=1;}else {Y07=0; M0311=0;}break;
  159. case 10:
  160. if(dir) {Y10=1; M0312=1;}else {Y10=0; M0312=0;}break;
  161. case 11:
  162. if(dir) {Y11=1; M0313=1;}else {Y11=0; M0313=0;}break;
  163. case 12:
  164. if(dir) {Y12=1; M0314=1;}else {Y12=0; M0314=0;}break;
  165. case 13:
  166. if(dir) {Y13=1; M0315=1;}else {Y13=0; M0315=0;}break;
  167. case 14:
  168. if(dir) {Y14=1; M0316=1;}else {Y14=0; M0316=0;}break;
  169. case 15:
  170. if(dir) {Y15=1; M0317=1;}else {Y15=0; M0317=0;}break;
  171. case 16:
  172. if(dir) {Y16=1; M0318=1;}else {Y16=0; M0318=0;}break;
  173. case 17:
  174. if(dir) {Y17=1; M0319=1;}else {Y17=0; M0319=0;}break;
  175. case 20:
  176. if(dir) {Y20=1; M0320=1;}else {Y20=0; M0320=0;}break;
  177. case 21:
  178. if(dir) {Y21=1; M0321=1;}else {Y21=0; M0321=0;}break;
  179. case 22:
  180. if(dir) {Y22=1; M0322=1;}else {Y22=0; M0322=0;}break;
  181. case 23:
  182. if(dir) {Y23=1; M0323=1;}else {Y23=0; M0323=0;}break;
  183. case 24:
  184. if(dir) {Y24=1; M0324=1;}else {Y24=0; M0324=0;}break;
  185. case 25:
  186. if(dir) {Y25=1; M0325=1;}else {Y25=0; M0325=0;}break;
  187. case 26:
  188. if(dir) {Y26=1; M0326=1;}else {Y26=0; M0326=0;}break;
  189. default:
  190. break;
  191. }
  192. break;
  193. //不使用方向
  194. case NO_USE_TYPE:
  195. break;
  196. default:
  197. break;
  198. }
  199. }
  200. /**
  201. * 获取方向
  202. *
  203. * @author lxz
  204. *
  205. * @param no
  206. *
  207. * @return int
  208. */
  209. int hw_pwm_get_dir(unsigned char no) {
  210. hw_pwm_pin_t *pwm_pin = &pin_maps[no];
  211. if (pwm_pin->dir_port != (void *)0) {
  212. return (pwm_pin->dir_port->IDR >> pwm_pin->dir_pin) & (0x01) == 0x01;
  213. }
  214. return 0;
  215. }
  216. /**
  217. * 设置使能状态
  218. *
  219. * @author lxz
  220. *
  221. * @param no
  222. * @param dir
  223. */
  224. void hw_pwm_set_enable(unsigned char no, int en) {
  225. hw_pwm_pin_t *pwm_pin = &pin_maps[no];
  226. if (pwm_pin->en_port != (void *)0) {
  227. if (en) {
  228. pwm_pin->en_port->BSRR = 1 << (pwm_pin->en_pin + 16);
  229. } else {
  230. pwm_pin->en_port->BSRR = 1 << pwm_pin->en_pin;
  231. }
  232. }
  233. }
  234. /**
  235. * 获取使能状态
  236. *
  237. * @author lxz
  238. *
  239. * @param no
  240. *
  241. * @return int
  242. */
  243. int hw_pwm_get_enable(unsigned char no) {
  244. hw_pwm_pin_t *pwm_pin = &pin_maps[no];
  245. if (pwm_pin->en_port != (void *)0) {
  246. return (pwm_pin->en_port->IDR >> pwm_pin->en_pin) & (0x01);
  247. }
  248. return 0;
  249. }
  250. /**
  251. * 获取报警状态
  252. *
  253. * @author lxz
  254. *
  255. * @param no
  256. *
  257. * @return int
  258. */
  259. int hw_pwm_get_alr(unsigned char no) {
  260. hw_pwm_pin_t *pwm_pin = &pin_maps[no];
  261. if (pwm_pin->alr_port != (void *)0) {
  262. return (pwm_pin->alr_port->IDR >> pwm_pin->alr_pin) & (0x01)==0x01;
  263. }
  264. return 0;
  265. }
  266. /**
  267. * 设置报警清除
  268. *
  269. * @author lxz
  270. *
  271. * @param no
  272. * @param dir
  273. */
  274. void hw_pwm_set_clr(unsigned char no, int en) {
  275. hw_pwm_pin_t *pwm_pin = &pin_maps[no];
  276. if (pwm_pin->clr_port != (void *)0) {
  277. if (en) {
  278. pwm_pin->clr_port->BSRR = 1 << (pwm_pin->clr_pin + 16);
  279. }
  280. else {
  281. pwm_pin->clr_port->BSRR = 1 << pwm_pin->clr_pin;
  282. }
  283. }
  284. }
  285. /**
  286. * 获取脉冲的频率
  287. *
  288. * @author lxz
  289. *
  290. * @param no
  291. *
  292. * @return int
  293. */
  294. int hw_pwm_get_clk(unsigned char no) {
  295. return hw_pwm_maps[no].unit_in_hz;
  296. }
  297. /**
  298. * 启动pwm
  299. *
  300. * @author lxz (2019/5/20/周一)
  301. *
  302. * @param no
  303. */
  304. void hw_pwm_start(unsigned char no) {
  305. HW_PWM_ON(no);
  306. }
  307. /**
  308. * 停止PWM
  309. *
  310. * @author lxz (2019/5/20/周一)
  311. *
  312. * @param no
  313. */
  314. void hw_pwm_stop(unsigned char no) {
  315. HW_PWM_OFF(no);
  316. }
  317. /**
  318. * 设置PWM的周期
  319. *
  320. * @author lxz
  321. *
  322. * @param no
  323. * @param value
  324. */
  325. void hw_pwm_set_period(unsigned char no, int value) {
  326. HW_PWM_PERIOD(no) = value;
  327. HW_PWM_DUTYCYCLE(no) = value >> 1;
  328. }
  329. /**
  330. * 注册PWM中断的处理事件
  331. *
  332. * @author lxz
  333. *
  334. * @param no
  335. * @param handle
  336. * @param para
  337. */
  338. void hw_pwm_it_register(unsigned char no, pwm_handle handle, void *para) {
  339. if (no < HW_PWM_NUMBER) {
  340. pwm_hanlde_parames[no] = para;
  341. pwm_handle_maps[no] = handle;
  342. }
  343. }
  344. static void hw_pwm_pulse_init(int index)
  345. {
  346. hw_pwm_pin_t *pwm_pin = &pin_maps[index];
  347. uint32_t port = (uint32_t)pwm_pin->pulse_port;
  348. uint16_t pin = pwm_pin->pulse_pin;
  349. if (port >= GPIOA_BASE && port <= GPIOG_BASE)
  350. {
  351. RCC->APB2ENR |= 1 << ((port - APB2PERIPH_BASE) / 0x400);
  352. GPIO_Set((GPIO_TypeDef *)port, 1 << pin,
  353. GPIO_MODE_AF_PP,
  354. GPIO_SPEED_50M,
  355. GPIO_PUPD_PU);
  356. GPIO_Remap_Set(pwm_pin->remap, 1);
  357. }
  358. }
  359. static void hw_pwm_dir_init(int index)
  360. {
  361. hw_pwm_pin_t *pwm_pin = &pin_maps[index];
  362. uint32_t port = (uint32_t)pwm_pin->dir_port;
  363. uint16_t pin = pwm_pin->dir_pin;
  364. if (port >= GPIOA_BASE && port <= GPIOG_BASE)
  365. {
  366. RCC->APB2ENR |= 1 << ((port - APB2PERIPH_BASE) / 0x400);
  367. GPIO_Set((GPIO_TypeDef *)port, 1 << pin,
  368. GPIO_MODE_OUT_PP,
  369. GPIO_SPEED_50M,
  370. GPIO_PUPD_PU);
  371. hw_pwm_dir_rw_map[index].idr = (uint16_t *)(port + 16);
  372. hw_pwm_dir_rw_map[index].odr = (uint16_t *)(port + 24);
  373. hw_pwm_dir_rw_map[index].pin = (1 << pin);
  374. hw_pwm_dir_rw_map[index].level = 0;
  375. }
  376. }
  377. static void hw_pwm_on_init(int index)
  378. {
  379. hw_pwm_pin_t *pwm_pin = &pin_maps[index];
  380. uint32_t port = (uint32_t)pwm_pin->en_port;
  381. uint16_t pin = pwm_pin->en_pin;
  382. if (port >= GPIOA_BASE && port <= GPIOG_BASE)
  383. {
  384. RCC->APB2ENR |= 1 << ((port - APB2PERIPH_BASE) / 0x400);
  385. GPIO_Set((GPIO_TypeDef *)port, 1 << pin,
  386. GPIO_MODE_OUT_PP,
  387. GPIO_SPEED_50M,
  388. GPIO_PUPD_PU);
  389. hw_pwm_en_rw_map[index].idr = (uint16_t *)(port + 16);
  390. hw_pwm_en_rw_map[index].odr = (uint16_t *)(port + 24);
  391. hw_pwm_en_rw_map[index].pin = (1 << pin);
  392. hw_pwm_en_rw_map[index].level = 1;
  393. HW_PWM_SET_EN(index, 1);
  394. }
  395. }
  396. static void hw_pwm_timer_init(int index,int clk)
  397. {
  398. hw_pwm_t *pwm = &hw_pwm_maps[index];
  399. uint32_t tim_base = (uint32_t)pwm->base;
  400. TIM_TypeDef *timx = pwm->base;
  401. uint16_t psc = 1;
  402. if (tim_base >= TIM2_BASE && tim_base <= TIM5_BASE)
  403. {
  404. uint32_t en_mask = 1 << ((tim_base - APB1PERIPH_BASE) / 0x400);
  405. do {
  406. RCC->APB1ENR |= en_mask;
  407. } while (RCC->APB1ENR & en_mask == 0);
  408. psc = (clk * 1000000) / (pwm->unit_in_hz) - 1;
  409. }
  410. else if (tim_base >= TIM1_BASE && tim_base <= TIM8_BASE)
  411. {
  412. uint32_t en_mask = 1 << ((tim_base - APB2PERIPH_BASE) / 0x400);
  413. do {
  414. RCC->APB2ENR |= en_mask;
  415. } while (RCC->APB2ENR & en_mask == 0);
  416. psc = (clk * 1000000) / (pwm->unit_in_hz) - 1;
  417. }
  418. else
  419. {
  420. do {
  421. //无效的定时器
  422. } while (1);
  423. }
  424. //初始化定时器
  425. timx->PSC = psc; //设置预分频,得到一个基本的时钟单元
  426. timx->ARR = 1000; //没有意义
  427. timx->SMCR = 0;
  428. timx->DIER |= 1 << 0; //使能更新中断
  429. timx->CR1 &= ~(3 << 8); //不分频
  430. timx->CR1 &= ~(3 << 5); //边沿计数模式
  431. timx->CR1 &= ~(1 << 4); //向上计数
  432. timx->CR1 |= (1 << 2); //限制只有上溢中断
  433. if (timx == TIM8 || timx == TIM1)
  434. {
  435. timx->CR1 |= 1 << 7;
  436. timx->BDTR |= 1 << 15; //MOE使能输出
  437. }
  438. //timx->CR1 |= (1 << 7); //ARR寄存器不缓冲
  439. timx->CCR1 = 0;
  440. timx->CCR2 = 0;
  441. timx->CCR3 = 0;
  442. timx->CCR4 = 0;
  443. timx->CR2 = 0;
  444. timx->CCER |= (1 << ((pwm->ch - 1) * 4)); //使能PWM通道
  445. {
  446. timx->CCER &= ~(1 << ((pwm->ch - 1) * 4 + 1)); //高电平有效
  447. }
  448. if (pwm->ch <= 2)
  449. {
  450. uint32_t ccmr = timx->CCMR1;
  451. uint32_t offset = (pwm->ch - 1) * 8;
  452. ccmr &= ~(3 << (offset + 0)); //输出模式
  453. ccmr |= (1 << (offset + 2)); //比较快速使能
  454. ccmr |= (0 << (offset + 3)); //预装载使能禁止
  455. ccmr |= (7 << (offset + 4)); //PWM模式1,
  456. timx->CCMR1 = ccmr;
  457. }
  458. else
  459. {
  460. uint32_t ccmr = timx->CCMR2;
  461. uint32_t offset = (pwm->ch - 3) * 8;
  462. ccmr &= ~(3 << (offset + 0)); //输出模式
  463. ccmr |= (1 << (offset + 2)); //比较快速使能
  464. ccmr |= (0 << (offset + 3)); //预装载使能禁止
  465. ccmr |= (7 << (offset + 4)); //PWM模式1,
  466. timx->CCMR2 = ccmr;
  467. }
  468. //中断向量使能
  469. //MY_NVIC_Init(1, 3, pwm->irqn, 2);
  470. hw_pwm_period_registers[index] = (uint16_t *)(tim_base + 0x2C);
  471. hw_pwm_dutycycle_registers[index] = (uint16_t *)(tim_base + 0x34 + (pwm->ch - 1) * 4);
  472. hw_pwm_cr_registers[index] = (uint16_t *)(tim_base + 0x00);
  473. hw_pwm_egr_registers[index] = (uint16_t *)(tim_base + 0x10);
  474. HW_PWM_SET_PERIOD(index, 1000);
  475. HW_PWM_ON(index);
  476. hw_delay_us(1);
  477. HW_PWM_OFF(index);
  478. Sys_NVIC_Init(1, 1, pwm->irqn, 1);
  479. }
  480. /**
  481. * 初始化硬件
  482. */
  483. void hw_pwm_init(int clk) {
  484. //初始化IO
  485. int index = 0;
  486. while (index < HW_PWM_NUMBER)
  487. {
  488. if(index == 0)//X轴配置时
  489. {
  490. if(SET_PULSE_TYPE & X_AXIS_PULSE_ENABLE)
  491. {
  492. hw_pwm_pulse_init(index);
  493. }
  494. if(SET_PULSE_TYPE & Y_DIR_ENABLE)
  495. {
  496. hw_pwm_dir_init(index);
  497. }
  498. if(SET_PULSE_TYPE & Y_ON_ENABLE)
  499. {
  500. hw_pwm_on_init(index);
  501. }
  502. }
  503. else//Y轴配置时
  504. {
  505. if(SET_PULSE_TYPE & Y_AXIS_PULSE_ENABLE)
  506. {
  507. hw_pwm_pulse_init(index);
  508. }
  509. if(SET_PULSE_TYPE & X_DIR_ENABLE)
  510. {
  511. hw_pwm_dir_init(index);
  512. }
  513. if(SET_PULSE_TYPE & X_ON_ENABLE)
  514. {
  515. hw_pwm_on_init(index);
  516. }
  517. }
  518. index++;
  519. }
  520. //设置默认参数变量
  521. index = 0;
  522. while (index < HW_PWM_NUMBER)
  523. {
  524. pwm_handle_maps[index] = hw_pwm_default_handler;
  525. pwm_hanlde_parames[index] = (void *)0;
  526. index++;
  527. }
  528. //初始化硬件
  529. index = 0;
  530. while (index < HW_PWM_NUMBER)
  531. {
  532. if(index == 0)
  533. {
  534. if(SET_PULSE_TYPE & X_AXIS_PULSE_ENABLE)
  535. {
  536. hw_pwm_timer_init(index, clk);
  537. }
  538. }
  539. else
  540. {
  541. if(SET_PULSE_TYPE & Y_AXIS_PULSE_ENABLE)
  542. {
  543. hw_pwm_timer_init(index, clk);
  544. }
  545. }
  546. index++;
  547. }
  548. }
  549. /**
  550. * 关闭所有的脉冲输出
  551. *
  552. * @author lxz (2019/5/30/周四)
  553. */
  554. void hw_pwm_close_all(void) {
  555. int index = 0;
  556. while (index < HW_PWM_NUMBER) {
  557. HW_PWM_OFF(index);
  558. index++;
  559. }
  560. }