[DemoCode下载]

透过 PWM 触发 ADC ,并且可以用 Brake 功能将 PWM 的波形停止

[复制链接]
1193|8
手机看帖
扫描二维码
随时随地手机跟帖
小灵通2018|  楼主 | 2018-12-26 23:59 | 显示全部楼层 |阅读模式
[Mini51][PWM]PWM_trigger_ADC_and_PWM_Brake_function.zip (417.14 KB)
捉虫天师| | 2018-12-27 00:01 | 显示全部楼层
分享 Brake function 的使用经验,在程序包里面的功能主要是透过 PWM trigger ADC ,并且可以用 Brake Function 将 PWM 的 waveform 停止,程序的部分需要设定使用 Brake0 or Brake1,并且选择要 产生 Brake 的 source,有 INT0-1 CPO0-1四种,可以透过 TRM 技术文件来看,假设想要使用 INT1 当 作 Brake 的 source 就要使用 Brake1 并且设定 CPO0BKEN bit 为使用 INT1,最后再将 INT1 设定为 Falling trigger这是因为 Brake 需要透过 Falling 来产生 event ,特别要注意的是 I/O 预设是 floating 因 此当产生了 Brake event 后将 PWM 的 waveform 停止,并且保持依照设定的 level 这个时候 Brake Flag 会被设起,若在中断有将 Brake Flag清除将会释放 PWM 因为没有设定 INT pin 的 IO 模式,因此 在 floating 的情况下用手去触摸会造成再次触发 Brake event, 让 PWM 再次被 Brake 成High 这是由 PWMBKO2(PFBCON[24:31]) 所设定,而进入中断后会将 Brake Flag 清除掉,这时候会让 PWM 的 waveform 回到 Low ,因此会产生一个很小宽度的 Pulse, 而产生 333ns 的 pulse 这是因为进入中断到 出来的时间为333ns,这说明了若是让 INT pin 为 floating 则会让 PWM 再次发生 Brake ,。
若是不想让 INT1 pin 为 floating 可以将 INT1 pin 设定为 Quasi-bidirectional I/O mode,这样可以让 INT1 的 pin 为 High 且不再 floating。

使用特权

评论回复
捉虫天师| | 2018-12-27 00:01 | 显示全部楼层

