之前点灯都是用的延时函数,这次用定时器做,为了体现出新唐BSP的好用,关于配置定时器的部分,我们全部使用BSP提供的库函数。
思路:定时器属于片内外设,因此初始化需要完成以下内容:
使能定时器模块的时钟,启用定时器;
设置定时器模块的时钟源,这里要根据你启用了哪些时钟源;
这里我们通过定时器中断来修改一个LED的状态,所以要使能定时器模块的中断功能;
学过51的都知道51单片机对应的中断模块启用后,还要开启总中断,ARM也不例外,
要将启用的定时器中断加入到嵌套向量中断控制器NVIC.类似于开启总中断(其实还是不一样的,我们先这么理解);
然后还要设置定时器运行的模式和中断周期(这里库函数提供的传入参数是频率),最后就是按下启动开关,让定时器运行。
#include"NuMicro.h"
#include<stdio.h>
void SYS_Init(void)
{
/*---------------------------------------------------------------------------------------------------------*/
/* Init System Clock */
/*---------------------------------------------------------------------------------------------------------*/
/* Unlock protected registers */
SYS_UnlockReg();
/* Set XT1_OUT(PF.2) and XT1_IN(PF.3) to input mode */
PF->MODE &= ~(GPIO_MODE_MODE2_Msk | GPIO_MODE_MODE3_Msk);
/* Enable HIRC clock (Internal RC 48 MHz) */
CLK_EnableXtalRC(CLK_PWRCTL_HIRCEN_Msk);
/* Wait for HIRC clock ready */
CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk);
/* Set core clock as 96MHz from PLL */
CLK_SetCoreClock(FREQ_96MHZ);
/* Set PCLK0/PCLK1 to HCLK/2 */
CLK->PCLKDIV = (CLK_PCLKDIV_APB0DIV_DIV2 | CLK_PCLKDIV_APB1DIV_DIV2);
/* Enable UART clock */
CLK_EnableModuleClock(UART0_MODULE);
CLK_EnableModuleClock(TMR0_MODULE);
/* Select UART clock source from HIRC */
CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART0SEL_HIRC, CLK_CLKDIV0_UART0(1));
CLK_SetModuleClock(TMR0_MODULE,CLK_CLKSEL1_TMR0SEL_HIRC,0);
/* Update System Core Clock */
/* User can use SystemCoreClockUpdate() to calculate SystemCoreClock. */
SystemCoreClockUpdate();
/* Set GPB multi-function pins for UART0 RXD and TXD */
SYS->GPB_MFPH = (SYS->GPB_MFPH & ~(SYS_GPB_MFPH_PB12MFP_Msk | SYS_GPB_MFPH_PB13MFP_Msk)) | \
(SYS_GPB_MFPH_PB12MFP_UART0_RXD | SYS_GPB_MFPH_PB13MFP_UART0_TXD);
/* Lock protected registers */
SYS_LockReg();
}
void TMR0_IRQHandler(void)
{
if(TIMER_GetIntFlag(TIMER0) == 1)
{
/* Clear Timer0 time-out interrupt flag */
TIMER_ClearIntFlag(TIMER0);
PB14 ^=1;
}
}
int main(void)
{
int i=0;
SYS_Init();
UART_Open(UART0, 115200);
printf("Hello World\n");
GPIO_SetMode(PB,BIT14,GPIO_MODE_OUTPUT);
PB14=1;
TIMER_Open(TIMER0,TIMER_PERIODIC_MODE,1);
TIMER_EnableInt(TIMER0);
/* Enable Timer0 NVIC */
NVIC_EnableIRQ(TMR0_IRQn);
/* Start Timer0 counting */
TIMER_Start(TIMER0);
while(1)
{
}
}
TIMER_Open(TIMER0,TIMER_PERIODIC_MODE,1);
这里设置的第三个参数是频率,设置为1,那么LED就会以2秒一个周期闪烁,因此1秒修改一次LED的状态。
如果想设置LED以频率1Hz闪烁,那么就将该参数设置为2。
比如我们用串口打印LED的状态
#include"NuMicro.h"
#include<stdio.h>
void SYS_Init(void)
{
/*---------------------------------------------------------------------------------------------------------*/
/* Init System Clock */
/*---------------------------------------------------------------------------------------------------------*/
/* Unlock protected registers */
SYS_UnlockReg();
/* Set XT1_OUT(PF.2) and XT1_IN(PF.3) to input mode */
PF->MODE &= ~(GPIO_MODE_MODE2_Msk | GPIO_MODE_MODE3_Msk);
/* Enable HIRC clock (Internal RC 48 MHz) */
CLK_EnableXtalRC(CLK_PWRCTL_HIRCEN_Msk);
/* Wait for HIRC clock ready */
CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk);
/* Set core clock as 96MHz from PLL */
CLK_SetCoreClock(FREQ_96MHZ);
/* Set PCLK0/PCLK1 to HCLK/2 */
CLK->PCLKDIV = (CLK_PCLKDIV_APB0DIV_DIV2 | CLK_PCLKDIV_APB1DIV_DIV2);
/* Enable UART clock */
CLK_EnableModuleClock(UART0_MODULE);
CLK_EnableModuleClock(TMR0_MODULE);
/* Select UART clock source from HIRC */
CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART0SEL_HIRC, CLK_CLKDIV0_UART0(1));
CLK_SetModuleClock(TMR0_MODULE,CLK_CLKSEL1_TMR0SEL_HIRC,0);
/* Update System Core Clock */
/* User can use SystemCoreClockUpdate() to calculate SystemCoreClock. */
SystemCoreClockUpdate();
/* Set GPB multi-function pins for UART0 RXD and TXD */
SYS->GPB_MFPH = (SYS->GPB_MFPH & ~(SYS_GPB_MFPH_PB12MFP_Msk | SYS_GPB_MFPH_PB13MFP_Msk)) | \
(SYS_GPB_MFPH_PB12MFP_UART0_RXD | SYS_GPB_MFPH_PB13MFP_UART0_TXD);
/* Lock protected registers */
SYS_LockReg();
}
void TMR0_IRQHandler(void)
{
if(TIMER_GetIntFlag(TIMER0) == 1)
{
/* Clear Timer0 time-out interrupt flag */
TIMER_ClearIntFlag(TIMER0);
if(PB14) {PB14=0;printf("LED is ON \n");}
else {PB14=1;printf("LED is OFF \n");}
}
}
int main(void)
{
SYS_Init();
UART_Open(UART0, 115200);
printf("Hello World\n");
GPIO_SetMode(PB,BIT14,GPIO_MODE_OUTPUT);
PB14=1;
TIMER_Open(TIMER0,TIMER_PERIODIC_MODE,1);
TIMER_EnableInt(TIMER0);
/* Enable Timer0 NVIC */
NVIC_EnableIRQ(TMR0_IRQn);
/* Start Timer0 counting */
TIMER_Start(TIMER0);
while(1)
{
}
}
因为库函数传递的参数是整数,因此最小频率是1Hz,如何实现类似0.5Hz这种操作呢,那么就需要在中断里计数了,计数2个后再执行,就可以了。更大周期的以此类推。
#include"NuMicro.h"
#include<stdio.h>
//用于记录中断次数
int val=0;
void SYS_Init(void)
{
/*---------------------------------------------------------------------------------------------------------*/
/* Init System Clock */
/*---------------------------------------------------------------------------------------------------------*/
/* Unlock protected registers */
SYS_UnlockReg();
/* Set XT1_OUT(PF.2) and XT1_IN(PF.3) to input mode */
PF->MODE &= ~(GPIO_MODE_MODE2_Msk | GPIO_MODE_MODE3_Msk);
/* Enable HIRC clock (Internal RC 48 MHz) */
CLK_EnableXtalRC(CLK_PWRCTL_HIRCEN_Msk);
/* Wait for HIRC clock ready */
CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk);
/* Set core clock as 96MHz from PLL */
CLK_SetCoreClock(FREQ_96MHZ);
/* Set PCLK0/PCLK1 to HCLK/2 */
CLK->PCLKDIV = (CLK_PCLKDIV_APB0DIV_DIV2 | CLK_PCLKDIV_APB1DIV_DIV2);
/* Enable UART clock */
CLK_EnableModuleClock(UART0_MODULE);
CLK_EnableModuleClock(TMR0_MODULE);
/* Select UART clock source from HIRC */
CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART0SEL_HIRC, CLK_CLKDIV0_UART0(1));
CLK_SetModuleClock(TMR0_MODULE,CLK_CLKSEL1_TMR0SEL_HIRC,0);
/* Update System Core Clock */
/* User can use SystemCoreClockUpdate() to calculate SystemCoreClock. */
SystemCoreClockUpdate();
/* Set GPB multi-function pins for UART0 RXD and TXD */
SYS->GPB_MFPH = (SYS->GPB_MFPH & ~(SYS_GPB_MFPH_PB12MFP_Msk | SYS_GPB_MFPH_PB13MFP_Msk)) | \
(SYS_GPB_MFPH_PB12MFP_UART0_RXD | SYS_GPB_MFPH_PB13MFP_UART0_TXD);
/* Lock protected registers */
SYS_LockReg();
}
void TMR0_IRQHandler(void)
{
if(TIMER_GetIntFlag(TIMER0) == 1)
{
val++;
/* Clear Timer0 time-out interrupt flag */
TIMER_ClearIntFlag(TIMER0);
//计数5秒后再执行翻转LED命令
if(val==5)
{
val=0;
if(PB14) {PB14=0;printf("LED is ON \n");}
else {PB14=1;printf("LED is OFF \n");}
}
}
}
int main(void)
{
SYS_Init();
UART_Open(UART0, 115200);
printf("Hello World\n");
GPIO_SetMode(PB,BIT14,GPIO_MODE_OUTPUT);
PB14=1;
TIMER_Open(TIMER0,TIMER_PERIODIC_MODE,1);
TIMER_EnableInt(TIMER0);
/* Enable Timer0 NVIC */
NVIC_EnableIRQ(TMR0_IRQn);
/* Start Timer0 counting */
TIMER_Start(TIMER0);
while(1)
{
}
}
以上代码都是经过测试有效的,不在附带图片或动画。
关于4种定时器计时模式,请参考技术手册的说明。
|