You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

226 lines
8.1 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. #include "pwm.h"
  2. #include "board.h"
  3. #define CLCK 48
  4. uint32_t target_frequencyhz;
  5. uint32_t target_duty;
  6. static double calculate_top(double target_frequency_hz) {
  7. int clck = 0;
  8. int top = 0;
  9. clck = CLCK * 1000 * 1000;
  10. top = clck / target_frequency_hz;
  11. return top;
  12. }
  13. void t16_pa4_init(void) {
  14. T16Nx_Disable(T16N0);
  15. // PA4 T16N0_1
  16. T16Nx_BaseInitStruType x;
  17. T16Nx_PWMInitStruType y;
  18. /* 初始化T16Nx定时器*/
  19. x.T16Nx_ClkS = T16Nx_ClkS_PCLK; //时钟源48M
  20. x.T16Nx_SYNC = Disable; //不同步
  21. x.T16Nx_EDGE = T16Nx_EDGE_Rise; //上升沿触发
  22. x.T16Nx_Mode = T16Nx_Mode_PWM; // 选用PWM模式
  23. x.T16Nx_PREMAT = 0x01; /* 预分频比1:1 */
  24. T16Nx_BaseInit(T16N0, &x);
  25. /* 配置T16N0通道1输出 */
  26. y.T16Nx_MOE0 = Disable;
  27. y.T16Nx_MOE1 = Enable;
  28. y.T16Nx_POL0 = POSITIVE; //在串口发送的时候,正极性代表发送的数据与接受的数据相同,负极性代表与发送的数据相反,在这么不知道有没有作用
  29. y.T16Nx_POL1 = POSITIVE;
  30. y.T16Nx_PWMMODE = T16Nx_PWMMode_INDEP; //选择独立模式
  31. y.PWMDZE = Disable; // PWM互补模式死区使能
  32. y.REGBUFEN = Enable; //缓冲寄存器使能 (REGBUFEN目前不知道干什么用的)
  33. T16Nx_PMWOutInit(T16N0, &y);
  34. /* 配置T16N0 通道1输出 */
  35. /*MAT2 MAT3 通道的中断配置*/
  36. //匹配寄存器值匹配后的工作模式,计数到以后: 继续计数不产生中断
  37. T16Nx_MAT2ITConfig(T16N0, T16Nx_Go_No);
  38. //匹配寄存器值匹配后的工作模式,清零并重新计数,产生中断
  39. T16Nx_MAT3ITConfig(T16N0, T16Nx_Clr_Int);
  40. /*MAT2 MAT3 匹配后的输出电平高低*/
  41. T16Nx_MAT2Out1Config(T16N0,
  42. T16Nx_Out_Low); //匹配后输出端口的模式,输出高还是低
  43. T16Nx_MAT3Out1Config(T16N0,
  44. T16Nx_Out_High); //匹配后输出端口的模式,输出高还是低
  45. //以上是设置模式,输出高低电平
  46. T16Nx_SetCNT1(T16N0, 0); //设定计数器的初始值
  47. T16Nx_SetMAT2(T16N0, 0); //设置匹配寄存器的数值
  48. T16Nx_SetMAT3(T16N0, 0); //设置匹配寄存器的数值
  49. //设置计数器峰值//根据这个得到定时的时钟48M/48000=1khZ(在独立模式下PWM的周期由TOP1决定为TOP+1,周期算出来是1ms)
  50. T16Nx_SetTOP1(T16N0, 0);
  51. //以上是设置占空比
  52. /* 配置输出管脚 */
  53. GPIO_InitSettingType initset;
  54. initset.Signal = GPIO_Pin_Signal_Digital; //数字
  55. initset.Dir = GPIO_Direction_Output; //输出模式
  56. initset.Func = GPIO_Reuse_Func2; //复用到T16N0_1功能
  57. initset.ODE = GPIO_ODE_Output_Disable; //开漏使能
  58. initset.DS = GPIO_DS_Output_Normal; //普通电流模式
  59. initset.PUE = GPIO_PUE_Input_Enable; //弱上拉使能
  60. initset.PDE = GPIO_PDE_Input_Disable; //弱下拉禁止
  61. /* 配置PA4为T16N0输出通道1 */
  62. GPIO_Init(GPIO_Pin_A4, &initset);
  63. T16Nx_Enable(T16N0);
  64. return;
  65. }
  66. void set_pwm_t16_pa4(uint32_t freqhz, double duty) {
  67. double top_double = calculate_top(freqhz); //根据需要的频率计算出TOP(自动重装载值)
  68. uint16_t top = (uint16_t)top_double;
  69. uint16_t Mat2 = (uint16_t)top_double * (duty / 100.0);
  70. uint16_t Mat3 = top;
  71. if (Mat2 >= top) Mat2 = top - 1;
  72. // printf("Mat2:%d\r\n", Mat2);
  73. // printf("Mat3:%d\r\n", Mat3);
  74. // printf("top:%d\r\n", top);
  75. T16Nx_SetCNT1(T16N0, 0); //设定计数器的初始值
  76. T16Nx_SetMAT2(T16N0, Mat2); //设置匹配寄存器的数值
  77. T16Nx_SetMAT3(T16N0, Mat3); //设置匹配寄存器的数值
  78. //设置计数器峰值//根据这个得到定时的时钟48M/48000=1khZ(在独立模式下PWM的周期由TOP1决定为TOP+1,周期算出来是1ms)
  79. T16Nx_SetTOP1(T16N0, top);
  80. //以上是设置占空比
  81. }
  82. //######################################################
  83. /**
  84. * @brief pwm的周期占空比
  85. *
  86. * @param frequency
  87. * @param duty
  88. */
  89. /**
  90. *
  91. * :
  92. *
  93. *
  94. *
  95. * :
  96. * 20->0
  97. * 0->20
  98. * 0->10
  99. *
  100. * ,
  101. *
  102. *
  103. *
  104. *
  105. *
  106. *
  107. * 1. ,
  108. * 2.
  109. *
  110. */
  111. uint32_t s_target_frequencyhz;
  112. uint32_t s_now_frequencyhz;
  113. uint32_t s_target_duty;
  114. uint32_t s_now_duty;
  115. /**
  116. * @brief
  117. *
  118. * @param freq
  119. * @param us
  120. */
  121. // static uint32_t get_duty_by_freq_and_valid_time(uint32_t freq, uint32_t us) {
  122. // uint32_t period = 1000000 / freq;
  123. // uint32_t duty = us * 100 / period;
  124. // return duty;
  125. // }
  126. // static uint32_t get_pwm_pulse_width_us_by_duty(uint32_t freq, uint32_t duty) {
  127. // uint32_t period = 1000000 / freq;
  128. // uint32_t pwm_pulse_width_us = period * duty / 100;
  129. // return pwm_pulse_width_us;
  130. // }
  131. double get_duty(double now_duty, double target_duty, double increment_count) {
  132. if (now_duty > target_duty) {
  133. now_duty -= (now_duty - target_duty) / increment_count; //(now_duty-target_duty)/increment_count每次的增量
  134. } else if (now_duty < target_duty) {
  135. now_duty += (target_duty - now_duty) / increment_count;
  136. }
  137. return now_duty;
  138. }
  139. void set_pwm_modbul_freq_duty(uint32_t frequencyhz, uint32_t duty) {
  140. static uint32_t now_frequencyhz;
  141. static double now_duty;
  142. static uint32_t pwm_pulse_width_us;
  143. uint32_t increment_conut; //从现在的频率到目标频率每次增加PWM_CHANGE_STEP_FREQ,还需要增加多少次
  144. target_frequencyhz = frequencyhz;
  145. target_duty = duty;
  146. if (now_frequencyhz == target_frequencyhz) {
  147. if (now_duty != target_duty) {
  148. now_duty = target_duty;
  149. set_pwm_t16_pa4(now_frequencyhz, now_duty);
  150. }
  151. if ((uint32_t)now_duty == target_duty) {
  152. return;
  153. }
  154. }
  155. // pwm_pulse_width_us = get_pwm_pulse_width_us_by_duty(target_frequencyhz, target_duty);
  156. if (now_frequencyhz < target_frequencyhz) {
  157. now_frequencyhz = now_frequencyhz + PWM_CHANGE_STEP_FREQ;
  158. if (now_frequencyhz >= target_frequencyhz) {
  159. now_frequencyhz = target_frequencyhz;
  160. }
  161. increment_conut = (target_frequencyhz - now_frequencyhz) / PWM_CHANGE_STEP_FREQ;
  162. // now_duty = get_duty_by_freq_and_valid_time(now_frequencyhz, pwm_pulse_width_us);
  163. now_duty = get_duty(now_duty, target_duty, increment_conut);
  164. set_pwm_t16_pa4(now_frequencyhz, now_duty);
  165. printf("%d,%lf\r\n", now_frequencyhz, now_duty);
  166. } else if (now_frequencyhz > target_frequencyhz) {
  167. now_frequencyhz = now_frequencyhz - PWM_CHANGE_STEP_FREQ;
  168. if (now_frequencyhz <= target_frequencyhz) {
  169. now_frequencyhz = target_frequencyhz;
  170. }
  171. // now_duty = get_duty_by_freq_and_valid_time(now_frequencyhz, pwm_pulse_width_us);
  172. increment_conut = (now_frequencyhz - target_frequencyhz) / PWM_CHANGE_STEP_FREQ;
  173. now_duty = get_duty(now_duty, target_duty, increment_conut);
  174. set_pwm_t16_pa4(now_frequencyhz, now_duty);
  175. printf("%d,%lf\r\n", now_frequencyhz, now_duty);
  176. }
  177. }
  178. // uint32_t get_next_value_on_step(uint32_t now, uint32_t target, uint32_t step) {
  179. // }
  180. // void pwm_module_stop() { set_pwm_modbul_freq_duty(MIN_PWM_FREQ, 0); }
  181. // void pwm_schdule() {
  182. // /**
  183. // * @brief 当前频率的占空比的百分之一变化
  184. // */
  185. // //计算当前频率下的目标占空比
  186. // uint32_t targetduty = 0;
  187. // uint32_t targetduty1 = s_target_duty;
  188. // uint32_t targetduty2 = (1.0 / s_target_frequencyhz) * (s_target_duty / 100.0) / (1.0 / s_now_frequencyhz) * 100;
  189. // targetduty = targetduty1 < targetduty2 ? targetduty1 : targetduty2;
  190. // if (targetduty != s_now_duty) {
  191. // set_pwm_t16_pa4(s_now_frequencyhz, targetduty);
  192. // return;
  193. // } else {
  194. // //计算下一次设置的频率
  195. // set_pwm_t16_pa4(s_now_frequencyhz, targetduty);
  196. // }
  197. // if (s_target_frequencyhz > s_now_frequencyhz) {
  198. // s_now_frequencyhz += 1000;
  199. // }
  200. // }
  201. //######################################################
  202. //# c语言的理解
  203. //# static , 字节长度 ,堆,栈,变量分布,
  204. //# 操作系统
  205. //# 线程,进程,信号量
  206. //#
  207. //#