[DemoCode下载] 058S的PWM捕获

[复制链接]
 楼主| mintspring 发表于 2017-8-26 21:14 | 显示全部楼层 |阅读模式
  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: 4 $
  5. * $Date: 15/02/06 10:22a $
  6. * [url=home.php?mod=space&uid=247401]@brief[/url]    Capture the PWMA Channel 1 waveform by PWMA Channel 2.
  7. * @note
  8. * Copyright (C) 2014 Nuvoton Technology Corp. All rights reserved.
  9. *
  10. ******************************************************************************/
  11. #include <stdio.h>
  12. #include "M058S.h"

  13. /*---------------------------------------------------------------------------------------------------------*/
  14. /* Macro, type and constant definitions                                                                    */
  15. /*---------------------------------------------------------------------------------------------------------*/

  16. #define PLLCON_SETTING      CLK_PLLCON_50MHz_HXT
  17. #define PLL_CLOCK           50000000

  18. /**
  19. * @brief       PWMA IRQ Handler
  20. *
  21. * @param       None
  22. *
  23. * [url=home.php?mod=space&uid=266161]@return[/url]      None
  24. *
  25. * [url=home.php?mod=space&uid=1543424]@Details[/url]     ISR to handle PWMA interrupt event
  26. */
  27. void PWMA_IRQHandler(void)
  28. {
  29.     uint32_t u32CapIntFlag1;

  30.     /* Handle PWMA Capture function */
  31.     u32CapIntFlag1 = PWMA->CCR2;

  32.     /* PWMA channel 2 Capture interrupt */
  33.     if(u32CapIntFlag1 & PWM_CCR2_CAPIF2_Msk)
  34.     {
  35.         PWMA->CCR2 &= (PWM_CCR_MASK | PWM_CCR2_CAPIF2_Msk);
  36.     }
  37. }

  38. /*--------------------------------------------------------------------------------------*/
  39. /* Capture function to calculate the input waveform information                         */
  40. /* u32Count[4] : Keep the internal counter value when input signal rising / falling     */
  41. /*               happens                                                                */
  42. /*                                                                                      */
  43. /* time    A    B     C     D                                                           */
  44. /*           ___   ___   ___   ___   ___   ___   ___   ___                              */
  45. /*      ____|   |_|   |_|   |_|   |_|   |_|   |_|   |_|   |_____                        */
  46. /* index              0 1   2 3                                                         */
  47. /*                                                                                      */
  48. /* The capture internal counter down count from 0x10000, and reload to 0x10000 after    */
  49. /* input signal falling happens (Time B/C/D)                                            */
  50. /*--------------------------------------------------------------------------------------*/
  51. void CalPeriodTime(PWM_T *PWM, uint32_t u32Ch)
  52. {
  53.     uint16_t u32Count[4];
  54.     uint32_t u32i;
  55.     uint16_t u16RisingTime, u16FallingTime, u16HighPeroid, u16LowPeroid, u16TotalPeroid;

  56.     /* Clear Capture Falling Indicator (Time A) */
  57.     PWM_ClearCaptureIntFlag(PWM, u32Ch, PWM_CAPTURE_INT_FALLING_LATCH);

  58.     /* Wait for Capture Falling Indicator  */
  59.     while(PWM_GetCaptureIntFlag(PWM, u32Ch) < 2);

  60.     /* Clear Capture Falling Indicator (Time B)*/
  61.     PWM_ClearCaptureIntFlag(PWM, u32Ch, PWM_CAPTURE_INT_FALLING_LATCH);

  62.     u32i = 0;

  63.     while(u32i < 4)
  64.     {
  65.         /* Wait for Capture Falling Indicator */
  66.         while(PWM_GetCaptureIntFlag(PWM, u32Ch) < 2);

  67.         /* Clear Capture Falling and Rising Indicator */
  68.         PWM_ClearCaptureIntFlag(PWM, u32Ch, PWM_CAPTURE_INT_FALLING_LATCH | PWM_CAPTURE_INT_RISING_LATCH);

  69.         /* Get Capture Falling Latch Counter Data */
  70.         u32Count[u32i++] = PWM_GET_CAPTURE_FALLING_DATA(PWM, u32Ch);

  71.         /* Wait for Capture Rising Indicator */
  72.         while(PWM_GetCaptureIntFlag(PWM, u32Ch) < 2);

  73.         /* Clear Capture Rising Indicator */
  74.         PWM_ClearCaptureIntFlag(PWM, u32Ch, PWM_CAPTURE_INT_RISING_LATCH);

  75.         /* Get Capture Rising Latch Counter Data */
  76.         u32Count[u32i++] = PWM_GET_CAPTURE_RISING_DATA(PWM, u32Ch);
  77.     }

  78.     u16RisingTime = u32Count[1];

  79.     u16FallingTime = u32Count[0];

  80.     u16HighPeroid = u32Count[1] - u32Count[2];

  81.     u16LowPeroid = 0x10000 - u32Count[1];

  82.     u16TotalPeroid = 0x10000 - u32Count[2];

  83.     printf("\nPWM generate: \nHigh Period=7199 ~ 7201, Low Period=16799 ~ 16801, Total Period=23999 ~ 24001\n");
  84.     printf("\nCapture Result: Rising Time = %d, Falling Time = %d \nHigh Period = %d, Low Period = %d, Total Period = %d.\n\n",
  85.            u16RisingTime, u16FallingTime, u16HighPeroid, u16LowPeroid, u16TotalPeroid);
  86.     if((u16HighPeroid < 7199) || (u16HighPeroid > 7201) || (u16LowPeroid < 16799) || (u16LowPeroid > 16801) || (u16TotalPeroid < 23999) || (u16TotalPeroid > 24001))
  87.         printf("Capture Test Fail!!\n");
  88.     else
  89.         printf("Capture Test Pass!!\n");
  90. }


  91. void SYS_Init(void)
  92. {
  93.     /*---------------------------------------------------------------------------------------------------------*/
  94.     /* Init System Clock                                                                                       */
  95.     /*---------------------------------------------------------------------------------------------------------*/

  96.     /* Enable Internal RC clock */
  97.     CLK->PWRCON |= CLK_PWRCON_OSC22M_EN_Msk;

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

  100.     /* Switch HCLK clock source to Internal RC and HCLK source divide 1 */
  101.     CLK->CLKSEL0 &= ~CLK_CLKSEL0_HCLK_S_Msk;
  102.     CLK->CLKSEL0 |= CLK_CLKSEL0_HCLK_S_HIRC;
  103.     CLK->CLKDIV &= ~CLK_CLKDIV_HCLK_N_Msk;

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

  106.     /* Enable external 12MHz XTAL, internal 22.1184MHz */
  107.     CLK->PWRCON |= CLK_PWRCON_XTL12M_EN_Msk | CLK_PWRCON_OSC22M_EN_Msk;

  108.     /* Enable PLL and Set PLL frequency */
  109.     CLK->PLLCON = PLLCON_SETTING;

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

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

  114.     /* Enable IP clock */
  115.     CLK->APBCLK = CLK_APBCLK_UART0_EN_Msk | CLK_APBCLK_PWM01_EN_Msk | CLK_APBCLK_PWM23_EN_Msk;

  116.     /* IP clock source */
  117.     CLK->CLKSEL1 = CLK_CLKSEL1_UART_S_PLL;

  118.     /* IP clock source */
  119.     CLK->CLKSEL1 |= CLK_CLKSEL1_PWM01_S_HXT | CLK_CLKSEL1_PWM23_S_HXT;

  120.     /* Reset PWMA channel0~channel3 */
  121.     SYS->IPRSTC2 = SYS_IPRSTC2_PWM03_RST_Msk;
  122.     SYS->IPRSTC2 = 0;

  123.     /* Update System Core Clock */
  124.     SystemCoreClockUpdate();

  125.     /*---------------------------------------------------------------------------------------------------------*/
  126.     /* Init I/O Multi-function                                                                                 */
  127.     /*---------------------------------------------------------------------------------------------------------*/
  128.     /* Set P3 multi-function pins for UART RXD and TXD  */
  129.     SYS->P3_MFP = SYS_MFP_P30_RXD | SYS_MFP_P31_TXD;
  130.     /* Set P2 multi-function pins for PWMA Channel 1 and 2 */
  131.     SYS->P2_MFP = SYS_MFP_P21_PWM1 | SYS_MFP_P22_PWM2;
  132. }


  133. void UART0_Init(void)
  134. {

  135.     /*---------------------------------------------------------------------------------------------------------*/
  136.     /* Init UART                                                                                               */
  137.     /*---------------------------------------------------------------------------------------------------------*/
  138.     UART0->BAUD = UART_BAUD_MODE2 | UART_BAUD_MODE2_DIVIDER(PLL_CLOCK, 115200);
  139.     UART0->LCR = UART_WORD_LEN_8 | UART_PARITY_NONE | UART_STOP_BIT_1;
  140. }



  141. /*---------------------------------------------------------------------------------------------------------*/
  142. /*  Main Function                                                                                          */
  143. /*---------------------------------------------------------------------------------------------------------*/
  144. int32_t main(void)
  145. {
  146.     /* Unlock protected registers */
  147.     SYS_UnlockReg();

  148.     /* Init System, IP clock and multi-function I/O */
  149.     SYS_Init();

  150.     /* Lock protected registers */
  151.     SYS_LockReg();

  152.     /* Init UART0 for printf */
  153.     UART0_Init();

  154.     printf("+------------------------------------------------------------------------+\n");
  155.     printf("|                          PWM Driver Sample Code                        |\n");
  156.     printf("|                                                                        |\n");
  157.     printf("+------------------------------------------------------------------------+\n");
  158.     printf("  This sample code will use PWMA channel 2 to capture\n  the signal from PWMA channel 1.\n");
  159.     printf("  I/O configuration:\n");
  160.     printf("    PWM1(P2.1 PWMA channel 1) <--> PWM2(P2.2 PWMA channel 2)\n\n");
  161.     printf("Use PWMA Channel 2(P2.2) to capture the PWMA Channel 1(P2.1) Waveform\n");

  162.     while(1)
  163.     {
  164.         printf("Press any key to start PWM Capture Test\n");
  165.         getchar();

  166.         /*--------------------------------------------------------------------------------------*/
  167.         /* Set the PWMA Channel 1 as PWM output function.                                               */
  168.         /*--------------------------------------------------------------------------------------*/

  169.         /* Assume PWM output frequency is 250Hz and duty ratio is 30%, user can calculate PWM settings by follows.
  170.            duty ratio = (CMR+1)/(CNR+1)
  171.            cycle time = CNR+1
  172.            High level = CMR+1
  173.            PWM clock source frequency = __HXT = 12000000
  174.            (CNR+1) = PWM clock source frequency/prescaler/clock source divider/PWM output frequency
  175.                    = 12000000/2/1/250 = 24000
  176.            (Note: CNR is 16 bits, so if calculated value is larger than 65536, user should increase prescale value.)
  177.            CNR = 23999
  178.            duty ratio = 30% ==> (CMR+1)/(CNR+1) = 30%
  179.            CMR = 7199
  180.            Prescale value is 1 : prescaler= 2
  181.            Clock divider is PWM_CSR_DIV1 : clock divider =1
  182.         */

  183.         /* set PWMA channel 1 output configuration */
  184.         PWM_ConfigOutputChannel(PWMA, PWM_CH1, 250, 30);

  185.         /* Enable PWM Output path for PWMA channel 1 */
  186.         PWM_EnableOutput(PWMA, 0x2);

  187.         /* Enable Timer for PWMA channel 1 */
  188.         PWM_Start(PWMA, 0x2);

  189.         /*--------------------------------------------------------------------------------------*/
  190.         /* Set the PWMA channel 2  for capture function                                         */
  191.         /*--------------------------------------------------------------------------------------*/

  192.         /* If input minimum frequency is 250Hz, user can calculate capture settings by follows.
  193.            Capture clock source frequency = __HXT = 12000000 in the sample code.
  194.            (CNR+1) = Capture clock source frequency/prescaler/clock source divider/minimum input frequency
  195.                    = 12000000/2/1/250 = 24000
  196.            (Note: CNR is 16 bits, so if calculated value is larger than 65536, user should increase prescale value.)
  197.            CNR = 0xFFFF
  198.            (Note: In capture mode, user should set CNR to 0xFFFF to increase capture frequency range.)
  199.         */

  200.         /* set PWMA channel 2 capture configuration */
  201.         PWM_ConfigCaptureChannel(PWMA, PWM_CH2, 166, 0);

  202.         /* Enable capture falling edge interrupt for PWMA channel 2 */
  203.         PWM_EnableCaptureInt(PWMA, PWM_CH2, PWM_CAPTURE_INT_FALLING_LATCH);

  204.         /* Enable PWMA NVIC interrupt */
  205.         NVIC_EnableIRQ((IRQn_Type)(PWMA_IRQn));

  206.         /* Enable Timer for PWMA channel 2  */
  207.         PWM_Start(PWMA, 0x4);

  208.         /* Enable Capture Function for PWMA channel 2 */
  209.         PWM_EnableCapture(PWMA, 0x4);

  210.         /* Wait until PWMA channel 2 Timer start to count */
  211.         while(PWMA->PDR2 == 0);

  212.         /* Capture the Input Waveform Data */
  213.         CalPeriodTime(PWMA, PWM_CH2);
  214.         /*------------------------------------------------------------------------------------------------------*/
  215.         /* Stop PWMA channel 1 (Recommended procedure method 1)                                                 */
  216.         /* Set PWM Timer loaded value(CNR) as 0. When PWM internal counter(PDR) reaches to 0, disable PWM Timer */
  217.         /*------------------------------------------------------------------------------------------------------*/

  218.         /* Set PWMA channel 1 loaded value as 0 */
  219.         PWM_Stop(PWMA, 0x2);

  220.         /* Wait until PWMA channel 1 Timer Stop */
  221.         while(PWMA->PDR1 != 0);

  222.         /* Disable Timer for PWMA channel 1 */
  223.         PWM_ForceStop(PWMA, 0x2);

  224.         /* Disable PWM Output path for PWMA channel 1 */
  225.         PWM_DisableOutput(PWMA, 0x2);

  226.         /*------------------------------------------------------------------------------------------------------*/
  227.         /* Stop PWMA channel 2 (Recommended procedure method 1)                                                 */
  228.         /* Set PWM Timer loaded value(CNR) as 0. When PWM internal counter(PDR) reaches to 0, disable PWM Timer */
  229.         /*------------------------------------------------------------------------------------------------------*/

  230.         /* Disable PWMA NVIC */
  231.         NVIC_DisableIRQ((IRQn_Type)(PWMA_IRQn));

  232.         /* Set loaded value as 0 for PWMA channel 2 */
  233.         PWM_Stop(PWMA, 0x4);

  234.         /* Wait until PWMA channel 2 current counter reach to 0 */
  235.         while(PWMA->PDR2 != 0);

  236.         /* Disable Timer for PWMA channel 2 */
  237.         PWM_ForceStop(PWMA, 0x4);

  238.         /* Disable Capture Function and Capture Input path for  PWMA channel 2*/
  239.         PWM_DisableCapture(PWMA, 0x4);

  240.         /* Clear Capture Interrupt flag for PWMA channel 2*/
  241.         PWM_ClearCaptureIntFlag(PWMA, PWM_CH2, PWM_CAPTURE_INT_FALLING_LATCH);
  242.     }
  243. }





 楼主| mintspring 发表于 2017-8-26 21:23 | 显示全部楼层
 楼主| mintspring 发表于 2017-8-26 21:24 | 显示全部楼层
 楼主| mintspring 发表于 2017-8-26 21:31 | 显示全部楼层
 楼主| mintspring 发表于 2017-8-26 21:39 | 显示全部楼层
