[DemoCode下载] 最新M471K系列单片机开发板测评:定时器库函数超好用

[复制链接]
1643|2
 楼主| gaoyang9992006 发表于 2021-9-12 19:14 | 显示全部楼层 |阅读模式
之前点灯都是用的延时函数,这次用定时器做,为了体现出新唐BSP的好用,关于配置定时器的部分,我们全部使用BSP提供的库函数。
思路:定时器属于片内外设,因此初始化需要完成以下内容:
使能定时器模块的时钟,启用定时器;
设置定时器模块的时钟源,这里要根据你启用了哪些时钟源;

这里我们通过定时器中断来修改一个LED的状态,所以要使能定时器模块的中断功能;
学过51的都知道51单片机对应的中断模块启用后,还要开启总中断,ARM也不例外,
要将启用的定时器中断加入到嵌套向量中断控制器NVIC.类似于开启总中断(其实还是不一样的,我们先这么理解);
然后还要设置定时器运行的模式和中断周期(这里库函数提供的传入参数是频率),最后就是按下启动开关,让定时器运行。
  1. #include"NuMicro.h"
  2. #include<stdio.h>

  3. void SYS_Init(void)
  4. {
  5.     /*---------------------------------------------------------------------------------------------------------*/
  6.     /* Init System Clock                                                                                       */
  7.     /*---------------------------------------------------------------------------------------------------------*/
  8.     /* Unlock protected registers */
  9.     SYS_UnlockReg();

  10.     /* Set XT1_OUT(PF.2) and XT1_IN(PF.3) to input mode */
  11.     PF->MODE &= ~(GPIO_MODE_MODE2_Msk | GPIO_MODE_MODE3_Msk);

  12.     /* Enable HIRC clock (Internal RC 48 MHz) */
  13.     CLK_EnableXtalRC(CLK_PWRCTL_HIRCEN_Msk);

  14.     /* Wait for HIRC clock ready */
  15.     CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk);

  16.     /* Set core clock as 96MHz from PLL */
  17.     CLK_SetCoreClock(FREQ_96MHZ);

  18.     /* Set PCLK0/PCLK1 to HCLK/2 */
  19.     CLK->PCLKDIV = (CLK_PCLKDIV_APB0DIV_DIV2 | CLK_PCLKDIV_APB1DIV_DIV2);

  20.     /* Enable UART clock */
  21.     CLK_EnableModuleClock(UART0_MODULE);

  22.         CLK_EnableModuleClock(TMR0_MODULE);               
  23.                
  24.     /* Select UART clock source from HIRC */
  25.     CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART0SEL_HIRC, CLK_CLKDIV0_UART0(1));
  26.        
  27.         CLK_SetModuleClock(TMR0_MODULE,CLK_CLKSEL1_TMR0SEL_HIRC,0);

  28.     /* Update System Core Clock */
  29.     /* User can use SystemCoreClockUpdate() to calculate SystemCoreClock. */
  30.     SystemCoreClockUpdate();

  31.     /* Set GPB multi-function pins for UART0 RXD and TXD */
  32.     SYS->GPB_MFPH = (SYS->GPB_MFPH & ~(SYS_GPB_MFPH_PB12MFP_Msk | SYS_GPB_MFPH_PB13MFP_Msk))    |       \
  33.                     (SYS_GPB_MFPH_PB12MFP_UART0_RXD | SYS_GPB_MFPH_PB13MFP_UART0_TXD);

  34. /* Lock protected registers */
  35.     SYS_LockReg();
  36. }

  37. void TMR0_IRQHandler(void)
  38. {
  39.     if(TIMER_GetIntFlag(TIMER0) == 1)
  40.     {
  41.         /* Clear Timer0 time-out interrupt flag */
  42.         TIMER_ClearIntFlag(TIMER0);
  43.                         PB14 ^=1;
  44.     }

  45. }

  46. int main(void)
  47. {
  48.         int i=0;

  49.         SYS_Init();

  50.         UART_Open(UART0, 115200);
  51.         printf("Hello World\n");
  52.         GPIO_SetMode(PB,BIT14,GPIO_MODE_OUTPUT);
  53.         PB14=1;

  54.         TIMER_Open(TIMER0,TIMER_PERIODIC_MODE,1);
  55.         TIMER_EnableInt(TIMER0);
  56.         /* Enable Timer0 NVIC */
  57.         NVIC_EnableIRQ(TMR0_IRQn);
  58.         /* Start Timer0 counting */
  59.         TIMER_Start(TIMER0);
  60.         while(1)
  61.         {

  62.         }

  63. }
  1. TIMER_Open(TIMER0,TIMER_PERIODIC_MODE,1);
