打印
[DemoCode下载]

基于ADC 输入电压来调整PWM 占空比

[复制链接]
136|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wahahaheihei|  楼主 | 2023-6-20 15:09 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
en-us--EC_MS51_ADC_PWM_V1.00.zip (1.12 MB)
大家猜猜这是怎么用的?
是不是弄一个分压电位器,旋钮,转动起来就调节了PWM,是不是很爽。
/**************************************************************************//**
* [url=home.php?mod=space&uid=288409]@file[/url] main.c
* [url=home.php?mod=space&uid=895143]@version[/url] V1.00
* [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.
*
* SPDX-License-Identifier: Apache-2.0
* [url=home.php?mod=space&uid=17282]@CopyRight[/url] (C) 2022 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/


#include "MS51_8K.h"

/*---------------------------------------------------------------------------------------------------------*/
/* Define                                                                                                                                 */
/*---------------------------------------------------------------------------------------------------------*/

/* main-loop switch-case state */
#define IDLE_STATE       0
#define ADC_UPDATE_STATE   1

/**
* PWM frequency = FPWM / {(PWM0PH, PWM0PL) + 1}
* 10kHz         = 24MHz / {(PWM0PH, PWM0PL) + 1}
* (PWM0PH, PWM0PL) = 2399(0x95F)
*/
#define PWM_FREQ   0x95F
#define ROUNDING(x) (2x-(int)(x))

/*---------------------------------------------------------------------------------------------------------*/
/* Global variables                                                                                        */
/*---------------------------------------------------------------------------------------------------------*/
bit g_bADC_Flag = 0;
unsigned int xdata u32_ADCdataAIN;
double i64_ADCdataConvert;

/*---------------------------------------------------------------------------------------------------------*/
/* Functions                                                                                                           */
/*---------------------------------------------------------------------------------------------------------*/
/**
* @brief ADC interrupt service routine
*
* @param[in] None
*
* [url=home.php?mod=space&uid=266161]@return[/url] None
*
* [url=home.php?mod=space&uid=1543424]@Details[/url] Get ADC conversion result.
*/
void ADC_ISR(void) interrupt 11
{
    _push_(SFRS);

    clr_ADCCON0_ADCF;//Clear ADC interrupt flag

    u32_ADCdataAIN = ADCRH << 4;
    u32_ADCdataAIN |= ADCRL;
    g_bADC_Flag = 1;
    _pop_(SFRS);
}

/**
* @brief Initialize the PWM module with specified configurations. It could be clock source, PWM channel and frequency.
*        The default duty cycle is 50%.
*
* @param[in] None
*
* @return None
*
* @details None
*/
void PWM0_Init(void)
{
    /* Define PWM0 clock source and divider. */
    PWM0_ClockSource(PWM_FSYS, 1);

    /* Setting PWM0 channel 2 */
    ENABLE_PWM0_CH2_P10_OUTPUT;
    P10_PUSHPULL_MODE;
    PWM0_ConfigOutputChannel(2, Independent, EdgeAligned, PWM_FREQ, 50);

    PWM0_RUN();
}

/**
* @brief Update PWM duty cycle.
*
* @param[in] u16PWM0Duty Set PWM default duty cycle. The range is 0%~100%
*
* @return None
*
* @details The formula is:
*          PWM duty cycle = PWM duty register /  (PWM period register + 1)
*          -> PWM duty register = PWM duty cycle * (PWM period register + 1)
*/
void PWM0_Reload(unsigned int u16PWM0Duty)
{
    /* Reload PWM duty */
    unsigned int u16PWM0DutyCycleTemp = 0;
    u16PWM0DutyCycleTemp = ((PWM_FREQ + 1) / 100) * u16PWM0Duty;

    PWM2H = u16PWM0DutyCycleTemp >> 8;
    PWM2L = u16PWM0DutyCycleTemp;

    set_PWMCON0_LOAD;
}

/**
* @brief Initialize the ADC module with specified configurations and start ADC convert.
*
* @param[in] None
*
* @return None
*
* @details None
*/
void ADC_Convert(void)
{
    /*Enable channel 5 */
    ENABLE_ADC_CH5;
    ADCCON1 |= 0x30;          /* clock divider */
    ADCCON2 |= 0x0E;          /* AQT time */
    AUXR1 |= SET_BIT4;        /* ADC clock low speed */
    clr_ADCCON0_ADCF;
    set_ADCCON0_ADCS;

    /* Enable ADC interrupt */
    set_IE_EADC;
}

void main(void)
{
    unsigned char state = IDLE_STATE;

    /* FSYS = 24MHz */
    MODIFY_HIRC(HIRC_24);
    PWM0_Init();
    ENABLE_GLOBAL_INTERRUPT;

    while (1)
    {
        switch (state)
        {
            case IDLE_STATE:
            default:
                /* Enable channel 5 */
                ADC_Convert();
                state = ADC_UPDATE_STATE;
                break;


            case ADC_UPDATE_STATE:

                if (g_bADC_Flag == 1)
                {
                    g_bADC_Flag = 0;

                    i64_ADCdataConvert = u32_ADCdataAIN;
                    i64_ADCdataConvert = i64_ADCdataConvert * 100 / 4095;
                    /* Integer value */
                    i64_ADCdataConvert = (2 * i64_ADCdataConvert - (int)(i64_ADCdataConvert));

                    PWM0_Reload((unsigned int)i64_ADCdataConvert);
                    DISABLE_ADC;
                    state = IDLE_STATE;
                }

                break;
        }
    }
}





使用特权

评论回复
沙发
稳稳の幸福| | 2023-6-21 08:45 | 只看该作者
方法不错,用于测试或者要求精度不高但是连续调节的应用。

使用特权

评论回复
板凳
heisexingqisi| | 2023-6-30 20:56 | 只看该作者
学习一下这个操作方法。

使用特权

评论回复
地板
heisexingqisi| | 2023-6-30 20:57 | 只看该作者
用的是状态机,如果用中断也是可以的吧。在主函数里读取标志位再判断是否执行PWM修改。

使用特权

评论回复
5
643757107| | 2023-7-9 16:28 | 只看该作者
ADC调节PWM占空比。

使用特权

评论回复
6
Bowclad| | 2023-7-11 23:44 | 只看该作者
但是电位器调节精度怎么控制啊?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

202

主题

2988

帖子

12

粉丝