[技术问答]

新唐M051能输出的最高的PWM频率是多少?

[复制链接]
2094|4
手机看帖
扫描二维码
随时随地手机跟帖
zhcxq|  楼主 | 2016-5-19 10:34 | 显示全部楼层 |阅读模式
如题,新唐M051能输出的最高的PWM频率是多少?假设PWM的分辩率为256级,M051的晶振为外部12M,PWM时钟使用内部倍频后的时钟50M,由于分频寄存器最小需要为1,为0时PWM不工作,时钟至少要2分频,所以能输出的最高频率为:50M/2/256=97656.25HZ,我这么理解对不对?
以前接触的其它单片机,可以不必分频,如果频率一样,能输出的PWM频率能高一些。
huangcunxiake| | 2016-5-20 09:52 | 显示全部楼层
你理解的很对,就是这么个回事。

使用特权

评论回复
玛尼玛尼哄| | 2016-5-31 22:02 | 显示全部楼层
#include "PWM.h"
#define EN_EXT_OSC       0
#define COMPLEMENT_MODE         0x00000020
#define DEAD_ZONE_INTERVAL      0xC8FF0000
#define PWM_ENABLE              0x01010101

#if     EN_EXT_OSC
#define PWM_CLOCK_SOURCE        0x00000000  //使用外部振荡12MHz
#else  
#define PWM_CLOCK_SOURCE        0xF0000000  //使用内部RC振荡22.1184MHz
#endif
#define PWM_PRESCALAE           0x0000C731  //PWM01预分频0x31(49),PWM23预分频0xC7(199)
#define PWM_CLOCK_DIVIDER       0x00004444  //输入时钟分频1
#define PWM_OUTPUT_INVERT       0x00040000
#define PWM_OUTPUT_ENABLE       0x0000000F   //PWM0、1、2、3输出使能
#define PWM_CMR_VALUE   0x0
#define PWM_CNR_VALUE       0x1000      //4096
/*
PWM频率=PWMxy_CLK/(prescale+1)*(clock divider)/(CNR+1)
(1)使用外部晶振12MHz
PWM频率=12000000/(49+1)*4097 =58.57Hz
(2)使用内部RC振荡22.1184MHz
PWM频率=22118400/(49+1)*4097 =107.97Hz
*/
#define LED_DARKING             0
#define LED_BRIGHTING   1
STATIC UINT32 g_unPWMCMRValue=PWM_CNR_VALUE;
STATIC UINT32 g_unLedStat=LED_DARKING;
/****************************************
*函数名称:PWMInit
*输    入:无
*输    出:无
*功    能:PWM初始化
******************************************/
VOID PWMInit(VOID)
{
    P2_MFP |= ~(P20_AD8_PWM0 | P21_AD9_PWM1 | P22_AD10_PWM2 | P23_AD11_PWM3);
P2_MFP |= (PWM0 | PWM1 | PWM2 | PWM3);   //使能P2.0~P2.3为PWM输出   
    P2_PMD &= ~Px0_PMD;                       //配置P2.0~P2.3为推挽输出
P2_PMD |= Px0_OUT;
P2_PMD &= ~Px1_PMD;
P2_PMD |= Px1_OUT;
P2_PMD &= ~Px2_PMD;
P2_PMD |= Px2_OUT;
P2_PMD &= ~Px3_PMD;
P2_PMD |= Px3_OUT;
    APBCLK |= PWM01_CLKEN | PWM23_CLKEN;                        //使能PWM0~3时钟
CLKSEL1 = PWM_CLOCK_SOURCE;                 //选择PWM0~3时钟源
   
PPRA = PWM_PRESCALAE | DEAD_ZONE_INTERVAL;                  //选择PWM0~3时钟预分频和死区间隔
    CSRA = PWM_CLOCK_DIVIDER;                                   //选择PWM0~3时钟分频
    PCRA = 0x08080808 | PWM_OUTPUT_INVERT | COMPLEMENT_MODE;    //PWM0~3自动重装载
    CNR0A = CNR1A = CNR2A = CNR3A = PWM_CNR_VALUE;              //PWM0~3计数值
    CMR0A = CMR1A = CMR2A = CMR3A = PWM_CMR_VALUE;              //PWM0~3比较值
    PIERA  |= PWMIE3 | PWMIE2 | PWMIE1 | PWMIE0 ;    //使能PWM0~3中断
    NVIC_ISER |= PWMA_INT;                                      //使能PWM0~3中断
    POEA = PWM_OUTPUT_ENABLE;                                   //PWM输出使能
    PCRA |= PWM_ENABLE;                                         //PWM使能,启动
}
/****************************************
*函数名称:PWMA_IRQHandler
*输    入:无
*输    出:无
*功    能:中断服务函数-PWMA
******************************************/
VOID PWMA_IRQHandler(VOID)
{
  switch(g_unLedStat)            //检查LED状态
  {
   case  LED_DARKING:         //LED状态渐暗
  {
    if(g_unPWMCMRValue < PWM_CNR_VALUE)
    {
     g_unPWMCMRValue+=50;
    }
    else
    {
       g_unLedStat = LED_BRIGHTING;
     g_unPWMCMRValue=PWM_CNR_VALUE;
    }  
  }break;
  case  LED_BRIGHTING:         //LED状态渐亮
  {
    if(g_unPWMCMRValue>=50)
    {
     g_unPWMCMRValue-=50;
    }
    else
    {
       g_unLedStat = LED_DARKING;
     g_unPWMCMRValue=PWM_CMR_VALUE;   
    }
  }break;
  default:break;  
  }
  CMR0A = CMR1A = CMR2A = CMR3A = g_unPWMCMRValue;  //设置PWM0~3比较值
     PIIRA = PIIRA;                           
}
/****************************************
*函数名称:main
*输    入:无
*输    出:无
*功    能:函数主体
******************************************/
INT32 main(VOID)
{
   PROTECT_REG                         //ISP下载时保护FLASH存储器
  (
   PWRCON |= XTL12M_EN;                   //默认时钟源为外部晶振
   while((CLKSTATUS & XTL12M_STB) == 0);                //等待12MHz时钟稳定  
   CLKSEL0 = (CLKSEL0 & (~HCLK)) | HCLK_12M;              //设置外部晶振为系统时钟
   PWMInit();              //PWM初始化
  )
     while(1);
}

