之前点灯都是用的延时函数,这次用定时器做,为了体现出新唐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种定时器计时模式,请参考技术手册的说明。
|