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.

100 lines
4.2 KiB

3 years ago
  1. # PWM
  2. ```
  3. 1khz变换2khz切换点会产生一个错误脉冲
  4. ```
  5. ## 1khz
  6. ![image-20220308143348591](markdown.assets/PWM%E9%94%99%E8%AF%AF%E8%AE%B0%E5%BD%95.assets/image-20220308143348591.png)
  7. ## 切断点的错误脉冲
  8. ![image-20220308143508650](markdown.assets/PWM%E9%94%99%E8%AF%AF%E8%AE%B0%E5%BD%95.assets/image-20220308143508650.png)
  9. ## 2khz
  10. ![image-20220308143535990](markdown.assets/PWM%E9%94%99%E8%AF%AF%E8%AE%B0%E5%BD%95.assets/image-20220308143535990.png)
  11. ## 原因:
  12. 每次进行pwm设置的时候都调用了这个方法,失能定时器后进行重新配置,这就导致丢失一定的波形输出
  13. ```c
  14. void set_pwm_t16_pa4(int freqhz, float duty) {
  15. double top_double = calculate_top(freqhz); //根据需要的频率计算出TOP(自动重装载值)
  16. uint16_t top = (uint16_t)top_double;
  17. uint16_t Mat2 = (uint16_t)top_double * (duty / 100.0);
  18. uint16_t Mat3 = top;
  19. if (Mat2 >= top) Mat2 = top - 1;
  20. printf("Mat2:%d\r\n", Mat2);
  21. printf("Mat3:%d\r\n", Mat3);
  22. printf("top:%d\r\n", top);
  23. /////////////////////////////////////////////////
  24. T16Nx_Disable(T16N0);
  25. // PA4 T16N0_1
  26. T16Nx_BaseInitStruType x;
  27. T16Nx_PWMInitStruType y;
  28. /* 初始化T16Nx定时器*/
  29. x.T16Nx_ClkS = T16Nx_ClkS_PCLK; //时钟源48M
  30. x.T16Nx_SYNC = Disable; //不同步
  31. x.T16Nx_EDGE = T16Nx_EDGE_Rise; //上升沿触发
  32. x.T16Nx_Mode = T16Nx_Mode_PWM; // 选用PWM模式
  33. x.T16Nx_PREMAT = 0x01; /* 预分频比1:1 */
  34. T16Nx_BaseInit(T16N0, &x);
  35. /* 配置T16N0通道1输出 */
  36. y.T16Nx_MOE0 = Disable;
  37. y.T16Nx_MOE1 = Enable;
  38. y.T16Nx_POL0 = POSITIVE; //在串口发送的时候,正极性代表发送的数据与接受的数据相同,负极性代表与发送的数据相反,在这么不知道有没有作用
  39. y.T16Nx_POL1 = POSITIVE;
  40. y.T16Nx_PWMMODE = T16Nx_PWMMode_INDEP; //选择独立模式
  41. y.PWMDZE = Disable; // PWM互补模式死区使能
  42. y.REGBUFEN = Enable; //缓冲寄存器使能 (REGBUFEN目前不知道干什么用的)
  43. T16Nx_PMWOutInit(T16N0, &y);
  44. /* 配置T16N0 通道1输出 */
  45. /*MAT2 MAT3 通道的中断配置*/
  46. //匹配寄存器值匹配后的工作模式,计数到以后: 继续计数不产生中断
  47. T16Nx_MAT2ITConfig(T16N0, T16Nx_Go_No);
  48. //匹配寄存器值匹配后的工作模式,清零并重新计数,产生中断
  49. T16Nx_MAT3ITConfig(T16N0, T16Nx_Clr_Int);
  50. /*MAT2 MAT3 匹配后的输出电平高低*/
  51. T16Nx_MAT2Out1Config(T16N0,
  52. T16Nx_Out_Low); //匹配后输出端口的模式,输出高还是低
  53. T16Nx_MAT3Out1Config(T16N0,
  54. T16Nx_Out_High); //匹配后输出端口的模式,输出高还是低
  55. //以上是设置模式,输出高低电平
  56. T16Nx_SetCNT1(T16N0, 0); //设定计数器的初始值
  57. T16Nx_SetMAT2(T16N0, Mat2); //设置匹配寄存器的数值
  58. T16Nx_SetMAT3(T16N0, Mat3); //设置匹配寄存器的数值
  59. //设置计数器峰值//根据这个得到定时的时钟48M/48000=1khZ(在独立模式下PWM的周期由TOP1决定为TOP+1,周期算出来是1ms)
  60. T16Nx_SetTOP1(T16N0, top);
  61. //以上是设置占空比
  62. /* 配置输出管脚 */
  63. GPIO_InitSettingType initset;
  64. initset.Signal = GPIO_Pin_Signal_Digital; //数字
  65. initset.Dir = GPIO_Direction_Output; //输出模式
  66. initset.Func = GPIO_Reuse_Func2; //复用到T16N0_1功能
  67. initset.ODE = GPIO_ODE_Output_Disable; //开漏使能
  68. initset.DS = GPIO_DS_Output_Normal; //普通电流模式
  69. initset.PUE = GPIO_PUE_Input_Enable; //弱上拉使能
  70. initset.PDE = GPIO_PDE_Input_Disable; //弱下拉禁止
  71. /* 配置PA4为T16N0输出通道1 */
  72. GPIO_Init(GPIO_Pin_A4, &initset);
  73. T16Nx_Enable(T16N0);
  74. return;
  75. }
  76. ```
  77. ## 解决:
  78. 只初始化配置一次PWM输出,修改pwm频率时,只修改以下参数
  79. ```c
  80. T16Nx_SetMAT2(T16N0, Mat2); //设置匹配寄存器的数值
  81. T16Nx_SetMAT3(T16N0, Mat3); //设置匹配寄存器的数值
  82. //设置计数器峰值//根据这个得到定时的时钟48M/48000=1khZ(在独立模式下PWM的周期由TOP1决定为TOP+1,周期算出来是1ms)
  83. T16Nx_SetTOP1(T16N0, top);
  84. ```