使用特权

评论回复
玛尼玛尼哄| | 2016-5-31 22:03 | 显示全部楼层
/*********************************************************************************************
程序名:  PWM实验   用PWM制作呼吸灯
编写人:  闪闪发光的金子
编写时间:2014年2月21日
硬件支持:M0516LNB 12MHz晶体
接口说明:    P2.0接LED正极
---------------------------------------------------

#include <stdio.h>
#include <M051Series.h>
#define PLLCON_SETTING      SYSCLK_PLLCON_50MHz_XTAL
#define PLL_CLOCK           50000000

    uint16_t g_u16PWMValue;
   
void SYS_Init(void)
{
/*---------------------------------------------------------------------------------------------------------*/
/* Init System Clock                                                                                       */
/*---------------------------------------------------------------------------------------------------------*/
    /* Unlock protected registers */
    SYS_UnlockReg();

    /* Enable External XTAL (4~24 MHz) */
    SYSCLK->PWRCON |= SYSCLK_PWRCON_XTL12M_EN_Msk;

    /* Waiting for 12MHz clock ready */
    SYS_WaitingForClockReady( SYSCLK_CLKSTATUS_XTL12M_STB_Msk);

    /* Switch HCLK clock source to XTAL */
    SYSCLK->CLKSEL0 = SYSCLK_CLKSEL0_HCLK_XTAL;

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

    /* Set PLL frequency */        
    SYSCLK->PLLCON = PLLCON_SETTING;

    /* Waiting for clock ready */
    SYS_WaitingForClockReady(SYSCLK_CLKSTATUS_PLL_STB_Msk);

    /* Switch HCLK clock source to PLL */
    SYSCLK->CLKSEL0 = SYSCLK_CLKSEL0_HCLK_PLL;

    /* Enable IP clock */
    //设置PWM0、PWM1的时钟源      
    SYSCLK->APBCLK = SYSCLK_APBCLK_PWM01_EN_Msk;

    /* Select IP clock source */
    SYSCLK->CLKSEL1 = SYSCLK_CLKSEL1_PWM01_XTAL;

    /* Reset PWMB channel0~channel3 */                    
    SYS->IPRSTC2 = SYS_IPRSTC2_PWM47_RST_Msk;                    
    SYS->IPRSTC2 = 0;      


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

/*---------------------------------------------------------------------------------------------------------*/
/* Init I/O Multi-function                                                                                 */
/*---------------------------------------------------------------------------------------------------------*/
    /* P2.0 for PWM0 */
    SYS->P2_MFP = SYS_MFP_P20_PWM0 ;



    /* Lock protected registers */
    SYS_LockReg();
}
void PWMA_Init(void)
{
    //配置预分频器 (PPR)
    PWMA->PPR = PWM_PPR_CP01(30) ;
    //配置时钟选择器(CSR)
    PWMA->CSR = PWM_CSR_CSR0(PWM_CSR_DIV16);

    /* Enable PWM0  counter. We must set PWM mode before setting CNR, CMR. */
    //如果设置PWM_PCR_CH0MOD_AUTO_RELOAD ,当PWM计数器达到0,自动重载CNR0的值到PWM计数器
    PWMA->PCR = PWM_PCR_CH0EN_Msk | PWM_PCR_CH0MOD_AUTO_RELOAD;

    //频率计算公式
    /* PWM0 = 12000000 / 30 / 16 / 200 =    125Hz */
        PWMA->CNR0= 200;   //配置PWM计数器寄存器 (CNR) 设定PWM周期
    PWMA->CMR0= 100;   //配置比较器寄存器(CMR) 设定PWM占空比

    /* Enable PWM channle 0  Output */
    //配置相应的GPIO管脚为PWM功能(使能 POE 和禁用CAPENR).
    PWMA->POE = PWM_POE_PWM0_Msk;
}


int main(void)
{
    uint16_t i,j;
    SYS_Init();
    PWMA_Init();
    while(1)
    {
      //下面有小到大 然后由大到小 循环改变占空比大小,LED灯就会慢慢变亮,然后又慢慢变暗。
      //注意CMR的值不能大于CNR
        for (g_u16PWMValue = 1;g_u16PWMValue<200;g_u16PWMValue++)   
        {      
            PWMA->CMR0 = g_u16PWMValue;
            for(i=0;i<500;i++)  //延时
                for(j=0;j<100;j++);
        }
        for (g_u16PWMValue = 199;g_u16PWMValue>0;g_u16PWMValue--)   
        {      
            PWMA->CMR0 = g_u16PWMValue;
            for(i=0;i<500;i++)  //延时
                for(j=0;j<100;j++);
        }
    }
}

使用特权

评论回复
huangcunxiake| | 2016-5-31 22:56 | 显示全部楼层
没算过这个值,不知道数据手册提供了没。

使用特权

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

本版积分规则

4

主题

14

帖子

0

粉丝