[DemoCode下载] PWM捕获操作

[复制链接]
783|3
 楼主| zhuomuniao110 发表于 2019-5-26 22:45 | 显示全部楼层 |阅读模式
PWM, se, TE, ck
  1. /*---------------------------------------------------------------------------------------------------------*/
  2. /*                                                                                                         */
  3. /* Copyright(c) 2009 Nuvoton Technology Corp. All rights reserved.                                         */
  4. /*                                                                                                         */
  5. /*---------------------------------------------------------------------------------------------------------*/
  6. #include <stdio.h>
  7. #include "M051Series.h"
  8. #include "LCD_Driver.h"


  9. #define PLLCON_SETTING      CLK_PLLCON_50MHz_HXT
  10. #define PLL_CLOCK           50000000


  11. uint32_t g_u32Freq = 0;
  12. uint32_t g_u32DutyCycle = 0;
  13. uint32_t g_u32RisingCnt = 0;
  14. uint32_t g_u32FallingCnt = 0;
  15. char g_strBuf[32] = {0};

  16. void PWMA_IRQHandler(void)
  17. {
  18.     uint32_t u32Reg;

  19.     u32Reg = PWMA->CCR0;

  20.     /* Clear capture interrupt flag */
  21.     PWMA->CCR0 |= PWM_CCR0_CAPIF0_Msk;

  22.     /* Falling edge */
  23.     if(u32Reg & PWM_CCR0_CFLRI0_Msk)
  24.     {
  25.         g_u32FallingCnt = PWMA->CFLR0;
  26.         /* Clear falling event flag */
  27.         PWMA->CCR0 |= PWM_CCR0_CFLRI0_Msk;
  28.     }

  29.     /* Rising edge */
  30.     if(u32Reg & PWM_CCR0_CRLRI0_Msk)
  31.     {
  32.         g_u32RisingCnt = PWMA->CRLR0;
  33.         /* Clear rising event flag */
  34.         PWMA->CCR0 |= PWM_CCR0_CRLRI0_Msk;
  35.     }

  36.     /* Clear PWM0 interrupt flag */
  37.     PWMA->PIIR = PWM_PIIR_PWMIF0_Msk;
  38. }


  39. void SYS_Init(void)
  40. {

  41.     /*---------------------------------------------------------------------------------------------------------*/
  42.     /* Init System Clock                                                                                       */
  43.     /*---------------------------------------------------------------------------------------------------------*/

  44.     /* Enable Internal RC clock */
  45.     CLK->PWRCON |= CLK_PWRCON_OSC22M_EN_Msk;

  46.     /* Waiting for IRC22M clock ready */
  47.     while(!(CLK->CLKSTATUS & CLK_CLKSTATUS_OSC22M_STB_Msk));

  48.     /* Switch HCLK clock source to internal RC */
  49.     CLK->CLKSEL0 &= ~CLK_CLKSEL0_HCLK_S_Msk;
  50.     CLK->CLKSEL0 |= CLK_CLKSEL0_HCLK_S_HIRC;

  51.     /* Set PLL to power down mode and PLL_STB bit in CLKSTATUS register will be cleared by hardware.*/
  52.     CLK->PLLCON |= CLK_PLLCON_PD_Msk;

  53.     /* Enable external 12MHz XTAL */
  54.     CLK->PWRCON |= CLK_PWRCON_XTL12M_EN_Msk;

  55.     /* Enable PLL and Set PLL frequency */
  56.     CLK->PLLCON = PLLCON_SETTING;

  57.     /* Waiting for clock ready */
  58.     while(!(CLK->CLKSTATUS & (CLK_CLKSTATUS_PLL_STB_Msk | CLK_CLKSTATUS_XTL12M_STB_Msk)));

  59.     /* Switch HCLK clock source to PLL, STCLK to HCLK/2 */
  60.     CLK->CLKSEL0 = CLK_CLKSEL0_STCLK_S_HCLK_DIV2 | CLK_CLKSEL0_HCLK_S_PLL;

  61.     /* Enable IP clock */
  62.     CLK->APBCLK = CLK_APBCLK_UART0_EN_Msk | CLK_APBCLK_SPI0_EN_Msk |
  63.                   CLK_APBCLK_PWM01_EN_Msk | CLK_APBCLK_ADC_EN_Msk;
  64.     /* IP clock source */
  65.     CLK->CLKSEL1 = CLK_CLKSEL1_UART_S_PLL | CLK_CLKSEL1_PWM01_S_HCLK;

  66.     /* Update System Core Clock */
  67.     /* User can use SystemCoreClockUpdate() to calculate PllClock, SystemCoreClock and CycylesPerUs automatically. */
  68.     //SystemCoreClockUpdate();
  69.     PllClock        = PLL_CLOCK;            // PLL
  70.     SystemCoreClock = PLL_CLOCK / 1;        // HCLK
  71.     CyclesPerUs     = PLL_CLOCK / 1000000;  // For SYS_SysTickDelay()

  72.     /*---------------------------------------------------------------------------------------------------------*/
  73.     /* Init I/O Multi-function                                                                                 */
  74.     /*---------------------------------------------------------------------------------------------------------*/
  75.     /* Set P3 multi-function pins for UART0 RXD and TXD  */
  76.     SYS->P3_MFP = SYS_MFP_P30_RXD0 | SYS_MFP_P31_TXD0;
  77.     /* Set P1.4, P1.5, P1.6, P1.7 for SPI0 to driver LCD */
  78.     SYS->P1_MFP = SYS_MFP_P14_SPISS0 | SYS_MFP_P15_MOSI_0 | SYS_MFP_P16_MISO_0 | SYS_MFP_P17_SPICLK0;
  79.     /* Set P2.0 => PWM0, P2.1 => PWM1 */
  80.     SYS->P2_MFP = SYS_MFP_P20_PWM0 | SYS_MFP_P21_PWM1;
  81. }


  82. void UART0_Init(void)
  83. {

  84.     /*---------------------------------------------------------------------------------------------------------*/
  85.     /* Init UART                                                                                               */
  86.     /*---------------------------------------------------------------------------------------------------------*/
  87.     UART0->BAUD = UART_BAUD_MODE2 | UART_BAUD_MODE2_DIVIDER(__HXT, 115200);
  88.     UART0->LCR = UART_WORD_LEN_8 | UART_PARITY_NONE | UART_STOP_BIT_1;

  89. }


  90. void PWMA_Init(void)
  91. {
  92.     /* PWM Timer0: clk = HCLK / 2 /  1, Freq = clk / 65536, Max cycles = 65536      */
  93.     /* PWM Timer1: clk = HCLK / 2 / 16, Freq = clk / 1000, duty cycle = 200/1000 % */
  94.     PWM_SET_PRESCALER(PWMA, PWM_CH1, 1);
  95.     PWM_SET_DIVIDER(PWMA, PWM_CH0, PWM_CLK_DIV_1);
  96.     PWM_SET_DIVIDER(PWMA, PWM_CH1, PWM_CLK_DIV_16);

  97.     /* Enable PWM0,1 counter. We must set PWM mode before setting CNR, CMR. */
  98.     PWMA->PCR = PWM_PCR_CH1EN_Msk | PWM_PCR_CH1MOD_Msk |
  99.                 PWM_PCR_CH0EN_Msk | PWM_PCR_CH0MOD_Msk;

  100.     /* Enable PWM0 as input capture mode */
  101.     PWMA->CCR0 = PWM_CCR0_CFLRI0_Msk | PWM_CCR0_CRLRI0_Msk | PWM_CCR0_CAPCH0EN_Msk |
  102.                  PWM_CCR0_CFL_IE0_Msk | PWM_CCR0_CRL_IE0_Msk;

  103.     PWMA->CNR0 = 0xffff;
  104.     PWMA->CMR0 = 0;
  105.     PWMA->CNR1 = 1000 - 1;
  106.     PWMA->CMR1 = 200 - 1;

  107.     /* Enable Interrupt */
  108.     PWMA->PIER = PWM_PIER_PWMIE0_Msk;

  109.     NVIC_EnableIRQ(PWMA_IRQn);

  110.     /* Enable PWM1 Output */
  111.     PWMA->POE = PWM_POE_PWM1_Msk;

  112.     /* Need to make sure PWM timer0 ready before enable capture */
  113.     while(PWMA->PDR0 == 0);

  114.     /* Enable PWM0 Capture */
  115.     PWMA->CAPENR = 1;

  116. }

  117. /*----------------------------------------------------------------------------
  118.   MAIN function
  119.   ----------------------------------------------------------------------------*/
  120. int32_t main(void)
  121. {
  122.     /* Unlock protected registers */
  123.     SYS_UnlockReg();

  124.     /* Init system, IP clock and multi-function I/O */
  125.     SYS_Init();

  126.     /* Lock protected registers */
  127.     SYS_LockReg();

  128.     /* Init UART0 for printf */
  129.     UART0_Init();

  130.     /* Init SPI0 and LCD */
  131.     LCD_Init();
  132.     LCD_EnableBackLight();
  133.     LCD_ClearScreen();

  134.     LCD_Print(0, "IN:P2.0(400~100kHz)");
  135.     LCD_Print(1, "OUT:P2.1(1500Hz)");

  136.     /* Init PWMA channel 0 to be capture mode and channel 1 to be output mode */
  137.     PWMA_Init();

  138.     /*
  139.         PWM timer 0 is set as input capture function.
  140.         PWM0 will down-count from 0xFFFF. When capture rising and falling event, the count value will
  141.         be recorded by g_u32RisingCnt, g_u32FallingCnt in ISR.
  142.         We can use g_u32RisingCnt and g_u32FallingCnt to calculate input frequency and duty cycle.

  143.         PWM timer 1 is set as PWM output.
  144.     */

  145.     while(1)
  146.     {
  147.         uint32_t u32Tmp1, u32Tmp2;
  148.         char strClearFreqVal[15] = "Freq:          ";
  149.         char strClearDutyVal[15] = "Duty:          ";
  150.         u32Tmp1 = (0xFFFF - g_u32RisingCnt); // low interval
  151.         u32Tmp2 = (0xFFFF - g_u32FallingCnt); // high interval
  152.         g_u32Freq =  u32Tmp1 + u32Tmp2;
  153.         if(g_u32Freq)
  154.             g_u32Freq = 24000000 / g_u32Freq;

  155.         if(u32Tmp2 + u32Tmp2)
  156.             g_u32DutyCycle = u32Tmp2 * 200 / (u32Tmp1 + u32Tmp2) + 1 >> 1;


  157.         sprintf(g_strBuf, "Freq:%dHz", g_u32Freq);
  158.         LCD_Print(2, strClearFreqVal);
  159.         LCD_Print(2, g_strBuf);
  160.         sprintf(g_strBuf, "Duty:%d ", g_u32DutyCycle);
  161.         LCD_Print(3, strClearDutyVal);
  162.         g_strBuf[8] = '%';
  163.         LCD_Print(3, g_strBuf);
  164.     }

  165. }




 楼主| zhuomuniao110 发表于 2019-5-26 22:46 | 显示全部楼层
捕获是精准测量的高效手段,学习PWM捕获技术非常关键。
21mengnan 发表于 2019-5-27 19:19 | 显示全部楼层
检测波宽很有用。
equivalent 发表于 2019-5-29 20:37 | 显示全部楼层
PWM应用已经很常见了,有这个会方便很多
您需要登录后才可以回帖 登录 | 注册

本版积分规则

233

主题

3529

帖子

11

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