[DemoCode下载]

058S的PWM捕获

[复制链接]
1250|23
手机看帖
扫描二维码
随时随地手机跟帖
mintspring|  楼主 | 2017-8-26 21:14 | 显示全部楼层 |阅读模式
/**************************************************************************//**
* [url=home.php?mod=space&uid=288409]@file[/url]     main.c
* [url=home.php?mod=space&uid=895143]@version[/url]  V1.00
* $Revision: 4 $
* $Date: 15/02/06 10:22a $
* [url=home.php?mod=space&uid=247401]@brief[/url]    Capture the PWMA Channel 1 waveform by PWMA Channel 2.
* @note
* Copyright (C) 2014 Nuvoton Technology Corp. All rights reserved.
*
******************************************************************************/
#include <stdio.h>
#include "M058S.h"

/*---------------------------------------------------------------------------------------------------------*/
/* Macro, type and constant definitions                                                                    */
/*---------------------------------------------------------------------------------------------------------*/

#define PLLCON_SETTING      CLK_PLLCON_50MHz_HXT
#define PLL_CLOCK           50000000

/**
* @brief       PWMA IRQ Handler
*
* @param       None
*
* [url=home.php?mod=space&uid=266161]@return[/url]      None
*
* [url=home.php?mod=space&uid=1543424]@Details[/url]     ISR to handle PWMA interrupt event
*/
void PWMA_IRQHandler(void)
{
    uint32_t u32CapIntFlag1;

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

    /* PWMA channel 2 Capture interrupt */
    if(u32CapIntFlag1 & PWM_CCR2_CAPIF2_Msk)
    {
        PWMA->CCR2 &= (PWM_CCR_MASK | PWM_CCR2_CAPIF2_Msk);
    }
}

/*--------------------------------------------------------------------------------------*/
/* Capture function to calculate the input waveform information                         */
/* u32Count[4] : Keep the internal counter value when input signal rising / falling     */
/*               happens                                                                */
/*                                                                                      */
/* time    A    B     C     D                                                           */
/*           ___   ___   ___   ___   ___   ___   ___   ___                              */
/*      ____|   |_|   |_|   |_|   |_|   |_|   |_|   |_|   |_____                        */
/* index              0 1   2 3                                                         */
/*                                                                                      */
/* The capture internal counter down count from 0x10000, and reload to 0x10000 after    */
/* input signal falling happens (Time B/C/D)                                            */
/*--------------------------------------------------------------------------------------*/
void CalPeriodTime(PWM_T *PWM, uint32_t u32Ch)
{
    uint16_t u32Count[4];
    uint32_t u32i;
    uint16_t u16RisingTime, u16FallingTime, u16HighPeroid, u16LowPeroid, u16TotalPeroid;

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

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

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

    u32i = 0;

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

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

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

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

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

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

    u16RisingTime = u32Count[1];

    u16FallingTime = u32Count[0];

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

    u16LowPeroid = 0x10000 - u32Count[1];

    u16TotalPeroid = 0x10000 - u32Count[2];

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


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

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

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

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

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

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

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

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

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

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

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

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

    /* Reset PWMA channel0~channel3 */
    SYS->IPRSTC2 = SYS_IPRSTC2_PWM03_RST_Msk;
    SYS->IPRSTC2 = 0;

    /* Update System Core Clock */
    SystemCoreClockUpdate();

    /*---------------------------------------------------------------------------------------------------------*/
    /* Init I/O Multi-function                                                                                 */
    /*---------------------------------------------------------------------------------------------------------*/
    /* Set P3 multi-function pins for UART RXD and TXD  */
    SYS->P3_MFP = SYS_MFP_P30_RXD | SYS_MFP_P31_TXD;
    /* Set P2 multi-function pins for PWMA Channel 1 and 2 */
    SYS->P2_MFP = SYS_MFP_P21_PWM1 | SYS_MFP_P22_PWM2;
}


void UART0_Init(void)
{

    /*---------------------------------------------------------------------------------------------------------*/
    /* Init UART                                                                                               */
    /*---------------------------------------------------------------------------------------------------------*/
    UART0->BAUD = UART_BAUD_MODE2 | UART_BAUD_MODE2_DIVIDER(PLL_CLOCK, 115200);
    UART0->LCR = UART_WORD_LEN_8 | UART_PARITY_NONE | UART_STOP_BIT_1;
}



