ls1c_pwm.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. // 封装硬件pwm接口
  2. #include "ls1c_public.h"
  3. #include "ls1c_pin.h"
  4. #include "ls1c_pwm.h"
  5. #include "ls1c_clock.h"
  6. #include "ls1c_regs.h"
  7. // pwm的最大周期
  8. #define PWM_MAX_PERIOD (0xFFFFFF) // 计数器的值
  9. /*
  10. * 根据gpio获取相应pwm的基地址
  11. * @gpio pwm引脚
  12. * @ret pwm基地址
  13. */
  14. unsigned int pwm_get_reg_base(unsigned int gpio)
  15. {
  16. unsigned int reg_base = 0;
  17. switch (gpio)
  18. {
  19. case LS1C_PWM0_GPIO06:
  20. case LS1C_PWM0_GPIO04:
  21. reg_base = LS1C_REG_BASE_PWM0;
  22. break;
  23. case LS1C_PWM1_GPIO92:
  24. case LS1C_PWM1_GPIO05:
  25. reg_base = LS1C_REG_BASE_PWM1;
  26. break;
  27. case LS1C_PWM2_GPIO52:
  28. case LS1C_PWM2_GPIO46:
  29. reg_base = LS1C_REG_BASE_PWM2;
  30. break;
  31. case LS1C_PWM3_GPIO47:
  32. case LS1C_PWM3_GPIO53:
  33. reg_base = LS1C_REG_BASE_PWM3;
  34. break;
  35. }
  36. return reg_base;
  37. }
  38. /*
  39. * 禁止pwm
  40. * @pwm_info PWMn的详细信息
  41. */
  42. void pwm_disable(pwm_info_t *pwm_info)
  43. {
  44. unsigned int pwm_reg_base = 0;
  45. // 检查入参
  46. if (NULL == pwm_info)
  47. {
  48. return ;
  49. }
  50. pwm_reg_base = pwm_get_reg_base(pwm_info->gpio);
  51. reg_write_32(0, (volatile unsigned int *)(pwm_reg_base + LS1C_PWM_CTRL));
  52. return ;
  53. }
  54. /*
  55. * 使能PWM
  56. * @pwm_info PWMn的详细信息
  57. */
  58. void pwm_enable(pwm_info_t *pwm_info)
  59. {
  60. unsigned int pwm_reg_base = 0;
  61. unsigned int ctrl = 0;
  62. // 检查入参
  63. if (NULL == pwm_info)
  64. {
  65. return ;
  66. }
  67. // 获取基地址
  68. pwm_reg_base = pwm_get_reg_base(pwm_info->gpio);
  69. // 清零计数器
  70. reg_write_32(0, (volatile unsigned int *)(pwm_reg_base + LS1C_PWM_CNTR));
  71. // 设置控制寄存器
  72. ctrl = (0 << LS1C_PWM_INT_LRC_EN)
  73. | (0 << LS1C_PWM_INT_HRC_EN)
  74. | (0 << LS1C_PWM_CNTR_RST)
  75. | (0 << LS1C_PWM_INT_SR)
  76. | (0 << LS1C_PWM_INTEN)
  77. | (0 << LS1C_PWM_OE)
  78. | (1 << LS1C_PWM_CNT_EN);
  79. if (PWM_MODE_PULSE == pwm_info->mode) // 单脉冲
  80. {
  81. ctrl |= (1 << LS1C_PWM_SINGLE);
  82. }
  83. else // 连续脉冲
  84. {
  85. ctrl &= ~(1 << LS1C_PWM_SINGLE);
  86. }
  87. reg_write_32(ctrl, (volatile unsigned int *)(pwm_reg_base + LS1C_PWM_CTRL));
  88. return ;
  89. }
  90. /*
  91. * 初始化PWMn
  92. * @pwm_info PWMn的详细信息
  93. */
  94. void pwm_init(pwm_info_t *pwm_info)
  95. {
  96. unsigned int gpio;
  97. unsigned long pwm_clk = 0; // pwm模块的时钟频率
  98. unsigned long tmp = 0;
  99. unsigned int pwm_reg_base = 0;
  100. unsigned long period = 0;
  101. // 判断入参
  102. if (NULL == pwm_info)
  103. {
  104. // 入参非法,则直接返回
  105. return ;
  106. }
  107. gpio = pwm_info->gpio;
  108. // 配置相应引脚用作pwm,而非gpio
  109. pin_set_purpose(gpio, PIN_PURPOSE_OTHER);
  110. // 复用
  111. switch (gpio)
  112. {
  113. // 不需要复用
  114. case LS1C_PWM0_GPIO06:
  115. case LS1C_PWM1_GPIO92:
  116. break;
  117. case LS1C_PWM0_GPIO04: // gpio04的第三复用
  118. pin_set_remap(LS1C_PWM0_GPIO04, PIN_REMAP_THIRD);
  119. break;
  120. case LS1C_PWM1_GPIO05: // gpio05的第三复用
  121. pin_set_remap(LS1C_PWM1_GPIO05, PIN_REMAP_THIRD);
  122. break;
  123. case LS1C_PWM2_GPIO52: // gpio52的第四复用
  124. pin_set_remap(LS1C_PWM2_GPIO52, PIN_REMAP_FOURTH);
  125. break;
  126. case LS1C_PWM2_GPIO46: // gpio46的第四复用
  127. pin_set_remap(LS1C_PWM2_GPIO46, PIN_REMAP_FOURTH);
  128. break;
  129. case LS1C_PWM3_GPIO47: // gpio47的第四复用
  130. pin_set_remap(LS1C_PWM3_GPIO47, PIN_REMAP_FOURTH);
  131. break;
  132. case LS1C_PWM3_GPIO53: // gpio53的第四复用
  133. pin_set_remap(LS1C_PWM3_GPIO53, PIN_REMAP_FOURTH);
  134. break;
  135. default:
  136. break;
  137. }
  138. // 根据占空比和pwm周期计算寄存器HRC和LRC的值
  139. // 两个64位数相乘,只能得到低32位,linux下却可以得到64位结果,
  140. // 暂不清楚原因,用浮点运算代替
  141. pwm_clk = clk_get_apb_rate();
  142. period = (1.0 * pwm_clk * pwm_info->period_ns) / 1000000000;
  143. period = MIN(period, PWM_MAX_PERIOD); // 限制周期不能超过最大值
  144. tmp = period - (period * pwm_info->duty);
  145. // 写寄存器HRC和LRC
  146. pwm_reg_base = pwm_get_reg_base(gpio);
  147. reg_write_32(--tmp, (volatile unsigned int *)(pwm_reg_base + LS1C_PWM_HRC));
  148. reg_write_32(--period, (volatile unsigned int *)(pwm_reg_base + LS1C_PWM_LRC));
  149. // 写主计数器
  150. pwm_enable(pwm_info);
  151. return ;
  152. }