这里设置的第三个参数是频率,设置为1,那么LED就会以2秒一个周期闪烁,因此1秒修改一次LED的状态。
如果想设置LED以频率1Hz闪烁,那么就将该参数设置为2。
比如我们用串口打印LED的状态
  1. #include"NuMicro.h"
  2. #include<stdio.h>

  3. void SYS_Init(void)
  4. {
  5.     /*---------------------------------------------------------------------------------------------------------*/
  6.     /* Init System Clock                                                                                       */
  7.     /*---------------------------------------------------------------------------------------------------------*/
  8.     /* Unlock protected registers */
  9.     SYS_UnlockReg();

  10.     /* Set XT1_OUT(PF.2) and XT1_IN(PF.3) to input mode */
  11.     PF->MODE &= ~(GPIO_MODE_MODE2_Msk | GPIO_MODE_MODE3_Msk);

  12.     /* Enable HIRC clock (Internal RC 48 MHz) */
  13.     CLK_EnableXtalRC(CLK_PWRCTL_HIRCEN_Msk);

  14.     /* Wait for HIRC clock ready */
  15.     CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk);

  16.     /* Set core clock as 96MHz from PLL */
  17.     CLK_SetCoreClock(FREQ_96MHZ);

  18.     /* Set PCLK0/PCLK1 to HCLK/2 */
  19.     CLK->PCLKDIV = (CLK_PCLKDIV_APB0DIV_DIV2 | CLK_PCLKDIV_APB1DIV_DIV2);

  20.     /* Enable UART clock */
  21.     CLK_EnableModuleClock(UART0_MODULE);

  22.         CLK_EnableModuleClock(TMR0_MODULE);               
  23.                
  24.     /* Select UART clock source from HIRC */
  25.     CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART0SEL_HIRC, CLK_CLKDIV0_UART0(1));
  26.        
  27.         CLK_SetModuleClock(TMR0_MODULE,CLK_CLKSEL1_TMR0SEL_HIRC,0);

  28.     /* Update System Core Clock */
  29.     /* User can use SystemCoreClockUpdate() to calculate SystemCoreClock. */
  30.     SystemCoreClockUpdate();

  31.     /* Set GPB multi-function pins for UART0 RXD and TXD */
  32.     SYS->GPB_MFPH = (SYS->GPB_MFPH & ~(SYS_GPB_MFPH_PB12MFP_Msk | SYS_GPB_MFPH_PB13MFP_Msk))    |       \
  33.                     (SYS_GPB_MFPH_PB12MFP_UART0_RXD | SYS_GPB_MFPH_PB13MFP_UART0_TXD);

  34. /* Lock protected registers */
  35.     SYS_LockReg();
  36. }

  37. void TMR0_IRQHandler(void)
  38. {
  39.         if(TIMER_GetIntFlag(TIMER0) == 1)
  40.         {
  41.                 /* Clear Timer0 time-out interrupt flag */
  42.                 TIMER_ClearIntFlag(TIMER0);
  43.                 if(PB14) {PB14=0;printf("LED is ON  \n");}
  44.                
  45.                 else     {PB14=1;printf("LED is OFF \n");}
  46.         }

  47. }

  48. int main(void)
  49. {

  50.         SYS_Init();

  51.         UART_Open(UART0, 115200);
  52.         printf("Hello World\n");
  53.        
  54.         GPIO_SetMode(PB,BIT14,GPIO_MODE_OUTPUT);
  55.         PB14=1;

  56.         TIMER_Open(TIMER0,TIMER_PERIODIC_MODE,1);
  57.         TIMER_EnableInt(TIMER0);
  58.         /* Enable Timer0 NVIC */
  59.         NVIC_EnableIRQ(TMR0_IRQn);
  60.         /* Start Timer0 counting */
  61.         TIMER_Start(TIMER0);
  62.         while(1)
  63.         {

  64.         }

  65. }
