[DemoCode下载] 基于ADC 输入电压来调整PWM 占空比

[复制链接]
483|5
 楼主| wahahaheihei 发表于 2023-6-20 15:09 | 显示全部楼层 |阅读模式
en-us--EC_MS51_ADC_PWM_V1.00.zip (1.12 MB, 下载次数: 1)
大家猜猜这是怎么用的?
是不是弄一个分压电位器,旋钮,转动起来就调节了PWM,是不是很爽。
  1. /**************************************************************************//**
  2. * [url=home.php?mod=space&uid=288409]@file[/url] main.c
  3. * [url=home.php?mod=space&uid=895143]@version[/url] V1.00
  4. * [url=home.php?mod=space&uid=247401]@brief[/url] This example code uses MS51 PWM to output 10 KHz waveform with 0~100% duty according to 0~3V ADC conversion.
  5. *
  6. * SPDX-License-Identifier: Apache-2.0
  7. * [url=home.php?mod=space&uid=17282]@CopyRight[/url] (C) 2022 Nuvoton Technology Corp. All rights reserved.
  8. *****************************************************************************/


  9. #include "MS51_8K.h"

  10. /*---------------------------------------------------------------------------------------------------------*/
  11. /* Define                                                                                                                                 */
  12. /*---------------------------------------------------------------------------------------------------------*/

  13. /* main-loop switch-case state */
  14. #define IDLE_STATE       0
  15. #define ADC_UPDATE_STATE   1

  16. /**
  17. * PWM frequency = FPWM / {(PWM0PH, PWM0PL) + 1}
  18. * 10kHz         = 24MHz / {(PWM0PH, PWM0PL) + 1}
  19. * (PWM0PH, PWM0PL) = 2399(0x95F)
  20. */
  21. #define PWM_FREQ   0x95F
  22. #define ROUNDING(x) (2x-(int)(x))

  23. /*---------------------------------------------------------------------------------------------------------*/
  24. /* Global variables                                                                                        */
  25. /*---------------------------------------------------------------------------------------------------------*/
  26. bit g_bADC_Flag = 0;
  27. unsigned int xdata u32_ADCdataAIN;
  28. double i64_ADCdataConvert;

  29. /*---------------------------------------------------------------------------------------------------------*/
  30. /* Functions                                                                                                           */
  31. /*---------------------------------------------------------------------------------------------------------*/
  32. /**
  33. * @brief ADC interrupt service routine
  34. *
  35. * @param[in] None
  36. *
  37. * [url=home.php?mod=space&uid=266161]@return[/url] None
  38. *
  39. * [url=home.php?mod=space&uid=1543424]@Details[/url] Get ADC conversion result.
  40. */
  41. void ADC_ISR(void) interrupt 11
  42. {
  43.     _push_(SFRS);

  44.     clr_ADCCON0_ADCF;//Clear ADC interrupt flag

  45.     u32_ADCdataAIN = ADCRH << 4;
  46.     u32_ADCdataAIN |= ADCRL;
  47.     g_bADC_Flag = 1;
  48.     _pop_(SFRS);
  49. }

  50. /**
  51. * @brief Initialize the PWM module with specified configurations. It could be clock source, PWM channel and frequency.
  52. *        The default duty cycle is 50%.
  53. *
  54. * @param[in] None
  55. *
  56. * @return None
  57. *
  58. * @details None
  59. */
  60. void PWM0_Init(void)
  61. {
  62.     /* Define PWM0 clock source and divider. */
  63.     PWM0_ClockSource(PWM_FSYS, 1);

  64.     /* Setting PWM0 channel 2 */
  65.     ENABLE_PWM0_CH2_P10_OUTPUT;
  66.     P10_PUSHPULL_MODE;
  67.     PWM0_ConfigOutputChannel(2, Independent, EdgeAligned, PWM_FREQ, 50);

  68.     PWM0_RUN();
  69. }

  70. /**
  71. * @brief Update PWM duty cycle.
  72. *
  73. * @param[in] u16PWM0Duty Set PWM default duty cycle. The range is 0%~100%
  74. *
  75. * @return None
  76. *
  77. * @details The formula is:
  78. *          PWM duty cycle = PWM duty register /  (PWM period register + 1)
  79. *          -> PWM duty register = PWM duty cycle * (PWM period register + 1)
  80. */
  81. void PWM0_Reload(unsigned int u16PWM0Duty)
  82. {
  83.     /* Reload PWM duty */
  84.     unsigned int u16PWM0DutyCycleTemp = 0;
  85.     u16PWM0DutyCycleTemp = ((PWM_FREQ + 1) / 100) * u16PWM0Duty;

  86.     PWM2H = u16PWM0DutyCycleTemp >> 8;
  87.     PWM2L = u16PWM0DutyCycleTemp;

  88.     set_PWMCON0_LOAD;
  89. }

  90. /**
  91. * @brief Initialize the ADC module with specified configurations and start ADC convert.
  92. *
  93. * @param[in] None
  94. *
  95. * @return None
  96. *
  97. * @details None
  98. */
  99. void ADC_Convert(void)
  100. {
  101.     /*Enable channel 5 */
  102.     ENABLE_ADC_CH5;
  103.     ADCCON1 |= 0x30;          /* clock divider */
  104.     ADCCON2 |= 0x0E;          /* AQT time */
  105.     AUXR1 |= SET_BIT4;        /* ADC clock low speed */
  106.     clr_ADCCON0_ADCF;
  107.     set_ADCCON0_ADCS;

  108.     /* Enable ADC interrupt */
  109.     set_IE_EADC;
  110. }

  111. void main(void)
  112. {
  113.     unsigned char state = IDLE_STATE;

  114.     /* FSYS = 24MHz */
  115.     MODIFY_HIRC(HIRC_24);
  116.     PWM0_Init();
  117.     ENABLE_GLOBAL_INTERRUPT;

  118.     while (1)
  119.     {
  120.         switch (state)
  121.         {
  122.             case IDLE_STATE:
  123.             default:
  124.                 /* Enable channel 5 */
  125.                 ADC_Convert();
  126.                 state = ADC_UPDATE_STATE;
  127.                 break;


  128.             case ADC_UPDATE_STATE:

  129.                 if (g_bADC_Flag == 1)
  130.                 {
  131.                     g_bADC_Flag = 0;

  132.                     i64_ADCdataConvert = u32_ADCdataAIN;
  133.                     i64_ADCdataConvert = i64_ADCdataConvert * 100 / 4095;
  134.                     /* Integer value */
  135.                     i64_ADCdataConvert = (2 * i64_ADCdataConvert - (int)(i64_ADCdataConvert));

  136.                     PWM0_Reload((unsigned int)i64_ADCdataConvert);
  137.                     DISABLE_ADC;
  138.                     state = IDLE_STATE;
  139.                 }

  140.                 break;
  141.         }
  142.     }
  143. }





稳稳の幸福 发表于 2023-6-21 08:45 | 显示全部楼层
方法不错,用于测试或者要求精度不高但是连续调节的应用。
heisexingqisi 发表于 2023-6-30 20:56 | 显示全部楼层
学习一下这个操作方法。
heisexingqisi 发表于 2023-6-30 20:57 | 显示全部楼层
用的是状态机,如果用中断也是可以的吧。在主函数里读取标志位再判断是否执行PWM修改。
643757107 发表于 2023-7-9 16:28 | 显示全部楼层
ADC调节PWM占空比。
Bowclad 发表于 2023-7-11 23:44 | 显示全部楼层
但是电位器调节精度怎么控制啊?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

232

主题

3223

帖子

12

粉丝
快速回复 在线客服 返回列表 返回顶部