IAP15W413AS工业自动化控制之【05定时器控制的流水灯】

  • SingleYork
  • LV5工程师
  • |      2017-08-12 10:52:15
  • 浏览量 1734
  • 回复:1
bg1.png

前面介绍了IAP15W413AS这款控制板的基本输入和输出控制,这一帖主要跟大家介绍一下怎么使用定时器来精确定时控制输出,还是用最简单的流水灯为例来介绍。

既然要使用定时器,那么首先肯定要配置好定时器的工作模式、定时时间长等参数:

/**************** 定时器配置 ******************/

void	Timer_config(void)

{

	TIM_InitTypeDef		TIM_InitStructure;					        //结构定义

	TIM_InitStructure.TIM_Mode      = TIM_16BitAutoReload;	        //指定工作模式,   TIM_16BitAutoReload,TIM_16Bit,TIM_8BitAutoReload,TIM_16BitAutoReloadNoMask

	TIM_InitStructure.TIM_Polity    = PolityLow;				    //指定中断优先级, PolityHigh,PolityLow

	TIM_InitStructure.TIM_Interrupt = ENABLE;						//中断是否允许,   ENABLE或DISABLE

	TIM_InitStructure.TIM_ClkSource = TIM_CLOCK_1T;					//指定时钟源,     TIM_CLOCK_1T,TIM_CLOCK_12T,TIM_CLOCK_Ext

	TIM_InitStructure.TIM_ClkOut    = DISABLE;						//是否输出高速脉冲, ENABLE或DISABLE

	TIM_InitStructure.TIM_Value     = 65536UL - (MAIN_Fosc / 1000);	//初值,1000HZ中断率,500HZ方波(1ms定时)

	TIM_InitStructure.TIM_Run       = ENABLE;						//是否初始化后启动定时器, ENABLE或DISABLE

	Timer_Inilize(Timer0,&TIM_InitStructure);						//初始化Timer0	  Timer0,Timer1,Timer2,Timer3,Timer44

}

在上面定时器的配置中,我们可以看到,使用的是定时器0,定时器的工作模式为“16位自动重装模式”,定时时长为“1毫秒”。如果要修改定时时长,值需要修改TIM_InitStructure.TIM_Value的值就好了,也即将后面的1000改成我们需要的数,至于具体计算方式,还请看芯片手册上的定时器这一章节,在这里就不再赘述。

定时器的参数配置好之后,我们就可以来使用定时器了,首先,我们定义两个变量OUT_CTR和Time_Cnt,其中OUT_CTR是用来控制输出的标志位,Time_Cnt是用来计时的:

bit OUT_CTR;            //定义一个标志控制输出

u16 Time_Cnt;           //定义一个变量用来计时

我们以定时500毫秒为例,定时器是每1毫秒中断一次,那么我们需要定时500毫秒的话,就可以让一个变量在定时器每次中断的时候自动加1,那么当这个变量加到500的时候,自然就是500毫秒了。

/********************* Timer0中断函数************************/

void timer0_int (void) interrupt TIMER0_VECTOR	//1ms

{

    if(++Time_Cnt>=500)

    {

        OUT_CTR = 1;

        Time_Cnt= 0;

    }

}

同时,我们在每定时到500毫秒的时候,将输出标志位OUT_CTR置1,用来控制后面的输出,同时也需要将Time_Cnt清零以便下次又从0开始计数。

由于变量OUT_CTR和Time_Cnt是在Timer.c里面定义的,那么我们在main.c里面也要用这两个变量怎么办?很明显,我需要对外部变量进行声明,声明之后我们就可以使用外部变量了:

extern bit OUT_CTR;            //定义一个标志控制输出

extern u16 Time_Cnt;           //定义一个变量用来计时

同时为了方便控制输出口的顺序输出,我们还定义了一个变量:

u8 Num;                        //定义一个变量来控制输出顺序

还有,为了方便让输出状态更容易理解,笔者宏定义了两个参数,在后面需要赋值1的地方便可以直接用ON来替代,需要赋值0的地方,可以直接用OFF来替代,这样会使得程序看起来更加容易理解:

#define ON  1

#define OFF 0

好了,准备工作都做好了,接下来就要来写我们要实现的动作了:

void main(void)

{

	OUT00   = OFF;

    OUT01   = OFF;

    OUT02   = OFF;

    OUT03   = OFF;

    OUT04   = OFF;

    OUT05   = OFF;

    

    delay_ms(1000);		//延时大约1秒,等待电源稳定

    

	Timer_config();		//定时器配置

	GPIO_config();      //GPIO配置

    

	EA       = 1;		//开启总中断

	Time_Cnt = 0;

    OUT_CTR  = 0;

    Num      = 0;

    

	while(1)

	{

        if(OUT_CTR)

        {

            OUT_CTR  = 0;

            

            if(Num==0)

            {

                OUT05    = OFF;

                OUT00    = ON;

            }

            if(Num==1)

            {

                OUT00    = OFF;

                OUT01    = ON;

            }

            if(Num==2)

            {

                OUT01    = OFF;

                OUT02    = ON;

            }

            if(Num==3)

            {

                OUT02    = OFF;

                OUT03    = ON;

            }

            if(Num==4)

            {

                OUT03    = OFF;

                OUT04    = ON;

            }

            if(Num==5)

            {

                OUT04    = OFF;

                OUT05    = ON;

            }

            

            Num ++;

            

            if(Num>5)   //因为只有5个输出,所以这里控制最大输出序号不能超过5

            {

               Num = 0; 

            }

        }

        

	}

}

思路是这样的:每500毫秒OUT_CTR会被自动置1,那么我们便在每次OUT_CTR置1的时候,控制一个输出口ON,当然我们也需要关闭前面一个输出口,不然就会所有输出口全部都依次亮了,而不是顺序亮的流水灯效果了。在每次操作一个输出口后,我们需要将Num加1,以便控制下一个输出口动作,同时,我们需要将OUT_CTR软件清零。另外需要注意的是,因为我们只有6个IO口,而Num是从0开始计数的,所以,当Num超过5后,我们需要将Num清零,否则就不能循环亮灯了。

至于演示效果就不再帖上来了,因为跟之前的延时函数流水灯的效果是一致的,源代码见附件!

源代码:

  • 1
  • 收藏
  • 举报
  • 分享
我来回复

登录后可评论,请 登录注册

所有回答 数量:2
2016大圣 2019-05-15
好资料,谢谢分享!:victory:点赞!
0   回复
举报
发布
mihang1987@126. 2017-09-28
初学者,又受教了
0   回复
举报
发布
x
收藏成功!点击 我的收藏 查看收藏的全部帖子