打印
[菜农助学交流]

【第四批】新手笔记三_定时器

[复制链接]
3869|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
在上次的实验中,使用按键中断方式控制LED的点亮方式,本次实验采用定时器按一定时间间隔扫描按键状态,并进行消抖和判断松开操作,进而控制LED。基本流程图如下:


程序如下:
 

#include <stdio.h>
#include "NUC1xx.h"
#include "DrvGPIO.h"
#include "DrvSYS.h"
#include "DrvTIMER.h"
#include "led.h"
int flag=0,flag1=0;
int k1,k2;
int L_num=0,R_num=0;
/*初始化*/
void Sys_Init()
{
    UNLOCKREG();         
    SYSCLK->PWRCON.XTL12M_EN = 1;//设定12M外部晶振
    DrvSYS_Delay(5000);//等待时钟就绪
DrvGPIO_Open(E_GPA,2,E_IO_OUTPUT);//LED端口设置为输出
DrvGPIO_Open(E_GPA,3,E_IO_OUTPUT);
DrvGPIO_Open(E_GPA,4,E_IO_OUTPUT);
DrvGPIO_Open(E_GPA,5,E_IO_OUTPUT);
DrvGPIO_Open(E_GPB,14,E_IO_INPUT);//按键接口设置为输入
DrvGPIO_Open(E_GPB,15,E_IO_INPUT);
DrvGPIO_Open(E_GPB,10,E_IO_OUTPUT);//蜂鸣器端口设置为输出
DrvGPIO_ClrBit(E_GPB,10);//关闭蜂鸣器
}
/***************************************************************
定时器1回调函数
用于按一定时间间隔扫描按键
如检测到有按键按下,则使能定时器2
***************************************************************/
void TMR1_Callback(void)
{
k1=DrvGPIO_GetBit(E_GPB,15);//取按键状态
k2=DrvGPIO_GetBit(E_GPB,14);
if(k1==0||k2==0)   //有按键按下
{
  DrvTIMER_DisableInt(E_TMR1);//禁止定时器1中断
  DrvTIMER_EnableInt(E_TMR2);//使能定时器2中断
  DrvTIMER_Start(E_TMR2);//启动定时器2
}  
}
/***************************************************************
定时器2回调函数
用于延时一段时间进行按键消抖
如仍有按键按下,则使能定时器3;如没有,使能定时器1
***************************************************************/
void TMR2_Callback(void)
{
k1=DrvGPIO_GetBit(E_GPB,15);//取按键状态
k2=DrvGPIO_GetBit(E_GPB,14);
if(k1==0||k2==0)     //仍有按键按下
{
  DrvTIMER_DisableInt(E_TMR2);//禁止定时器2中断
  DrvTIMER_EnableInt(E_TMR3);//使能定时器3中断
  DrvTIMER_Start(E_TMR3);//启动定时器3
  if(k1==0) flag1=1;
  if(k2==0) flag1=2;  
}
else
{
  DrvTIMER_DisableInt(E_TMR2);//禁止定时器2中断
  DrvTIMER_EnableInt(E_TMR1);//使能定时器3中断
  DrvTIMER_Start(E_TMR1);//启动定时器3
}  
}
/***************************************************************
定时器3回调函数
用于延时一段时间等待按键松开
***************************************************************/
void TMR3_Callback(void)
{
k1=DrvGPIO_GetBit(E_GPB,15);//取按键状态
k2=DrvGPIO_GetBit(E_GPB,14);
if(k1==1&k2==1)    //按键松开
{
  DrvTIMER_DisableInt(E_TMR3);//禁止定时器3中断
  DrvGPIO_SetBit(E_GPB,10);//启动蜂鸣器
  if(flag1==1)
  {
   flag=2;
   R_num++;
   flag1=0;
  }
  if(flag1==2)
  {
   flag=1;
   L_num++;
   flag1=0;
  }
  DrvTIMER_EnableInt(E_TMR1);//使能定时器1中断
  DrvTIMER_Start(E_TMR1);//启动定时器1
}
}
/*定时器初始化*/
void Timer_Init()
{
DrvTIMER_Init();//定时器初始化函数
/*定时器0配置*/
// DrvSYS_SelectIPClockSource(E_SYS_TMR0_CLKSRC,0);//时钟源选择,0为外部晶振
// DrvTIMER_Open(E_TMR0,100,E_PERIODIC_MODE);//设定tick周期启动定时器,每秒100次,周期模式
// DrvTIMER_SetTimerEvent(E_TMR0,100,(TIMER_CALLBACK)TMR0_Callback,0);//设定定时器处理事件,每100tick周期执行一次
// DrvTIMER_EnableInt(E_TMR0);//使能定时器0中断
// DrvTIMER_Start(E_TMR0);//启动定时器0

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

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

/*定时器3配置*/
DrvSYS_SelectIPClockSource(E_SYS_TMR3_CLKSRC,0);//时钟源选择
DrvTIMER_Open(E_TMR3,1000,E_PERIODIC_MODE);//设定tick周期启动定时器,每秒1000次,周期模式
DrvTIMER_SetTimerEvent(E_TMR3,50,(TIMER_CALLBACK)TMR3_Callback,0);//设定定时器处理事件,每50tick周期执行一次   
}
main()
{
Sys_Init();
Timer_Init();
while(1)
{
  if(flag==1)
  {
   DrvGPIO_ClrBit(E_GPB,10);
   if(L_num>=10) L_num=0;
   flag=0;
   switch(L_num)
   {
    case 0:
     led_allon();
     break;
    case 1:
     led_one(1);
     break;
    case 2:
     led_one(2);
     break;
    case 3:
     led_one(3);
     break;
    case 4:
     led_one(4);
     break;
    case 5:
     led_l2r_one();
     break;
    case 6:
     led_l2r_two();
     break;
    case 7:
     led_l2r_three();
     break;
    case 8:
     led_l2r_four();
     break;
    case 9:
     led_all();
     break;
    default:break;
   }
  }
  if(flag==2)
  {
   DrvGPIO_ClrBit(E_GPB,10);
   if(R_num>=10) R_num=0;
   flag=0;
   switch(R_num)
   {
    case 0:
     led_allon();
     break;
    case 1:
     led_one(4);
     break;
    case 2:
     led_one(3);
     break;
    case 3:
     led_one(2);
     break;
    case 4:
     led_one(1);
     break;
    case 5:
     led_r2l_one();
     break;
    case 6:
     led_r2l_two();
     break;
    case 7:
     led_r2l_three();
     break;
    case 8:
     led_r2l_four();
     break;
    case 9:
     led_all();
     break;
    default:break;
   }
  }
}
}



工程压缩包:
timer.rar (1 MB)

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

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

相关帖子

沙发
hotpower| | 2011-12-4 22:58 | 只看该作者
switch(R_num)不如函数指针数组~~~

使用特权

评论回复
板凳
mcs8098| | 2011-12-20 12:41 | 只看该作者
:lol

使用特权

评论回复
地板
huzaizai007| | 2012-3-8 16:28 | 只看该作者
2# hotpower

百度了一下,原来函数指针数组这么神奇
长知识了~

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

756

帖子

1

粉丝