/*---------------------------------------------------------------------------------------------------------*/
/*  Main Function                                                                                          */
/*---------------------------------------------------------------------------------------------------------*/
int32_t main(void)
{
    /* Unlock protected registers */
    SYS_UnlockReg();

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

    /* Lock protected registers */
    SYS_LockReg();

    /* Init UART0 for printf */
    UART0_Init();

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

    while(1)
    {
        printf("Press any key to start PWM Capture Test\n");
        getchar();

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

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

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

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

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

        /*--------------------------------------------------------------------------------------*/
        /* Set the PWMA channel 2  for capture function                                         */
        /*--------------------------------------------------------------------------------------*/

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

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

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

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

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

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

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

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

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

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

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

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

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

        /* Disable PWMA NVIC */
        NVIC_DisableIRQ((IRQn_Type)(PWMA_IRQn));

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

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

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

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

        /* Clear Capture Interrupt flag for PWMA channel 2*/
        PWM_ClearCaptureIntFlag(PWMA, PWM_CH2, PWM_CAPTURE_INT_FALLING_LATCH);
    }
}





mintspring|  楼主 | 2017-8-26 21:23 | 显示全部楼层
00.png

使用特权

评论回复
mintspring|  楼主 | 2017-8-26 21:24 | 显示全部楼层
01.png

使用特权

评论回复
mintspring|  楼主 | 2017-8-26 21:31 | 显示全部楼层
QQ截图20170826213054.png

使用特权

评论回复
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 | 显示全部楼层
/************************* Copyright (c) 2014 SmartMcu Team *****************************
*项目名称:ARM Cortex-M0
*描    述:PWM 占空比输出 测试
*设    计:SmartMcu Team By Stephen.Wen
*修改日期:2014/3/5
*官    网:www.smartmcu.com
*淘    宝:http://smartmcu.taobao.com/
*说    明:代码来自《ARM Cortex-M0微控制器原理与实践》
                   《ARM Cortex-M0微控制器深度实战》
*******************************************************************************************/

#include "SmartM_M0.h"

/****************************************
*函数名称:PWMInit
*输    入:无
*输    出:无
*功    能:PWM初始化
默认初始化频率为2500Hz
PWM频率=PWM_CLK/(prescale+1)/(clock divider)/(CNR+1)
       =12000000/10/2/240
       =2500Hz
******************************************/
VOID PWMInit(VOID)
{
        /* 配置P4.0为推挽输出 */
  P4_MFP &= ~(((1<<8)|(1<<0)));   
  P4_MFP |=   (1<<0) ;      
   
  P4_PMD &= ~Px0_PMD;                       
  P4_PMD |= Px0_OUT;

       
  /* 选择PWM0时钟源-外部晶振 */
  CLKSEL1 = 0;  
  /* 使能PWM0时钟 */       
  APBCLK |= PWM01_CLKEN;
                           
  /* 选择PWM0时钟预分频 */  
  PPRA = 9;   
  /* 选择PWM0时钟分频 */       
  CSRA = 0x0;            
  /* PWM0自动重装载 */       
  PCRA = 0x08 ;                                 
  /* PWM0计数值 */
  CNR0A  = 239;
  /* PWM0比较值 */       
  CMR0A  = 0;               
  /* PWM输出使能 */
  POEA  = 0x0F;   
  /* PWM使能,启动 */       
  PCRA |= 01;                                 
}
/************************************************
*函数名称:PWMOutput
*输    入:pBuf -PWM值
*输    出:无
*功    能:PWM输出占空比控制函数
**************************************************/
VOID PWMOutput(UINT8 ucPMR)
{                                       
                  CMR0A = 255-ucPMR;
}
/****************************************
*函数名称:main
*输    入:无
*输    出:无
*功    能:函数主体
******************************************/
INT32 main(VOID)
{
          UINT32 i=0;
          /*1.MCU频率初始化,频率为50MHz*/
          McuInit(MCU_FREQUENCY);
          /*2.串口初始化,波特率为115200bps*/
                UartInit(115200);
          /*3.PWM初始化,频率为2500Hz*/
          PWMInit();
       
          printf("\r\n================================================\r\n");
          printf("\r\n                 PWM Test                       \r\n");
          printf("\r\n          Please watch led brightness           \r\n");
          printf("\r\n================================================\r\n");
       
          while(1)
                {

                         /* PWM0输出调整 */
                   PWMOutput(i);
                       
                         if(i++>=240)
                         {
                                  i=0;
                         }       
         
       Delayms(20);
                }
}


