今天學習PWM,把M051的手冊中關于PWM的那一章反反復復看了好幾遍,還是看的云里霧里,最后竟然看的打起盹來。后來覺的差不多了,打算動手寫個呼吸燈程序,鞏固一下學習成果。
顧名思義,燈光在微電腦控制之下完成由亮到暗又由暗變亮的逐漸變化,感覺像是在呼吸。
LED等插在P2.0口上(PWM0) 。如下圖。

/*********************************************************************************************
程序名: 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++);
}
}
}
|