[菜农助学交流] 【第四批】新手笔记三_定时器

[复制链接]
4635|3
 楼主| 357482894 发表于 2011-12-4 12:28 | 显示全部楼层 |阅读模式
在上次的实验中,使用按键中断方式控制LED的点亮方式,本次实验采用定时器按一定时间间隔扫描按键状态,并进行消抖和判断松开操作,进而控制LED。基本流程图如下:


程序如下:


  1. #include <stdio.h>
  2. #include "NUC1xx.h"
  3. #include "DrvGPIO.h"
  4. #include "DrvSYS.h"
  5. #include "DrvTIMER.h"
  6. #include "led.h"
  7. int flag=0,flag1=0;
  8. int k1,k2;
  9. int L_num=0,R_num=0;
  10. /*初始化*/
  11. void Sys_Init()
  12. {
  13.     UNLOCKREG();         
  14.     SYSCLK->PWRCON.XTL12M_EN = 1;//设定12M外部晶振
  15.     DrvSYS_Delay(5000);//等待时钟就绪
  16. DrvGPIO_Open(E_GPA,2,E_IO_OUTPUT);//LED端口设置为输出
  17. DrvGPIO_Open(E_GPA,3,E_IO_OUTPUT);
  18. DrvGPIO_Open(E_GPA,4,E_IO_OUTPUT);
  19. DrvGPIO_Open(E_GPA,5,E_IO_OUTPUT);
  20. DrvGPIO_Open(E_GPB,14,E_IO_INPUT);//按键接口设置为输入
  21. DrvGPIO_Open(E_GPB,15,E_IO_INPUT);
  22. DrvGPIO_Open(E_GPB,10,E_IO_OUTPUT);//蜂鸣器端口设置为输出
  23. DrvGPIO_ClrBit(E_GPB,10);//关闭蜂鸣器
  24. }
  25. /***************************************************************
  26. 定时器1回调函数
  27. 用于按一定时间间隔扫描按键
  28. 如检测到有按键按下,则使能定时器2
  29. ***************************************************************/
  30. void TMR1_Callback(void)
  31. {
  32. k1=DrvGPIO_GetBit(E_GPB,15);//取按键状态
  33. k2=DrvGPIO_GetBit(E_GPB,14);
  34. if(k1==0||k2==0)   //有按键按下
  35. {
  36.   DrvTIMER_DisableInt(E_TMR1);//禁止定时器1中断
  37.   DrvTIMER_EnableInt(E_TMR2);//使能定时器2中断
  38.   DrvTIMER_Start(E_TMR2);//启动定时器2
  39. }  
  40. }
  41. /***************************************************************
  42. 定时器2回调函数
  43. 用于延时一段时间进行按键消抖
  44. 如仍有按键按下,则使能定时器3;如没有,使能定时器1
  45. ***************************************************************/
  46. void TMR2_Callback(void)
  47. {
  48. k1=DrvGPIO_GetBit(E_GPB,15);//取按键状态
  49. k2=DrvGPIO_GetBit(E_GPB,14);
  50. if(k1==0||k2==0)     //仍有按键按下
  51. {
  52.   DrvTIMER_DisableInt(E_TMR2);//禁止定时器2中断
  53.   DrvTIMER_EnableInt(E_TMR3);//使能定时器3中断
  54.   DrvTIMER_Start(E_TMR3);//启动定时器3
  55.   if(k1==0) flag1=1;
  56.   if(k2==0) flag1=2;  
  57. }
  58. else
  59. {
  60.   DrvTIMER_DisableInt(E_TMR2);//禁止定时器2中断
  61.   DrvTIMER_EnableInt(E_TMR1);//使能定时器3中断
  62.   DrvTIMER_Start(E_TMR1);//启动定时器3
  63. }  
  64. }
  65. /***************************************************************
  66. 定时器3回调函数
  67. 用于延时一段时间等待按键松开
  68. ***************************************************************/
  69. void TMR3_Callback(void)
  70. {
  71. k1=DrvGPIO_GetBit(E_GPB,15);//取按键状态
  72. k2=DrvGPIO_GetBit(E_GPB,14);
  73. if(k1==1&k2==1)    //按键松开
  74. {
  75.   DrvTIMER_DisableInt(E_TMR3);//禁止定时器3中断
  76.   DrvGPIO_SetBit(E_GPB,10);//启动蜂鸣器
  77.   if(flag1==1)
  78.   {
  79.    flag=2;
  80.    R_num++;
  81.    flag1=0;
  82.   }
  83.   if(flag1==2)
  84.   {
  85.    flag=1;
  86.    L_num++;
  87.    flag1=0;
  88.   }
  89.   DrvTIMER_EnableInt(E_TMR1);//使能定时器1中断
  90.   DrvTIMER_Start(E_TMR1);//启动定时器1
  91. }
  92. }
  93. /*定时器初始化*/
  94. void Timer_Init()
  95. {
  96. DrvTIMER_Init();//定时器初始化函数
  97. /*定时器0配置*/
  98. // DrvSYS_SelectIPClockSource(E_SYS_TMR0_CLKSRC,0);//时钟源选择,0为外部晶振
  99. // DrvTIMER_Open(E_TMR0,100,E_PERIODIC_MODE);//设定tick周期启动定时器,每秒100次,周期模式
  100. // DrvTIMER_SetTimerEvent(E_TMR0,100,(TIMER_CALLBACK)TMR0_Callback,0);//设定定时器处理事件,每100tick周期执行一次
  101. // DrvTIMER_EnableInt(E_TMR0);//使能定时器0中断
  102. // DrvTIMER_Start(E_TMR0);//启动定时器0

  103. /*定时器1配置*/
  104. DrvSYS_SelectIPClockSource(E_SYS_TMR1_CLKSRC,0);//时钟源选择
  105. DrvTIMER_Open(E_TMR1,1000,E_PERIODIC_MODE);//设定tick周期启动定时器,每秒1000次,周期模式
  106. DrvTIMER_SetTimerEvent(E_TMR1,20,(TIMER_CALLBACK)TMR1_Callback,0);//设定定时器处理事件,每20tick周期执行一次
  107. DrvTIMER_EnableInt(E_TMR1);//使能定时器1中断
  108. DrvTIMER_Start(E_TMR1);//启动定时器1

  109. /*定时器2配置*/
  110. DrvSYS_SelectIPClockSource(E_SYS_TMR2_CLKSRC,0);//时钟源选择
  111. DrvTIMER_Open(E_TMR2,1000,E_PERIODIC_MODE);//设定tick周期启动定时器,每秒1000次,周期模式
  112. DrvTIMER_SetTimerEvent(E_TMR2,30,(TIMER_CALLBACK)TMR2_Callback,0);//设定定时器处理事件,每30tick周期执行一次

  113. /*定时器3配置*/
  114. DrvSYS_SelectIPClockSource(E_SYS_TMR3_CLKSRC,0);//时钟源选择
  115. DrvTIMER_Open(E_TMR3,1000,E_PERIODIC_MODE);//设定tick周期启动定时器,每秒1000次,周期模式
  116. DrvTIMER_SetTimerEvent(E_TMR3,50,(TIMER_CALLBACK)TMR3_Callback,0);//设定定时器处理事件,每50tick周期执行一次   
  117. }
  118. main()
  119. {
  120. Sys_Init();
  121. Timer_Init();
  122. while(1)
  123. {
  124.   if(flag==1)
  125.   {
  126.    DrvGPIO_ClrBit(E_GPB,10);
  127.    if(L_num>=10) L_num=0;
  128.    flag=0;
  129.    switch(L_num)
  130.    {
  131.     case 0:
  132.      led_allon();
  133.      break;
  134.     case 1:
  135.      led_one(1);
  136.      break;
  137.     case 2:
  138.      led_one(2);
  139.      break;
  140.     case 3:
  141.      led_one(3);
  142.      break;
  143.     case 4:
  144.      led_one(4);
  145.      break;
  146.     case 5:
  147.      led_l2r_one();
  148.      break;
  149.     case 6:
  150.      led_l2r_two();
  151.      break;
  152.     case 7:
  153.      led_l2r_three();
  154.      break;
  155.     case 8:
  156.      led_l2r_four();
  157.      break;
  158.     case 9:
  159.      led_all();
  160.      break;
  161.     default:break;
  162.    }
  163.   }
  164.   if(flag==2)
  165.   {
  166.    DrvGPIO_ClrBit(E_GPB,10);
  167.    if(R_num>=10) R_num=0;
  168.    flag=0;
  169.    switch(R_num)
  170.    {
  171.     case 0:
  172.      led_allon();
  173.      break;
  174.     case 1:
  175.      led_one(4);
  176.      break;
  177.     case 2:
  178.      led_one(3);
  179.      break;
  180.     case 3:
  181.      led_one(2);
  182.      break;
  183.     case 4:
  184.      led_one(1);
  185.      break;
  186.     case 5:
  187.      led_r2l_one();
  188.      break;
  189.     case 6:
  190.      led_r2l_two();
  191.      break;
  192.     case 7:
  193.      led_r2l_three();
  194.      break;
  195.     case 8:
  196.      led_r2l_four();
  197.      break;
  198.     case 9:
  199.      led_all();
  200.      break;
  201.     default:break;
  202.    }
  203.   }
  204. }
  205. }



工程压缩包:


总的来说,本次实验使用的资源比较浪费。但通过本实验可以练习多个定时器的使用,比如这次涉及到的禁止某个定时器后再次打开,这个过程只需要操作定时器中断即可。

本来想使用定时器0,但发现当定时器0单独工作时,正常;当定时器0同其他定时器同时工作时,不能正常工作,不知为啥?

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
hotpower 发表于 2011-12-4 22:58 | 显示全部楼层
switch(R_num)不如函数指针数组~~~
mcs8098 发表于 2011-12-20 12:41 | 显示全部楼层
huzaizai007 发表于 2012-3-8 16:28 | 显示全部楼层
2# hotpower

百度了一下,原来函数指针数组这么神奇
长知识了~
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

756

帖子

1

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