使用特权

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

#include "SmartM_M0.h"

BOOL g_bPWMIRQ=FALSE;

UINT16 g_usPulseLow, g_usPulseHigh;
UINT8  g_ucCMR=120;

/****************************************
*函数名称:PWMInit
*输    入:无
*输    出:无
*功    能:PWM初始化
PWM频率=PWM_CLK/(prescale+1)/(clock divider)/(CNR+1)
       =12000000/256/16/240
       =7Hz
******************************************/
VOID PWMInit(VOID)
{
  /* 选择 P4.0,P4.1为PWM0、PWM1 */
  P4_MFP &= ~(((1<<8)|(1<<0)) |((1<<9)|(1<<1)));   
        P4_MFP |=   (1<<0) | (1<<1);
  /* 配置PWM0为双向IO模式,PWM1为推挽输出模式 */   
  P4_PMD &= ~((3<<0) | (3<<2));   
        P4_PMD |=   (3<<0) | (1<<2) ;         
                            
  /* 使能 PWM0,1时钟 */
  APBCLK |= PWM01_CLKEN;  
  /* 选择外部晶振为PWM0,1的时钟源 */       
        CLKSEL1 = (CLKSEL1 & (~PWM01_CLK)) | PWM01_12M;         
  /* PWM0,1 时钟预分频256 */               
  PPRA = 0xFF;   
  /* PWM0~3 时钟分频为16 */       
  CSRA = 0x33 ;     
  /* PWM0自动重载模式 */       
  PCRA |= CH1_AU_RL;
  /* PWM1自动重载模式 */       
        PCRA |= CH0_AU_RL;            
        /* PWM0向下计数寄存器初始值为65535 */
        CNR0A = 0xFFFF;               
   
        CCR0A &= ~INV0_ON;                                             
  CCR0A |= 0;                  
        /* 捕捉器PWM通道0使能 */
        CCR0A |= CAPCH0EN;                                                
        CAPENRA |= CAPCH0_ON;               
  /* PWM通道0中断使能 */                                 
  PIERA |= PWMIE0;     
  /* 使能捕捉下降沿中断 */       
  CCR0A |= CFL_IE0;                       
  /* 使能捕捉上升沿沿中断 */       
        CCR0A |= CRL_IE0;                               
  /* 使能PWM0~3中断 */       
        NVIC_ISER |= PWMA_INT;              
  /* PWM1向下计数寄存器240 */
        CNR1A = 239;                        
        CMR1A = 0;
  /* PWM1输出使能 */
  POEA = PWM1_OE;   
  /* 使能PWM1向下计数 */       
  PCRA |= CH1EN;       
  /* 使能PWM0向下计数 */       
        PCRA |= CH0EN;                                 
}
/****************************************
*函数名称:PWMEnable
*输    入:无
*输    出:无
*功    能:PWM使能
******************************************/
VOID PWMEnable(VOID)
{
  POEA = PWM1_OE;                     
  PCRA |= CH1EN;                                                        
        PCRA |= CH0EN;                                 
       
}
/****************************************
*函数名称:PWMEnable
*输    入:无
*输    出:无
*功    能:PWM禁止
******************************************/
VOID PWMDisable(VOID)
{
  POEA &= ~PWM1_OE;                     
  PCRA &= ~CH1EN;                                                        
        PCRA &= ~CH0EN;               
       
}
/****************************************
*函数名称:PWMOutput
*输    入:m -PWM1比较值
*输    出:无
*功    能:PWM输出调整
******************************************/
VOID PWMOutput(UINT8 m)
{
           CMR1A = m;       
}
/****************************************
*函数名称:KeyInit
*输    入:无
*输    出:无
*功    能:按键初始化
******************************************/
VOID KeyInit(VOID)
{
        /* 外部中断0初始化 */
        P3_MFP = (P3_MFP & (~P32_EINT0_MCLK)) | EINT0;  //P3.2引脚设置为外部中断
        P3_IMD  &=  IMD2_EDG;                               
        P3_IEN  |=  IF_EN2;                                                                                                                   //设置外部中断0为低电平/下降沿触发
        NVIC_ISER |= EXT_INT0;
       
        /* 外部中断1初始化 */
        P3_MFP = (P3_MFP & (~P33_EINT1_MCLK)) | EINT1;  //P3.3引脚设置为外部中断
        P3_IMD &= IMD3_EDG;                               
        P3_IEN |= IF_EN3;                                                                                                                           //设置外部中断1为低电平或下降沿触发
        NVIC_ISER |= EXT_INT1;       
}
/****************************************
*函数名称:PWMA_IRQHandler
*输    入:无
*输    出:无
*功    能:PWMA中断服务函数
******************************************/
VOID PWMA_IRQHandler(VOID)
{
        UINT32  sta;
       
        sta = CCR0A;
        /* 写"1"清零 */
  CCR0A |= CAPIF0;                 
  /* 计算低电平脉宽 */  
  g_usPulseLow = CNR0A - CRLR0A;  
  /* 计算高电平脉宽 */       
  g_usPulseHigh = CNR0A - CFLR0A;  
  /* 出现下降沿,表示PWM输出一个周期完成 */   
  if (sta & CFLRI0)               
        {
                  g_bPWMIRQ = TRUE;
               
        }
}
/****************************************
*函数名称:EINT0_IRQHandler
*输    入:无
*输    出:无
*功    能:外部中断0服务函数
******************************************/
VOID EINT0_IRQHandler(VOID)
{                  
   if(g_ucCMR<=239)
         {
                  g_ucCMR++;
         }
         
         PWMOutput(g_ucCMR);
         
         printf("+");
         Delayms(100);
   P3_ISRC |= 1<<2;                //写1清空
}
/****************************************
*函数名称:EINT1_IRQHandler
*输    入:无
*输    出:无
*功    能:外部中断1服务函数
******************************************/
VOID EINT1_IRQHandler(VOID)
{                  
   if(g_ucCMR>0)
         {
                  g_ucCMR--;
         }
         
         PWMOutput(g_ucCMR);
         
         printf("-");
         Delayms(100);
         P3_ISRC |= 1<<3;                //写1清空
}