/* 选择PWM0时钟源-外部晶振 */
CLKSEL1 = 0;
/* 使能PWM0时钟 */
APBCLK |= PWM01_CLKEN;
/* 选择PWM0时钟预分频 */
PPRA = 9;
/* 选择PWM0时钟分频 */
CSRA = 0x0;
为了能够让LED灯的亮度发生变化,需要调整CNR与CMR之间的关系,它们之间的关系控制着PWM输出引脚高低电平的变化,详细如下:
占空比 = (CMR+1)/(CNR+1)
 CMR >= CNR:PWM输出为高
 CMR < CNR :PWM低脉宽= (CNR-CMR);PWM高脉宽 = (CMR+1)
 CMR = 0 :PWM 低脉宽 = (CNR) ;PWM高脉宽= 1
 楼主| mintspring 发表于 2017-8-26 21:55 | 显示全部楼层
  1. /************************* Copyright (c) 2014 SmartMcu Team *****************************
  2. *项目名称:ARM Cortex-M0
  3. *描    述:PWM 占空比输出 测试
  4. *设    计:SmartMcu Team By Stephen.Wen
  5. *修改日期:2014/3/5
  6. *官    网:www.smartmcu.com
  7. *淘    宝:http://smartmcu.taobao.com/
  8. *说    明:代码来自《ARM Cortex-M0微控制器原理与实践》
  9.                    《ARM Cortex-M0微控制器深度实战》
  10. *******************************************************************************************/

  11. #include "SmartM_M0.h"

  12. /****************************************
  13. *函数名称:PWMInit
  14. *输    入:无
  15. *输    出:无
  16. *功    能:PWM初始化
  17. 默认初始化频率为2500Hz
  18. PWM频率=PWM_CLK/(prescale+1)/(clock divider)/(CNR+1)
  19.        =12000000/10/2/240
  20.        =2500Hz
  21. ******************************************/
  22. VOID PWMInit(VOID)
  23. {
  24.         /* 配置P4.0为推挽输出 */
  25.   P4_MFP &= ~(((1<<8)|(1<<0)));   
  26.   P4_MFP |=   (1<<0) ;      
  27.    
  28.   P4_PMD &= ~Px0_PMD;                       
  29.   P4_PMD |= Px0_OUT;

  30.        
  31.   /* 选择PWM0时钟源-外部晶振 */
  32.   CLKSEL1 = 0;  
  33.   /* 使能PWM0时钟 */       
  34.   APBCLK |= PWM01_CLKEN;
  35.                            
  36.   /* 选择PWM0时钟预分频 */  
  37.   PPRA = 9;   
  38.   /* 选择PWM0时钟分频 */       
  39.   CSRA = 0x0;            
  40.   /* PWM0自动重装载 */       
  41.   PCRA = 0x08 ;                                 
  42.   /* PWM0计数值 */
  43.   CNR0A  = 239;
  44.   /* PWM0比较值 */       
  45.   CMR0A  = 0;               
  46.   /* PWM输出使能 */
  47.   POEA  = 0x0F;   
  48.   /* PWM使能,启动 */       
  49.   PCRA |= 01;                                 
  50. }
  51. /************************************************
  52. *函数名称:PWMOutput
  53. *输    入:pBuf -PWM值
  54. *输    出:无
  55. *功    能:PWM输出占空比控制函数
  56. **************************************************/
  57. VOID PWMOutput(UINT8 ucPMR)
  58. {                                       
  59.                   CMR0A = 255-ucPMR;
  60. }
  61. /****************************************
  62. *函数名称:main
  63. *输    入:无
  64. *输    出:无
  65. *功    能:函数主体
  66. ******************************************/
  67. INT32 main(VOID)
  68. {
  69.           UINT32 i=0;
  70.           /*1.MCU频率初始化,频率为50MHz*/
  71.           McuInit(MCU_FREQUENCY);
  72.           /*2.串口初始化,波特率为115200bps*/
  73.                 UartInit(115200);
  74.           /*3.PWM初始化,频率为2500Hz*/
  75.           PWMInit();
  76.        
  77.           printf("\r\n================================================\r\n");
  78.           printf("\r\n                 PWM Test                       \r\n");
  79.           printf("\r\n          Please watch led brightness           \r\n");
  80.           printf("\r\n================================================\r\n");
  81.        
  82.           while(1)
  83.                 {

  84.                          /* PWM0输出调整 */
  85.                    PWMOutput(i);
  86.                        
  87.                          if(i++>=240)
  88.                          {
  89.                                   i=0;
  90.                          }       
  91.          
  92.        Delayms(20);
  93.                 }
  94. }


 楼主| mintspring 发表于 2017-8-26 21:56 | 显示全部楼层
  1. /************************* Copyright (c) 2014 SmartMcu Team *****************************
  2. *项目名称:ARM Cortex-M0
  3. *描    述:PWM 测量脉宽
  4. *设    计:SmartMcu Team By Stephen.Wen
  5. *修改日期:2014/3/5
  6. *官    网:www.smartmcu.com
  7. *淘    宝:http://smartmcu.taobao.com/
  8. *说    明:代码来自《ARM Cortex-M0微控制器原理与实践》
  9.                    《ARM Cortex-M0微控制器深度实战》
  10. *******************************************************************************************/

  11. #include "SmartM_M0.h"

  12. BOOL g_bPWMIRQ=FALSE;

  13. UINT16 g_usPulseLow, g_usPulseHigh;
  14. UINT8  g_ucCMR=120;

  15. /****************************************
  16. *函数名称:PWMInit
  17. *输    入:无
  18. *输    出:无
  19. *功    能:PWM初始化
  20. PWM频率=PWM_CLK/(prescale+1)/(clock divider)/(CNR+1)
  21.        =12000000/256/16/240
  22.        =7Hz
  23. ******************************************/
  24. VOID PWMInit(VOID)
  25. {
  26.   /* 选择 P4.0,P4.1为PWM0、PWM1 */
  27.   P4_MFP &= ~(((1<<8)|(1<<0)) |((1<<9)|(1<<1)));   
  28.         P4_MFP |=   (1<<0) | (1<<1);
  29.   /* 配置PWM0为双向IO模式,PWM1为推挽输出模式 */   
  30.   P4_PMD &= ~((3<<0) | (3<<2));   
  31.         P4_PMD |=   (3<<0) | (1<<2) ;         
  32.                             
  33.   /* 使能 PWM0,1时钟 */
  34.   APBCLK |= PWM01_CLKEN;  
  35.   /* 选择外部晶振为PWM0,1的时钟源 */       
  36.         CLKSEL1 = (CLKSEL1 & (~PWM01_CLK)) | PWM01_12M;         
  37.   /* PWM0,1 时钟预分频256 */               
  38.   PPRA = 0xFF;   
  39.   /* PWM0~3 时钟分频为16 */       
  40.   CSRA = 0x33 ;     
  41.   /* PWM0自动重载模式 */       
  42.   PCRA |= CH1_AU_RL;
  43.   /* PWM1自动重载模式 */       
  44.         PCRA |= CH0_AU_RL;            
  45.         /* PWM0向下计数寄存器初始值为65535 */
  46.         CNR0A = 0xFFFF;               
  47.    
  48.         CCR0A &= ~INV0_ON;                                             
  49.   CCR0A |= 0;                  
  50.         /* 捕捉器PWM通道0使能 */
  51.         CCR0A |= CAPCH0EN;                                                
  52.         CAPENRA |= CAPCH0_ON;               
  53.   /* PWM通道0中断使能 */                                 
  54.   PIERA |= PWMIE0;     
  55.   /* 使能捕捉下降沿中断 */       
  56.   CCR0A |= CFL_IE0;                       
  57.   /* 使能捕捉上升沿沿中断 */       
  58.         CCR0A |= CRL_IE0;                               
  59.   /* 使能PWM0~3中断 */       
  60.         NVIC_ISER |= PWMA_INT;              
  61.   /* PWM1向下计数寄存器240 */
  62.         CNR1A = 239;                        
  63.         CMR1A = 0;
  64.   /* PWM1输出使能 */
  65.   POEA = PWM1_OE;   
  66.   /* 使能PWM1向下计数 */       
  67.   PCRA |= CH1EN;       
  68.   /* 使能PWM0向下计数 */       
  69.         PCRA |= CH0EN;                                 
  70. }
  71. /****************************************
  72. *函数名称:PWMEnable
  73. *输    入:无
  74. *输    出:无
  75. *功    能:PWM使能
  76. ******************************************/
  77. VOID PWMEnable(VOID)
  78. {
  79.   POEA = PWM1_OE;                     
  80.   PCRA |= CH1EN;                                                        
  81.         PCRA |= CH0EN;                                 
  82.        
  83. }
  84. /****************************************
  85. *函数名称:PWMEnable
  86. *输    入:无
  87. *输    出:无
  88. *功    能:PWM禁止
  89. ******************************************/
  90. VOID PWMDisable(VOID)
  91. {
  92.   POEA &= ~PWM1_OE;                     
  93.   PCRA &= ~CH1EN;                                                        
  94.         PCRA &= ~CH0EN;               
  95.        
  96. }
  97. /****************************************
  98. *函数名称:PWMOutput
  99. *输    入:m -PWM1比较值
  100. *输    出:无
  101. *功    能:PWM输出调整
  102. ******************************************/
  103. VOID PWMOutput(UINT8 m)
  104. {
  105.            CMR1A = m;       
  106. }
  107. /****************************************
  108. *函数名称:KeyInit
  109. *输    入:无
  110. *输    出:无
  111. *功    能:按键初始化
  112. ******************************************/
  113. VOID KeyInit(VOID)
  114. {
  115.         /* 外部中断0初始化 */
  116.         P3_MFP = (P3_MFP & (~P32_EINT0_MCLK)) | EINT0;  //P3.2引脚设置为外部中断
  117.         P3_IMD  &=  IMD2_EDG;                               
  118.         P3_IEN  |=  IF_EN2;                                                                                                                   //设置外部中断0为低电平/下降沿触发
  119.         NVIC_ISER |= EXT_INT0;
  120.        
  121.         /* 外部中断1初始化 */
  122.         P3_MFP = (P3_MFP & (~P33_EINT1_MCLK)) | EINT1;  //P3.3引脚设置为外部中断
  123.         P3_IMD &= IMD3_EDG;                               
  124.         P3_IEN |= IF_EN3;                                                                                                                           //设置外部中断1为低电平或下降沿触发
  125.         NVIC_ISER |= EXT_INT1;       
  126. }
  127. /****************************************
  128. *函数名称:PWMA_IRQHandler
  129. *输    入:无
  130. *输    出:无
  131. *功    能:PWMA中断服务函数
  132. ******************************************/
  133. VOID PWMA_IRQHandler(VOID)
  134. {
  135.         UINT32  sta;
  136.        
  137.         sta = CCR0A;
  138.         /* 写"1"清零 */
  139.   CCR0A |= CAPIF0;                 
  140.   /* 计算低电平脉宽 */  
  141.   g_usPulseLow = CNR0A - CRLR0A;  
  142.   /* 计算高电平脉宽 */       
  143.   g_usPulseHigh = CNR0A - CFLR0A;  
  144.   /* 出现下降沿,表示PWM输出一个周期完成 */   
  145.   if (sta & CFLRI0)               
  146.         {
  147.                   g_bPWMIRQ = TRUE;
  148.                
  149.         }
  150. }
  151. /****************************************
  152. *函数名称:EINT0_IRQHandler
  153. *输    入:无
  154. *输    出:无
  155. *功    能:外部中断0服务函数
  156. ******************************************/
  157. VOID EINT0_IRQHandler(VOID)
  158. {                  
  159.    if(g_ucCMR<=239)
  160.          {
  161.                   g_ucCMR++;
  162.          }
  163.          
  164.          PWMOutput(g_ucCMR);
  165.          
  166.          printf("+");
  167.          Delayms(100);
  168.    P3_ISRC |= 1<<2;                //写1清空
  169. }
  170. /****************************************
  171. *函数名称:EINT1_IRQHandler
  172. *输    入:无
  173. *输    出:无
  174. *功    能:外部中断1服务函数
  175. ******************************************/
  176. VOID EINT1_IRQHandler(VOID)
  177. {                  
  178.    if(g_ucCMR>0)
  179.          {
  180.                   g_ucCMR--;
  181.          }
  182.          
  183.          PWMOutput(g_ucCMR);
  184.          
  185.          printf("-");
  186.          Delayms(100);
  187.          P3_ISRC |= 1<<3;                //写1清空
  188. }

  189. /****************************************
  190. *函数名称:main
  191. *输    入:无
  192. *输    出:无
  193. *功    能:函数主体
  194. ******************************************/
  195. INT32 main(VOID)
  196. {
  197.           /*1.MCU频率初始化,频率为50MHz*/
  198.           McuInit(MCU_FREQUENCY);
  199.           /*2.串口初始化,波特率为115200bps*/
  200.                 UartInit(115200);
  201.        
  202.           printf("\r\n================================================\r\n");
  203.           printf("\r\n            PWM Measure Pulse Test               \r\n");
  204.           printf("\r\n          Please Connect P4.0和P4.1             \r\n");
  205.                 printf("\r\n            Key1:'+'   Key2:'-'                 \r\n");
  206.           printf("\r\n================================================\r\n");
  207.        
  208.           /*3.PWM初始化,频率为7Hz*/
  209.           PWMInit();
  210.           /*4.调整脉宽,占空比50%*/
  211.           PWMOutput(g_ucCMR);       
  212.        
  213.           KeyInit();
  214.        
  215.           while(1)
  216.                 {
  217.                                  if(g_bPWMIRQ)
  218.                                  {
  219.                                           g_bPWMIRQ = FALSE;
  220.                                          
  221.                                           printf("High Pulse = %d,Low Pulse = %d\r\n",
  222.                                                   g_usPulseHigh,
  223.                                                   g_usPulseLow);
  224.                                          
  225.                                           Delayms(500);
  226.                                          
  227.                                  }
  228.                 }
  229. }
 楼主| mintspring 发表于 2017-8-26 21:56 | 显示全部楼层
  1. /************************* Copyright (c) 2014 SmartMcu Team *****************************
  2. *项目名称:ARM Cortex-M0
  3. *描    述:PWM 测量频率
  4. *设    计:SmartMcu Team By Stephen.Wen
  5. *修改日期:2014/3/5
  6. *官    网:www.smartmcu.com
  7. *淘    宝:http://smartmcu.taobao.com/
  8. *说    明:代码来自《ARM Cortex-M0微控制器原理与实践》
  9.                    《ARM Cortex-M0微控制器深度实战》
  10. *******************************************************************************************/

  11. #include "SmartM_M0.h"

  12. BOOL g_bPWMIRQ=FALSE;

  13. UINT16  g_usPulseHigh,g_usPulseLow;

  14. UINT32  g_unPWMCount=0;

  15. UINT8   g_ucCMR=120;

  16. BOOL    g_bKey1=FALSE;
  17. BOOL    g_bKey2=FALSE;


  18. /****************************************
  19. *函数名称:PWMInit
  20. *输    入:无
  21. *输    出:无
  22. *功    能:PWM初始化
  23. 默认初始化频率为2500Hz
  24. PWM频率=PWM_CLK/(prescale+1)/(clock divider)/(CNR+1)
  25.        =12000000/10/2/240
  26.        =2500Hz
  27. ******************************************/
  28. VOID PWMInit(VOID)
  29. {

  30.   /* 选择 P4.0,P4.1为PWM0、PWM1 */
  31.   P4_MFP &= ~(((1<<8)|(1<<0)) |((1<<9)|(1<<1)));   
  32.         P4_MFP |=   (1<<0) | (1<<1);
  33.   /* 配置PWM0为双向IO模式,PWM1为推挽输出模式 */   
  34.   P4_PMD &= ~((3<<0) | (3<<2));   
  35.         P4_PMD |=   (3<<0) | (1<<2) ;         
  36.                             
  37.   /* 使能 PWM0,1时钟 */
  38.   APBCLK |= PWM01_CLKEN;  
  39.   /* 选择外部晶振为PWM0,1的时钟源 */       
  40.         CLKSEL1 = (CLKSEL1 & (~PWM01_CLK)) | PWM01_12M;         
  41.   /* PWM0,1 时钟预分频10 */               
  42.   PPRA = 9;   
  43.   /* PWM0~1 时钟分频为2 */       
  44.   CSRA = 0 ;     
  45.   /* PWM0自动重载模式 */       
  46.   PCRA |= CH1_AU_RL;
  47.   /* PWM1自动重载模式 */       
  48.         PCRA |= CH0_AU_RL;            
  49.         /* PWM0向下计数寄存器初始值为65535 */
  50.         CNR0A = 0xFFFF;               
  51.    
  52.         CCR0A &= ~INV0_ON;                                             
  53.   CCR0A |= 0;                  
  54.         /* 捕捉器PWM通道0使能 */
  55.         CCR0A |= CAPCH0EN;                                                
  56.         CAPENRA |= CAPCH0_ON;               
  57.   /* PWM通道0中断使能 */                                 
  58.   PIERA |= PWMIE0;     
  59.   /* 使能捕捉下降沿中断 */       
  60.   CCR0A |= CFL_IE0;                       
  61.   /* 使能捕捉上升沿中断 */       
  62.         CCR0A |= CRL_IE0;                               
  63.   /* 使能PWM0~3中断 */       
  64.         NVIC_ISER |= PWMA_INT;              
  65.   /* PWM1向下计数寄存器240 */
  66.         CNR1A = 239;                        
  67.         CMR1A = 0;
  68.   /* PWM1输出使能 */
  69.   POEA = PWM1_OE;   
  70.   /* 使能PWM1向下计数 */       
  71.   PCRA |= CH1EN;       
  72.   /* 使能PWM0向下计数 */       
  73.         PCRA |= CH0EN;                                 
  74.                  
  75. }
  76. /****************************************
  77. *函数名称:PWMEnable
  78. *输    入:无
  79. *输    出:无
  80. *功    能:PWM使能
  81. ******************************************/
  82. VOID PWMEnable(VOID)
  83. {                  
  84.   PCRA |= CH1EN;                                                        
  85.         PCRA |= CH0EN;                                 
  86.        
  87. }
  88. /****************************************
  89. *函数名称:PWMEnable
  90. *输    入:无
  91. *输    出:无
  92. *功    能:PWM禁止
  93. ******************************************/
  94. VOID PWMDisable(VOID)
  95. {                    
  96.   PCRA &= ~CH1EN;                                                        
  97.         PCRA &= ~CH0EN;               
  98.        
  99. }
  100. /****************************************
  101. *函数名称:PWMOutput
  102. *输    入:m -调整分频值
  103. *输    出:无
  104. *功    能:PWM输出调整
  105. ******************************************/
  106. VOID PWMOutput(UINT8 m)
  107. {
  108.            CNR1A = m;       
  109. }
  110. /****************************************
  111. *函数名称:TMR0Init
  112. *输    入:无
  113. *输    出:无
  114. *功    能:定时器0初始化
  115. ******************************************/
  116. VOID TMR0Init(VOID)
  117. {
  118.   PROTECT_REG
  119.         (
  120.                 /* 使能TMR0时钟源 */
  121.           APBCLK |= TMR0_CLKEN;
  122.                 /* 选择TMR0时钟源为外部晶振12MHz */  
  123.                 CLKSEL1 = (CLKSEL1 & (~TM0_CLK)) | TM0_12M;        
  124.        
  125.                 /* 复位TMR0 */
  126.                 IPRSTC2 |=  TMR0_RST;
  127.                 IPRSTC2 &= ~TMR0_RST;
  128.        
  129.                 /* 选择TMR0的工作模式为周期模式*/       
  130.                 TCSR0 &= ~TMR_MODE;
  131.                 TCSR0 |=  MODE_PERIOD;               
  132.                
  133.                 /* 溢出周期 = (Period of timer clock input) * (8-bit Prescale + 1) * (24-bit TCMP)*/
  134.                 TCSR0  = TCSR0 & 0xFFFFFF00;                // 设置预分频值 [0~255]
  135.                 TCMPR0 = 12000*1000;                                      // 设置比较值 [0~16777215]

  136.                 TCSR0 |= TMR_IE;                                               //使能TMR0中断
  137.                 NVIC_ISER |= TMR0_INT;       
  138.        
  139.                 TCSR0 |= CRST;                                                       //复位TMR0计数器                               
  140.                 TCSR0 |= CEN;                                                         //使能TMR0
  141.         )
  142. }

  143. /****************************************
  144. *函数名称:KeyInit
  145. *输    入:无
  146. *输    出:无
  147. *功    能:按键初始化
  148. ******************************************/
  149. VOID KeyInit(VOID)
  150. {
  151.         /* 外部中断0初始化 */
  152.         P3_MFP = (P3_MFP & (~P32_EINT0_MCLK)) | EINT0;  //P3.2引脚设置为外部中断
  153.         P3_IMD  &=  IMD2_EDG;                               
  154.         P3_IEN  |=  IF_EN2;                                                                                                                   //设置外部中断0为低电平/下降沿触发
  155.         NVIC_ISER |= EXT_INT0;
  156.        
  157.         /* 外部中断1初始化 */
  158.         P3_MFP = (P3_MFP & (~P33_EINT1_MCLK)) | EINT1;  //P3.3引脚设置为外部中断
  159.         P3_IMD &= IMD3_EDG;                               
  160.         P3_IEN |= IF_EN3;                                                                                                                           //设置外部中断1为低电平或下降沿触发
  161.         NVIC_ISER |= EXT_INT1;       
  162. }
  163. /****************************************
  164. *函数名称:PWMA_IRQHandler
  165. *输    入:无
  166. *输    出:无
  167. *功    能:PWMA中断服务函数
  168. ******************************************/
  169. VOID PWMA_IRQHandler(VOID)
  170. {
  171.         UINT32  sta;
  172.        
  173.         sta = CCR0A;
  174.         /* 写"1"清零 */
  175.   CCR0A |= CAPIF0;                 
  176.   /* 计算低电平脉宽 */  
  177.   g_usPulseLow = CNR0A - CRLR0A;  
  178.   /* 计算高电平脉宽 */       
  179.   g_usPulseHigh = CNR0A - CFLR0A;  
  180.   /* 出现下降沿,表示PWM输出一个周期完成 */   
  181.   if (sta & CFLRI0)               
  182.         {
  183.                   g_bPWMIRQ = TRUE;
  184.                
  185.         }
  186. }
  187. /****************************************
  188. *函数名称:EINT0_IRQHandler
  189. *输    入:无
  190. *输    出:无
  191. *功    能:外部中断0服务函数
  192. ******************************************/
  193. VOID EINT0_IRQHandler(VOID)
  194. {                  
  195.          UINT32 l=0;
  196.        
  197.    if(g_ucCMR>0)
  198.          {
  199.                   g_ucCMR--;
  200.          }
  201.          
  202.          printf("+\r\n");
  203.          
  204.          /* 调整PWM1输出频率 */
  205.          PWMOutput(g_ucCMR);
  206.                
  207.          /* 计算并显示PWM1输出频率 */
  208.          l=12000000/10/2/(g_ucCMR+1);
  209.          
  210.          printf("[PWM1]输出频率:%dHz\r\n",l);       
  211.          
  212.    P3_ISRC |= 1<<2;                //写1清空
  213. }
  214. /****************************************
  215. *函数名称:EINT1_IRQHandler
  216. *输    入:无
  217. *输    出:无
  218. *功    能:外部中断1服务函数
  219. ******************************************/
  220. VOID EINT1_IRQHandler(VOID)
  221. {                  
  222.          UINT32 l=0;
  223.        
  224.    if(g_ucCMR<239)
  225.          {
  226.                   g_ucCMR++;
  227.          }
  228.          
  229.          printf("-\r\n");
  230.          /* 调整PWM1输出频率 */
  231.          PWMOutput(g_ucCMR);
  232.                
  233.          /* 计算并显示PWM1输出频率 */
  234.          l=12000000/10/2/(g_ucCMR+1);
  235.          
  236.          printf("[PWM1]输出频率:%dHz\r\n",l);         

  237.          P3_ISRC |= 1<<3;                //写1清空
  238. }
  239. /****************************************
  240. *函数名称:TMR0_IRQHandler
  241. *输    入:无
  242. *输    出:无
  243. *功    能:定时器0中断服务函数
  244. ******************************************/
  245. VOID TMR0_IRQHandler(VOID)
  246. {
  247.         PWMDisable();
  248.        
  249.   TCSR0 &=~CEN;//禁止TMR0
  250.        
  251.         /* 显示PWM0捕获频率 */
  252.         printf("[PWM0]捕获频率:%dHz\r\n",g_unPWMCount);

  253.         g_unPWMCount=0;
  254.        
  255.         /* 清除TMR1中断标志位 */
  256.         TISR0 |= TMR_TIF;
  257.         TCSR0 |= CRST;                //复位TMR0计数器                               
  258.         TCSR0 |= CEN;                        //使能TMR0
  259.        
  260.         PWMEnable();
  261. }
  262. /****************************************
  263. *函数名称:main
  264. *输    入:无
  265. *输    出:无
  266. *功    能:函数主体
  267. ******************************************/
  268. INT32 main(VOID)
  269. {
  270.           /*1.MCU频率初始化,频率为50MHz*/
  271.           McuInit(MCU_FREQUENCY);
  272.           /*2.串口初始化,波特率为115200bps*/
  273.                 UartInit(115200);
  274.        
  275.           printf("\r\n================================================\r\n");
  276.           printf("\r\n            PWM Measure Frequency Test          \r\n");
  277.           printf("\r\n          Please Connect P4.0和P4.1             \r\n");
  278.                 printf("\r\n            Key1:'+'   Key2:'-'                 \r\n");
  279.           printf("\r\n================================================\r\n");
  280.        
  281.           /*3.PWM初始化,频率为7Hz*/
  282.           PWMInit();
  283.           /*4.调整脉宽,占空比50%*/
  284.           PWMOutput(g_ucCMR);       
  285.           /*5.按键初始化*/
  286.           KeyInit();
  287.           /*6.定时器初始化*/
  288.           TMR0Init();
  289.        
  290.           while(1)
  291.                 {
  292.                        
  293.                          
  294.                                 /*   检测PWM0捕获中断 */
  295.                                 if(g_bPWMIRQ)
  296.                                 {
  297.                                          g_bPWMIRQ=FALSE;
  298.                                        
  299.                                          /*   保存计数值*/
  300.                                          g_unPWMCount+=g_usPulseHigh;
  301.                                        
  302.                                          g_usPulseHigh=0;
  303.                                        
  304.                                 }
  305.                 }
  306. }