因为库函数传递的参数是整数,因此最小频率是1Hz,如何实现类似0.5Hz这种操作呢,那么就需要在中断里计数了,计数2个后再执行,就可以了。更大周期的以此类推。
  1. #include"NuMicro.h"
  2. #include<stdio.h>

  3. //用于记录中断次数
  4.         int val=0;

  5. void SYS_Init(void)
  6. {
  7.     /*---------------------------------------------------------------------------------------------------------*/
  8.     /* Init System Clock                                                                                       */
  9.     /*---------------------------------------------------------------------------------------------------------*/
  10.     /* Unlock protected registers */
  11.     SYS_UnlockReg();

  12.     /* Set XT1_OUT(PF.2) and XT1_IN(PF.3) to input mode */
  13.     PF->MODE &= ~(GPIO_MODE_MODE2_Msk | GPIO_MODE_MODE3_Msk);

  14.     /* Enable HIRC clock (Internal RC 48 MHz) */
  15.     CLK_EnableXtalRC(CLK_PWRCTL_HIRCEN_Msk);

  16.     /* Wait for HIRC clock ready */
  17.     CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk);

  18.     /* Set core clock as 96MHz from PLL */
  19.     CLK_SetCoreClock(FREQ_96MHZ);

  20.     /* Set PCLK0/PCLK1 to HCLK/2 */
  21.     CLK->PCLKDIV = (CLK_PCLKDIV_APB0DIV_DIV2 | CLK_PCLKDIV_APB1DIV_DIV2);

  22.     /* Enable UART clock */
  23.     CLK_EnableModuleClock(UART0_MODULE);

  24.         CLK_EnableModuleClock(TMR0_MODULE);               
  25.                
  26.     /* Select UART clock source from HIRC */
  27.     CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART0SEL_HIRC, CLK_CLKDIV0_UART0(1));
  28.        
  29.         CLK_SetModuleClock(TMR0_MODULE,CLK_CLKSEL1_TMR0SEL_HIRC,0);

  30.     /* Update System Core Clock */
  31.     /* User can use SystemCoreClockUpdate() to calculate SystemCoreClock. */
  32.     SystemCoreClockUpdate();

  33.     /* Set GPB multi-function pins for UART0 RXD and TXD */
  34.     SYS->GPB_MFPH = (SYS->GPB_MFPH & ~(SYS_GPB_MFPH_PB12MFP_Msk | SYS_GPB_MFPH_PB13MFP_Msk))    |       \
  35.                     (SYS_GPB_MFPH_PB12MFP_UART0_RXD | SYS_GPB_MFPH_PB13MFP_UART0_TXD);

  36. /* Lock protected registers */
  37.     SYS_LockReg();
  38. }

  39. void TMR0_IRQHandler(void)
  40. {
  41.         if(TIMER_GetIntFlag(TIMER0) == 1)
  42.         {
  43.                 val++;
  44.                 /* Clear Timer0 time-out interrupt flag */
  45.                 TIMER_ClearIntFlag(TIMER0);
  46. //计数5秒后再执行翻转LED命令
  47.                 if(val==5)
  48.                 {
  49.                         val=0;
  50.                         if(PB14) {PB14=0;printf("LED is ON  \n");}
  51.                        
  52.                         else     {PB14=1;printf("LED is OFF \n");}
  53.                
  54.                 }

  55.         }

  56. }

  57. int main(void)
  58. {

  59.        
  60.         SYS_Init();

  61.         UART_Open(UART0, 115200);
  62.         printf("Hello World\n");
  63.        
  64.         GPIO_SetMode(PB,BIT14,GPIO_MODE_OUTPUT);
  65.         PB14=1;

  66.         TIMER_Open(TIMER0,TIMER_PERIODIC_MODE,1);
  67.         TIMER_EnableInt(TIMER0);
  68.         /* Enable Timer0 NVIC */
  69.         NVIC_EnableIRQ(TMR0_IRQn);
  70.         /* Start Timer0 counting */
  71.         TIMER_Start(TIMER0);
  72.         while(1)
  73.         {

  74.         }

  75. }


以上代码都是经过测试有效的,不在附带图片或动画。
关于4种定时器计时模式,请参考技术手册的说明。
kiwis66 发表于 2021-9-13 09:50 | 显示全部楼层
这是把几种配置综合到一起说了~
 楼主| gaoyang9992006 发表于 2021-9-13 11:21 | 显示全部楼层
kiwis66 发表于 2021-9-13 09:50
这是把几种配置综合到一起说了~

是的,主要还是为了体现出定时器与中断相关库函数的使用方法,确实比很多厂家的库函数好用。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:如果你觉得我的分享或者答复还可以,请给我点赞,谢谢。

2052

主题

16403

帖子

222

粉丝
快速回复 在线客服 返回列表 返回顶部