/****************************************
*函数名称:main
*输    入:无
*输    出:无
*功    能:函数主体
******************************************/
INT32 main(VOID)
{
          /*1.MCU频率初始化,频率为50MHz*/
          McuInit(MCU_FREQUENCY);
          /*2.串口初始化,波特率为115200bps*/
                UartInit(115200);
       
          printf("\r\n================================================\r\n");
          printf("\r\n            PWM Measure Pulse Test               \r\n");
          printf("\r\n          Please Connect P4.0和P4.1             \r\n");
                printf("\r\n            Key1:'+'   Key2:'-'                 \r\n");
          printf("\r\n================================================\r\n");
       
          /*3.PWM初始化,频率为7Hz*/
          PWMInit();
          /*4.调整脉宽,占空比50%*/
          PWMOutput(g_ucCMR);       
       
          KeyInit();
       
          while(1)
                {
                                 if(g_bPWMIRQ)
                                 {
                                          g_bPWMIRQ = FALSE;
                                         
                                          printf("High Pulse = %d,Low Pulse = %d\r\n",
                                                  g_usPulseHigh,
                                                  g_usPulseLow);
                                         
                                          Delayms(500);
                                         
                                 }
                }
}

使用特权

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

#include "SmartM_M0.h"

BOOL g_bPWMIRQ=FALSE;

UINT16  g_usPulseHigh,g_usPulseLow;

UINT32  g_unPWMCount=0;

UINT8   g_ucCMR=120;

BOOL    g_bKey1=FALSE;
BOOL    g_bKey2=FALSE;