wahahaheihei 发表于 2017-8-26 22:59 | 显示全部楼层
没想到PWM还可以捕获,明天学习学习。
捉虫天师 发表于 2017-8-27 19:37 | 显示全部楼层
刚入门的我,来看看能学点啥。
dongnanxibei 发表于 2017-8-27 21:08 | 显示全部楼层
PWM的功能真强大,看来我只会其中一种啊。
lss1985 发表于 2017-9-5 10:32 | 显示全部楼层
(CLK->CLKSEL1 & (CLK_CLKSEL1_PWM01_S_Msk << (u32ChannelNum >> 1))) >> (CLK_CLKSEL1_PWM01_S_Pos << (u32ChannelNum >> 1))
这句话好难
huangcunxiake 发表于 2017-9-5 23:05 | 显示全部楼层
还是新塘单片机好用啊。
huangcunxiake 发表于 2017-9-5 23:07 | 显示全部楼层
lss1985 发表于 2017-9-5 10:32
(CLK->CLKSEL1 & (CLK_CLKSEL1_PWM01_S_Msk > 1))) >> (CLK_CLKSEL1_PWM01_S_Pos > 1))
这句话好难

哈哈,这复杂的位组合运算,看了呕吐
zhuotuzi 发表于 2017-9-6 20:46 | 显示全部楼层
捕获脉冲宽度吗
ysdx06010302 发表于 2017-9-7 08:46 | 显示全部楼层
定时器也有捕获,定时器的捕获和PWM的捕获有啥区别?
谢谢
huahuagg 发表于 2017-9-8 23:41 来自手机 | 显示全部楼层
睡觉前来学习一下。定时器应该是捕获频率,pwm捕获脉冲宽度
huahuagg 发表于 2017-9-8 23:42 来自手机 | 显示全部楼层
ysdx06010302 发表于 2017-9-7 08:46
定时器也有捕获,定时器的捕获和PWM的捕获有啥区别?
谢谢

我觉得一个是捕获频率的,一个是捕获脉冲宽度的
734774645 发表于 2017-9-12 22:47 | 显示全部楼层
有些寄存器起名字难以记住。
天灵灵地灵灵 发表于 2017-9-13 23:05 | 显示全部楼层
正在努力学习这些内容呢。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

302

主题

4963

帖子

24

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