/******************************************************************************
* [url=home.php?mod=space&uid=288409]@file[/url]     main.c
* [url=home.php?mod=space&uid=895143]@version[/url]  V1.00
* $Revision: 3 $
* $Date: 13/10/07 3:57p $
* [url=home.php?mod=space&uid=247401]@brief[/url]    PWM sample for Mini51 series MCU
*
* @note
* Copyright (C) 2013 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/  
#include <stdio.h>
#include "Mini51Series.h"

volatile   uint32_t u32Flag;

void ADC_IRQHandler(void)
{      
    // Get ADC comparator interrupt flag
    u32Flag = ADC_GET_INT_FLAG(ADC, ADC_CMP0_INT | ADC_CMP1_INT);
   
    if(u32Flag & ADC_CMP0_INT)
        printf("Channel 0 input < 0x200\n");
    if(u32Flag & ADC_CMP1_INT)
        printf("Channel 0 input >= 0x200\n");
   
    ADC_CLR_INT_FLAG(ADC, u32Flag);
}

void EINT1_IRQHandler(void)
{
        P55=0;        //debug IO
        printf("INT1");
        P5->ISRC |= 0x04;        //CLR INT1 interrupt Flag
        PWM->PFBCON |= PWM_PFBCON_BKF_Msk;        //CLR Brake Function Flag
}

void PWM_IRQHandler(void)
{
    static uint32_t cnt;
    static uint32_t out;
   
    // Channel 0 frequency is 100Hz, every 1 second enter this IRQ handler 100 times.
    if(++cnt == 100) {
        if(out)
            PWM_EnableOutput(PWM, 0x3F);
        else
            PWM_DisableOutput(PWM, 0x3F);
        out ^= 1;
        cnt = 0;
    }
    // Clear channel 0 period interrupt flag
    PWM_ClearPeriodIntFlag(PWM, 0);
        PWM_ClearADCTriggerFlag(PWM, 0, PWM_TRIGGER_ADC_CNTR_IS_CNR);
        //PWM->PFBCON |= PWM_PFBCON_BKF_Msk;        //CLR Brake Function Flag
}

void SYS_Init(void)
{
/*---------------------------------------------------------------------------------------------------------*/
/* Init System Clock                                                                                       */
/*---------------------------------------------------------------------------------------------------------*/

    /* Unlock protected registers */
    SYS_UnlockReg();

    /* Enable external 12MHz XTAL, internal 22.1184MHz */
    CLK->PWRCON = CLK_PWRCON_XTL12M | CLK_PWRCON_IRC22M_EN_Msk;

    /* Waiting for clock ready */
    CLK_WaitClockReady(CLK_CLKSTATUS_XTL_STB_Msk | CLK_CLKSTATUS_IRC22M_STB_Msk);

    /* Enable IP clock */
    CLK->APBCLK = CLK_APBCLK_UART_EN_Msk | CLK_APBCLK_PWM01_EN_Msk | CLK_APBCLK_PWM23_EN_Msk | CLK_APBCLK_PWM45_EN_Msk | CLK_APBCLK_ADC_EN_Msk;

        /* ADC clock source is 22.1184MHz, set divider to (3 + 1), ADC clock is 22.1184/4 MHz */
    CLK->CLKDIV |= (3 << CLK_CLKDIV_ADC_N_Pos);
       
    /* Select UART clock source from external crystal*/
    CLK->CLKSEL1 = (CLK->CLKSEL1 & ~CLK_CLKSEL1_UART_S_Msk) | CLK_CLKSEL1_UART_S_XTAL;

    /* Update System Core Clock */
    /* User can use SystemCoreClockUpdate() to calculate SystemCoreClock and CycylesPerUs automatically. */
    SystemCoreClockUpdate();


/*---------------------------------------------------------------------------------------------------------*/
/* Init I/O Multi-function                                                                                 */
/*---------------------------------------------------------------------------------------------------------*/
    /* Set P1 multi-function pins for UART RXD, TXD */
    SYS->P0_MFP = SYS_MFP_P00_TXD | SYS_MFP_P01_RXD;

    /* Set P0 multi-function pins for PWM Channel 5  */
    SYS->P0_MFP |= SYS_MFP_P04_PWM5;
    /* Set P2 multi-function pins for PWM Channel 0~4  */
    SYS->P2_MFP |= SYS_MFP_P22_PWM0 | SYS_MFP_P23_PWM1 | SYS_MFP_P24_PWM2 | SYS_MFP_P25_PWM3 | SYS_MFP_P26_PWM4;

    /* Set P5.3 to ADC channel 0 input pin */
    SYS->P5_MFP |= SYS_MFP_P53_AIN0;
    /* Analog pin OFFD to prevent leakage */
    P5->OFFD |= (1 << 3) << GPIO_OFFD_OFFD_Pos;
       
        SYS->P5_MFP |=SYS_MFP_P55_GPIO;
        GPIO_SetMode(P5, BIT5, GPIO_PMD_OUTPUT);
       
        /* set P5.2 to INT1 mode to use the PWM Brake function */
        SYS->P5_MFP |= SYS_MFP_P52_INT1;
               
    /* Lock protected registers */
    SYS_LockReg();
        GPIO_SetMode(P5, BIT2, GPIO_PMD_QUASI);
}