/****************************************
*函数名称:PWMInit
*输    入:无
*输    出:无
*功    能:PWM初始化
默认初始化频率为2500Hz
PWM频率=PWM_CLK/(prescale+1)/(clock divider)/(CNR+1)
       =12000000/10/2/240
       =2500Hz
******************************************/
VOID PWMInit(VOID)
{

  /* 选择 P4.0,P4.1为PWM0、PWM1 */
  P4_MFP &= ~(((1<<8)|(1<<0)) |((1<<9)|(1<<1)));   
        P4_MFP |=   (1<<0) | (1<<1);
  /* 配置PWM0为双向IO模式,PWM1为推挽输出模式 */   
  P4_PMD &= ~((3<<0) | (3<<2));   
        P4_PMD |=   (3<<0) | (1<<2) ;         
                            
  /* 使能 PWM0,1时钟 */
  APBCLK |= PWM01_CLKEN;  
  /* 选择外部晶振为PWM0,1的时钟源 */       
        CLKSEL1 = (CLKSEL1 & (~PWM01_CLK)) | PWM01_12M;         
  /* PWM0,1 时钟预分频10 */               
  PPRA = 9;   
  /* PWM0~1 时钟分频为2 */       
  CSRA = 0 ;     
  /* PWM0自动重载模式 */       
  PCRA |= CH1_AU_RL;
  /* PWM1自动重载模式 */       
        PCRA |= CH0_AU_RL;            
        /* PWM0向下计数寄存器初始值为65535 */
        CNR0A = 0xFFFF;               
   
        CCR0A &= ~INV0_ON;                                             
  CCR0A |= 0;                  
        /* 捕捉器PWM通道0使能 */
        CCR0A |= CAPCH0EN;                                                
        CAPENRA |= CAPCH0_ON;               
  /* PWM通道0中断使能 */                                 
  PIERA |= PWMIE0;     
  /* 使能捕捉下降沿中断 */       
  CCR0A |= CFL_IE0;                       
  /* 使能捕捉上升沿中断 */       
        CCR0A |= CRL_IE0;                               
  /* 使能PWM0~3中断 */       
        NVIC_ISER |= PWMA_INT;              
  /* PWM1向下计数寄存器240 */
        CNR1A = 239;                        
        CMR1A = 0;
  /* PWM1输出使能 */
  POEA = PWM1_OE;   
  /* 使能PWM1向下计数 */       
  PCRA |= CH1EN;       
  /* 使能PWM0向下计数 */       
        PCRA |= CH0EN;                                 
                 
}
/****************************************
*函数名称:PWMEnable
*输    入:无
*输    出:无
*功    能:PWM使能
******************************************/
VOID PWMEnable(VOID)
{                  
  PCRA |= CH1EN;                                                        
        PCRA |= CH0EN;                                 
       
}
/****************************************
*函数名称:PWMEnable
*输    入:无
*输    出:无
*功    能:PWM禁止
******************************************/
VOID PWMDisable(VOID)
{                    
  PCRA &= ~CH1EN;                                                        
        PCRA &= ~CH0EN;               
       
}
/****************************************
*函数名称:PWMOutput
*输    入:m -调整分频值
*输    出:无
*功    能:PWM输出调整
******************************************/
VOID PWMOutput(UINT8 m)
{
           CNR1A = m;       
}
/****************************************
*函数名称:TMR0Init
*输    入:无
*输    出:无
*功    能:定时器0初始化
******************************************/
VOID TMR0Init(VOID)
{
  PROTECT_REG
        (
                /* 使能TMR0时钟源 */
          APBCLK |= TMR0_CLKEN;
                /* 选择TMR0时钟源为外部晶振12MHz */  
                CLKSEL1 = (CLKSEL1 & (~TM0_CLK)) | TM0_12M;        
       
                /* 复位TMR0 */
                IPRSTC2 |=  TMR0_RST;
                IPRSTC2 &= ~TMR0_RST;
       
                /* 选择TMR0的工作模式为周期模式*/       
                TCSR0 &= ~TMR_MODE;
                TCSR0 |=  MODE_PERIOD;               
               
                /* 溢出周期 = (Period of timer clock input) * (8-bit Prescale + 1) * (24-bit TCMP)*/
                TCSR0  = TCSR0 & 0xFFFFFF00;                // 设置预分频值 [0~255]
                TCMPR0 = 12000*1000;                                      // 设置比较值 [0~16777215]

                TCSR0 |= TMR_IE;                                               //使能TMR0中断
                NVIC_ISER |= TMR0_INT;       
       
                TCSR0 |= CRST;                                                       //复位TMR0计数器                               
                TCSR0 |= CEN;                                                         //使能TMR0
        )
}

