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

[复制链接]
1923|8
 楼主| 小灵通2018 发表于 2018-12-26 23:59 | 显示全部楼层 |阅读模式
[Mini51][PWM]PWM_trigger_ADC_and_PWM_Brake_function.zip (417.14 KB, 下载次数: 10)
透过 PWM 触发 ADC ,并且可以用 Brake 功能将 PWM 的波形停止
捉虫天师 发表于 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 | 显示全部楼层

  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. * $Revision: 3 $
  5. * $Date: 13/10/07 3:57p $
  6. * [url=home.php?mod=space&uid=247401]@brief[/url]    PWM sample for Mini51 series MCU
  7. *
  8. * @note
  9. * Copyright (C) 2013 Nuvoton Technology Corp. All rights reserved.
  10. *****************************************************************************/  
  11. #include <stdio.h>
  12. #include "Mini51Series.h"

  13. volatile   uint32_t u32Flag;

  14. void ADC_IRQHandler(void)
  15. {      
  16.     // Get ADC comparator interrupt flag
  17.     u32Flag = ADC_GET_INT_FLAG(ADC, ADC_CMP0_INT | ADC_CMP1_INT);
  18.    
  19.     if(u32Flag & ADC_CMP0_INT)
  20.         printf("Channel 0 input < 0x200\n");
  21.     if(u32Flag & ADC_CMP1_INT)
  22.         printf("Channel 0 input >= 0x200\n");
  23.    
  24.     ADC_CLR_INT_FLAG(ADC, u32Flag);
  25. }

  26. void EINT1_IRQHandler(void)
  27. {
  28.         P55=0;        //debug IO
  29.         printf("INT1");
  30.         P5->ISRC |= 0x04;        //CLR INT1 interrupt Flag
  31.         PWM->PFBCON |= PWM_PFBCON_BKF_Msk;        //CLR Brake Function Flag
  32. }

  33. void PWM_IRQHandler(void)
  34. {
  35.     static uint32_t cnt;
  36.     static uint32_t out;
  37.    
  38.     // Channel 0 frequency is 100Hz, every 1 second enter this IRQ handler 100 times.
  39.     if(++cnt == 100) {
  40.         if(out)
  41.             PWM_EnableOutput(PWM, 0x3F);
  42.         else
  43.             PWM_DisableOutput(PWM, 0x3F);
  44.         out ^= 1;
  45.         cnt = 0;
  46.     }
  47.     // Clear channel 0 period interrupt flag
  48.     PWM_ClearPeriodIntFlag(PWM, 0);
  49.         PWM_ClearADCTriggerFlag(PWM, 0, PWM_TRIGGER_ADC_CNTR_IS_CNR);
  50.         //PWM->PFBCON |= PWM_PFBCON_BKF_Msk;        //CLR Brake Function Flag
  51. }

  52. void SYS_Init(void)
  53. {
  54. /*---------------------------------------------------------------------------------------------------------*/
  55. /* Init System Clock                                                                                       */
  56. /*---------------------------------------------------------------------------------------------------------*/

  57.     /* Unlock protected registers */
  58.     SYS_UnlockReg();

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

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

  63.     /* Enable IP clock */
  64.     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;

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

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


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

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

  82.     /* Set P5.3 to ADC channel 0 input pin */
  83.     SYS->P5_MFP |= SYS_MFP_P53_AIN0;
  84.     /* Analog pin OFFD to prevent leakage */
  85.     P5->OFFD |= (1 << 3) << GPIO_OFFD_OFFD_Pos;
  86.        
  87.         SYS->P5_MFP |=SYS_MFP_P55_GPIO;
  88.         GPIO_SetMode(P5, BIT5, GPIO_PMD_OUTPUT);
  89.        
  90.         /* set P5.2 to INT1 mode to use the PWM Brake function */
  91.         SYS->P5_MFP |= SYS_MFP_P52_INT1;
  92.                
  93.     /* Lock protected registers */
  94.     SYS_LockReg();
  95.         GPIO_SetMode(P5, BIT2, GPIO_PMD_QUASI);
  96. }


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

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

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

  114.         // Enable channel 0
  115.         ADC_Open(ADC, 0, 0, 0x01);

  116.         // Power on ADC
  117.         ADC_POWER_ON(ADC);

  118.         ADC->ADCR |=ADC_ADCR_TRGEN_Msk;
  119.         ADC->ADCR |=ADC_TRIGGER_BY_PWM;
  120.         ADC->ADCR |=ADC_ADCR_ADIE_Msk;

  121.         ADC_CLR_INT_FLAG(ADC, u32Flag);
  122.        
  123.         // Configure and enable Comperator 0 to monitor channel 0 input less than 0x200
  124.         ADC_ENABLE_CMP0(ADC, 0, ADC_CMP_LESS_THAN, 0x200, 16);
  125.         // Configure and enable Comperator 1 to monitor channel 0 input greater or euqal to 0x200
  126.         ADC_ENABLE_CMP1(ADC, 0, ADC_CMP_GREATER_OR_EQUAL_TO, 0x200, 16);       
  127.        
  128.         // Enable ADC comparator 0 and 1 interrupt
  129.     ADC_EnableInt(ADC, ADC_CMP0_INT);
  130.     ADC_EnableInt(ADC, ADC_CMP1_INT);
  131.     NVIC_EnableIRQ(ADC_IRQn);

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

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

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

  147.         //PWM brake Flag clear
  148.         PWM->PFBCON |= PWM_PFBCON_BKF_Msk;
  149.        
  150.         // PWM BRKIE
  151.         PWM->PIER |= PWM_PIER_BRKIE_Msk;
  152.     PWM->PHCHGNXT |=PWM_PHCHGNXT_CE1_Msk;
  153.        
  154.         // Comparator 0 as fault break 1 source
  155.         PWM->PFBCON |= PWM_FB1_EINT1;
  156.         PWM->PFBCON &= ~PWM_PFBCON_CPO1BKEN_Msk;

  157.         P5->IEN |=0x04;                                                //EN P5.2 INT1 Falling
  158.         NVIC_EnableIRQ(EINT1_IRQn);
  159.        
  160.     // Start
  161.     PWM_Start(PWM, 0x3f);
  162.    
  163.     while(1);

  164. }

  165. /*** (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 | 显示全部楼层
通过外部触发?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

160

主题

1735

帖子

4

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