打印
[DemoCode下载]

新唐M051学习之(3)-PWM

[复制链接]
1760|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
cowboy2014|  楼主 | 2015-11-2 20:28 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
今天学习PWM,把M051的手册中关于PWM的那一章反反复复看了好几遍,还是看的云里雾里,最后竟然看的打起盹来。后来觉的差不多了,打算动手写个呼吸灯程序,巩固一下学习成果。
      顾名思义,灯光在微电脑控制之下完成由亮到暗又由暗变亮的逐渐变化,感觉像是在呼吸。
      LED等插在P2.0口上(PWM0) 。如下图。



/*********************************************************************************************

沙发
cowboy2014|  楼主 | 2015-11-2 20:28 | 只看该作者
/*********************************************************************************************
程序名:  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++);
        }
    }
}

使用特权

评论回复
板凳
mintspring| | 2015-11-3 09:39 | 只看该作者
功能很简单,配置很复杂,初始化一大堆代码。

使用特权

评论回复
地板
史迪威将军| | 2015-11-6 21:10 | 只看该作者
有没有简单的方法呢?

使用特权

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

本版积分规则

78

主题

821

帖子

5

粉丝