/****************************************
*函数名称:KeyInit
*输    入:无
*输    出:无
*功    能:按键初始化
******************************************/
VOID KeyInit(VOID)
{
        /* 外部中断0初始化 */
        P3_MFP = (P3_MFP & (~P32_EINT0_MCLK)) | EINT0;  //P3.2引脚设置为外部中断
        P3_IMD  &=  IMD2_EDG;                               
        P3_IEN  |=  IF_EN2;                                                                                                                   //设置外部中断0为低电平/下降沿触发
        NVIC_ISER |= EXT_INT0;
       
        /* 外部中断1初始化 */
        P3_MFP = (P3_MFP & (~P33_EINT1_MCLK)) | EINT1;  //P3.3引脚设置为外部中断
        P3_IMD &= IMD3_EDG;                               
        P3_IEN |= IF_EN3;                                                                                                                           //设置外部中断1为低电平或下降沿触发
        NVIC_ISER |= EXT_INT1;       
}
/****************************************
*函数名称:PWMA_IRQHandler
*输    入:无
*输    出:无
*功    能:PWMA中断服务函数
******************************************/
VOID PWMA_IRQHandler(VOID)
{
        UINT32  sta;
       
        sta = CCR0A;
        /* 写"1"清零 */
  CCR0A |= CAPIF0;                 
  /* 计算低电平脉宽 */  
  g_usPulseLow = CNR0A - CRLR0A;  
  /* 计算高电平脉宽 */       
  g_usPulseHigh = CNR0A - CFLR0A;  
  /* 出现下降沿,表示PWM输出一个周期完成 */   
  if (sta & CFLRI0)               
        {
                  g_bPWMIRQ = TRUE;
               
        }
}
/****************************************
*函数名称:EINT0_IRQHandler
*输    入:无
*输    出:无
*功    能:外部中断0服务函数
******************************************/
VOID EINT0_IRQHandler(VOID)
{                  
         UINT32 l=0;
       
   if(g_ucCMR>0)
         {
                  g_ucCMR--;
         }
         
         printf("+\r\n");
         
         /* 调整PWM1输出频率 */
         PWMOutput(g_ucCMR);
               
         /* 计算并显示PWM1输出频率 */
         l=12000000/10/2/(g_ucCMR+1);
         
         printf("[PWM1]输出频率:%dHz\r\n",l);       
         
   P3_ISRC |= 1<<2;                //写1清空
}
/****************************************
*函数名称:EINT1_IRQHandler
*输    入:无
*输    出:无
*功    能:外部中断1服务函数
******************************************/
VOID EINT1_IRQHandler(VOID)
{                  
         UINT32 l=0;
       
   if(g_ucCMR<239)
         {
                  g_ucCMR++;
         }
         
         printf("-\r\n");
         /* 调整PWM1输出频率 */
         PWMOutput(g_ucCMR);
               
         /* 计算并显示PWM1输出频率 */
         l=12000000/10/2/(g_ucCMR+1);
         
         printf("[PWM1]输出频率:%dHz\r\n",l);         

         P3_ISRC |= 1<<3;                //写1清空
}
/****************************************
*函数名称:TMR0_IRQHandler
*输    入:无
*输    出:无
*功    能:定时器0中断服务函数
******************************************/
VOID TMR0_IRQHandler(VOID)
{
        PWMDisable();
       
  TCSR0 &=~CEN;//禁止TMR0
       
        /* 显示PWM0捕获频率 */
        printf("[PWM0]捕获频率:%dHz\r\n",g_unPWMCount);

        g_unPWMCount=0;
       
        /* 清除TMR1中断标志位 */
        TISR0 |= TMR_TIF;
        TCSR0 |= CRST;                //复位TMR0计数器                               
        TCSR0 |= CEN;                        //使能TMR0
       
        PWMEnable();
}
/****************************************
*函数名称:main
*输    入:无
*输    出:无
*功    能:函数主体
******************************************/
INT32 main(VOID)
{
          /*1.MCU频率初始化,频率为50MHz*/
          McuInit(MCU_FREQUENCY);
          /*2.串口初始化,波特率为115200bps*/
                UartInit(115200);
       
          printf("\r\n================================================\r\n");
          printf("\r\n            PWM Measure Frequency Test          \r\n");
          printf("\r\n          Please Connect P4.0和P4.1             \r\n");
                printf("\r\n            Key1:'+'   Key2:'-'                 \r\n");
          printf("\r\n================================================\r\n");
       
          /*3.PWM初始化,频率为7Hz*/
          PWMInit();
          /*4.调整脉宽,占空比50%*/
          PWMOutput(g_ucCMR);       
          /*5.按键初始化*/
          KeyInit();
          /*6.定时器初始化*/
          TMR0Init();
       
          while(1)
                {
                       
                         
                                /*   检测PWM0捕获中断 */
                                if(g_bPWMIRQ)
                                {
                                         g_bPWMIRQ=FALSE;
                                       
                                         /*   保存计数值*/
                                         g_unPWMCount+=g_usPulseHigh;
                                       
                                         g_usPulseHigh=0;
                                       
                                }
                }
}

使用特权

评论回复
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 | 显示全部楼层
正在努力学习这些内容呢。

使用特权

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

本版积分规则

281

主题

4801

帖子

23

粉丝