int32_t main (void)
{
    /* Init System, IP clock and multi-function I/O
       In the end of SYS_Init() will issue SYS_LockReg()
       to lock protected register. If user want to write
       protected register, please issue SYS_UnlockReg()
       to unlock protected register if necessary */
    SYS_Init();

    /* Init UART to 115200-8n1 for print message */
    UART_Open(UART, 115200);

        printf("\nThis sample code will output PWM channel 2 (pin 24) to trigger ADC channel 0 (pin 41),\n");
    printf("and setting ADC conversion event source to PWM trigger,\n");
    printf("and setting Brake Function event source to INT1 (pin 20),\n");
        printf("the INT1 interrupt event is seting falling trigger,\n");
        printf("so user need use INT1 pin connect to VCC and removal connect,\n");
        printf("well be generate the brake Flag to STOP PWM waveform\n");       
        printf("**------------------------------------------------------------------------------------**\n");        

        // Enable channel 0
        ADC_Open(ADC, 0, 0, 0x01);

        // Power on ADC
        ADC_POWER_ON(ADC);

        ADC->ADCR |=ADC_ADCR_TRGEN_Msk;
        ADC->ADCR |=ADC_TRIGGER_BY_PWM;
        ADC->ADCR |=ADC_ADCR_ADIE_Msk;

        ADC_CLR_INT_FLAG(ADC, u32Flag);
       
        // Configure and enable Comperator 0 to monitor channel 0 input less than 0x200
        ADC_ENABLE_CMP0(ADC, 0, ADC_CMP_LESS_THAN, 0x200, 16);
        // Configure and enable Comperator 1 to monitor channel 0 input greater or euqal to 0x200
        ADC_ENABLE_CMP1(ADC, 0, ADC_CMP_GREATER_OR_EQUAL_TO, 0x200, 16);       
       
        // Enable ADC comparator 0 and 1 interrupt
    ADC_EnableInt(ADC, ADC_CMP0_INT);
    ADC_EnableInt(ADC, ADC_CMP1_INT);
    NVIC_EnableIRQ(ADC_IRQn);

        //setting counter matching CNR2 trigger ADC
        PWM->TRGCON0 |= 0x00020000;
        PWM_SET_ALIGNED_TYPE(pwm, 2, PWM_CENTER_ALIGNED);
       
    // PWM2 frequency is 300Hz, duty 50%
    PWM_ConfigOutputChannel(PWM, 2, 300, 50);
    PWM_EnableDeadZone(PWM, 2, 200);

    // Enable output of all PWM channels
    PWM_EnableOutput(PWM, 0x3f);
   
    // Enable PWM channel 0 period interrupt, use channel 0 to measure time.
    PWM_EnablePeriodInt(PWM, 2, PWM_PERIOD_INT_MATCH_CNR);
    NVIC_EnableIRQ(PWM_IRQn);            

        //PWM PFBCON: PWMBKO2 Mask
        PWM->PFBCON |= PWM_PFBCON_PWMBKO2_Msk;

        //PWM brake Flag clear
        PWM->PFBCON |= PWM_PFBCON_BKF_Msk;
       
        // PWM BRKIE
        PWM->PIER |= PWM_PIER_BRKIE_Msk;
    PWM->PHCHGNXT |=PWM_PHCHGNXT_CE1_Msk;
       
        // Comparator 0 as fault break 1 source
        PWM->PFBCON |= PWM_FB1_EINT1;
        PWM->PFBCON &= ~PWM_PFBCON_CPO1BKEN_Msk;

        P5->IEN |=0x04;                                                //EN P5.2 INT1 Falling
        NVIC_EnableIRQ(EINT1_IRQn);
       
    // Start
    PWM_Start(PWM, 0x3f);
   
    while(1);

}

/*** (C) COPYRIGHT 2013 Nuvoton Technology Corp. ***/


使用特权

评论回复
598330983| | 2018-12-29 23:41 | 显示全部楼层
这个触发方式功能强大

使用特权

评论回复
wanduzi| | 2018-12-30 19:02 | 显示全部楼层
这个跟定时器触发类似。只不过用的是PWM的定时器

使用特权

评论回复
yiy| | 2018-12-30 19:43 | 显示全部楼层
刹车功能。看看怎么做的。

使用特权

评论回复
yiy| | 2018-12-30 19:48 | 显示全部楼层
PWM功能很强啊

使用特权

评论回复
观海| | 2019-1-8 11:10 | 显示全部楼层
非常感谢楼主分享

使用特权

评论回复
guanjiaer| | 2019-1-8 11:22 | 显示全部楼层
通过外部触发?

使用特权

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

本版积分规则

116

主题

1441

帖子

4

粉丝