单片机控制定时器或计数器之模块化编程

时间:2022-06-28 19:44:30

学习单片机已经有一段时间了,但是很多程序都缺少模块化的思想,之前以为只要把单个的功能封装在一个函数里面就是模块化,但是在公司经过了十多天实习,才真正有了模块化的编程思想,这里将我编写的51单片机控制定时器中断的程序共享一下,一是希望没有模块化编程思想的后来者看看,二是希望前辈们给予斧正

(补充:以下代码只需要修改文件中含有 “选择” 字样的注释部分,就可以达到复用的效果,重点查看中文部分)


 /*################timer.h start################*/

#ifndef __TIMER_H__
#define __TIMER_H__


#ifndef HIGH_LEVEL
#define HIGH_LEVEL  1
#endif

#ifndef LOW_LEVEL
#define LOW_LEVEL  0
#endif


extern volatile unsigned int timerDelayTick;/*选择放在TIMER0或IMER1的中断服务程序中处理*/


/*
	TMOD (sfr   0x89)
sbit	7  6  5  4  3  2  1  0
	|  |  |  |  |  |  |_ |_ _M1 M0 (Timer0 operation  mode)
	|  |  |  |  |  |  		0    0  	13-bit Timer / Counter
	|  |  |  |  |  |        0    1	16-bit Timer / Counter
	|  |  |  |  |  |  		1    0	8-bit  Auto-load  Timer / Counter
	|  |  |  |  |  |  		1    1	(Onlu for Timer0) , TL0 is an 8-bit Counter by standard
	|  |  |  |  |  |  				timer0  control bits . But,TH0 is an 8-bit Counter and is
	|  |  |  |  |  |  				control by timer0 control bits
	|  |  |  |  |  |_  _ _ _ C/T
	|  |  |  |  |  			0		(Timer)    , input form internal clock
	|  |  |  |  |  			1		(Counter) , input form external pin
	|  |  |  |  | 
	|  |  |  |  |_ _ _ _ _ _Gate
	|  |  |  | 
	|  |  |  |
	|  |  |  | 
	|  |  |_ |_ _ _ _ _ _ _ M1 M0 (Timer1 operation  mode)
	|  |  |  				0    0  	13-bit Timer / Counter
	|  |  |     		    0   1	16-bit Timer / Counter
	|  |  |   				1    0	8-bit  Auto-load  Timer / Counter
	|  |  |  		
	|  |  |_  _ _ _ _ _ _ _C/T
	|  	                     0		(Timer)    , input form internal clock
	|               		 1		(Counter) , input form external pin
	|  
	|_ _ _ _ _ _ _ _ _ _ _ _Gate

*/
//Timer0
#define TIMER0_16BIT_TIMER		0X01
#define TIMER0_8BIT_TIMER		0x02
#define TIMER0_16BIT_COUNTER	0X05	
#define TIMER0_8BIT_COUNTER		0x06

//Timer1
#define TIMER1_16BIT_TIMER		0x10
#define TIMER1_8BIT_TIMER		0x20
#define TIMER1_16BIT_COUNTER	0x50
#define TIMER1_8BIT_COUNTER		0x60

//Timer0 and Timer1 mode select
#define TMOD_TIMER0	TIMER0_16BIT_TIMER/*根据需要选择*/
#define TMOD_TIMER1	TIMER1_16BIT_TIMER/*根据需要选择*/
#define TMOD_SETUP	(TMOD_TIMER0 | TMOD_TIMER1)/*根据需要选择*/
#define TIMER0_TICK 	50000/*50ms,50000us.@12.000MZH*/ /*timer0 的计数值,根据需要选择*/
#define TIMER1_TICK		50000/*50ms,50000us.@12.000MZH*/ /*timer1 的计数值,根据需要选择*/

/*-----------单位换算------------*/

#ifndef S_TO_MS
#define S_TO_MS		1000
#endif

#ifndef MS_TO_US
#define MS_TO_US	1000
#endif 

#ifndef US_TO_NS	
#define US_TO_NS	1000
#endif

/*------------------------------*/
/*定时器初始化*/
extern void timerInit(void);

/*定时器延时ms,定时等待直到时间到特定时间*/
extern void timerDelayMs(unsigned long period);


/*中断程序无需在此声明*/


#endif /*__TIMER_H__*/

/*################timer.h start################*/

 

 

/*################timer.c start################*/

/* 
----------------------------------------------------------------------------
FileName	:timer.c
Author		:yangrui
Date		:20130206
Versiion 	:1.0(20130206_15_13)
-----------------------------------------------------------------------------

----------------------------------------------------------------------------
****************************
修改0002	2014-02-07-15_44
****************************
	在函数timerInit()内部分别添加了
	#if(TIMER0_TICK > 65536)
			#error --Invaild TIMER0_TICK.When timer0 work in 16-bit mode.TIMER0_TICK max is 65536.
	#endif

	和
	#if(TIMER0_TICK > 256)
			#error --Invaild TIMER0_TICK.When timer1 work in 8-bit mode.TIMER0_TICK max is 256.
		#endif 


	以及相应的:
	#if (TIMER1_TICK > 65536)
			#error --Invaild TIMER1_TICK.when timer1 work in 16-bit mode.TIMER1_TICK max is 65536.
	#endif
	和
	#if(TIMER1_TICK > 256)
			#error --Invaild TIMER1_TICK.When timer1 work in 8-bit mode.TIMER1_TICK max is 256.
	#endif
	
	
	这四句话,主要是为了防止用户在选择操作模式和赋初值的过程中不小心,没有将这两项匹配起来,造成的定时错误,
	这样的错误有时是无法直接观察出来的。

****************************
修改0001	2014-02-07-13_24
****************************
	将函数
	void timer1DelayMs(unsigned int  period)---失败
	修改为
	void timer1DelayMs(unsigned long  period)---成功

----------------------------------------------------------------------------
*/

#include <reg52.h>
#include "timer.h"



volatile unsigned long  g_timerDelayTick = 0;  /*For timerDelayMs(unsigned long period)*/

/******************************************************************
FuncationName	:timerInit
Input			:N/A
Output			:N/A
Return 			:N/A
Note			:timer  initialization	
/******************************************************************/
void timerInit(void)
{
	TMOD = TMOD_SETUP ;

	/*::::::::::::::::::::::
		TIMER0
	::::::::::::::::::::::*/
	#if((TMOD_TIMER0 == TIMER0_16BIT_COUNTER) ||	\
		 (TMOD_TIMER0 == TIMER0_16BIT_TIMER))
	{/*Timer0  Mode: 16bit Timer / Counter*/
		#if(TIMER0_TICK > 65536)
			#error --Invaild TIMER0_TICK.When timer0 work in 16-bit mode.TIMER0_TICK max is 65536.
		#endif
		
		TH0 = (65535-TIMER0_TICK+1) /256;/*full is 65535,overflow when 65536*/
		TL0 = (65535-TIMER0_TICK+1) %256 ;
	}
	#elif((TMOD_TIMER0 == TIMER0_8BIT_COUNTER) ||	\
			TMOD_TIMER0 == TIMER0_8BIT_TIMER)
	{/*Timer0  Mode: 8bit  Auto-load Timer / Counter*/
		/*这里是为了防止用户操作失误,虽然可以赋值>256,但是最后现象也就不对了,所以为了安全起见,添加这一句*/
		#if(TIMER0_TICK > 256)
			#error --Invaild TIMER0_TICK.When timer1 work in 8-bit mode.TIMER0_TICK max is 256.
		#endif 
		
		TH0 = 255-TIMER0_TICK+1 ;/*full is 255,overflow shen 256*/
		TL0 = 255-TIMER0_TICK+1 ;
	}
	#else
	{
		#error --Invaild TMOD_TIMER0.Please select correct Timer0  mode !
	}
	#endif

	TR0 = HIGH_LEVEL;/*Timer0 start running*/
	ET0 = HIGH_LEVEL;/*Enable Timer0 overflow interrupt*/

	/*::::::::::::::::::::::
		TIMER1
	::::::::::::::::::::::*/
	#if( (TMOD_TIMER1 == TIMER1_16BIT_COUNTER) || \
		  (TMOD_TIMER1 == TIMER1_16BIT_TIMER))
	{/*Timer1  Mode: 16bit Timer / Counter*/
		#if (TIMER1_TICK > 65536)
			#error --Invaild TIMER1_TICK.when timer1 work in 16-bit mode.TIMER1_TICK max is 65536.
		#endif
		
		TH1 = (65535-TIMER1_TICK+1) /256;/*full is 65535,overflow when 65536*/
		TL1 = (65535-TIMER1_TICK+1) %256 ;
	}
	#elif((TMOD_TIMER1 == TIMER1_8BIT_COUNTER) ||	\
		  (TMOD_TIMER1 == TIMER1_8BIT_TIMER))
	{
		#if(TIMER1_TICK > 256)
			#error --Invaild TIMER1_TICK.When timer1 work in 8-bit mode.TIMER1_TICK max is 256.
		#endif
		
		TH1= 255-TIMER1_TICK+1 ;
		TL1= 255-TIMER1_TICK+1 ;
	}
	#else
	{
		#error --Invaild TMOD_TIMER1.Please select correct Timer1  mode !
	}
	#endif

	TR1 = HIGH_LEVEL;/*Timer1 start running*/
	ET1 = HIGH_LEVEL;/*Enable Timer1 overflow interruput*/

	/*::::::::::::::::::::::
		TIMER2
	::::::::::::::::::::::*/
	/*...................................................................*/





	EA = HIGH_LEVEL ;
}

/******************************************************************
FuncationName	:timer0InterruptServerRoutine
Input			:N/A
Output			:N/A
Return 			:N/A
Note			:timer0 interrupt server routine 	
/******************************************************************/

void timer0InterruptServerRoutine(void) interrupt 1 using 1
{
	#if( (TMOD_TIMER0 == TIMER0_16BIT_COUNTER) || \
		 (TMOD_TIMER0 == TIMER0_16BIT_TIMER))
	{
		TH0 = (65535-TIMER0_TICK+1) /256;
		TL0 = (65535-TIMER0_TICK+1) %256 ;
	}
	#elif( (TMOD_TIMER0 == TIMER0_8BIT_COUNTER) ||
		   (TMOD_TIMER0 == TIMER0_8BIT_TIMER))
	{
		//Auto-load
	}
	#else
		#error --Invaild TMOD_TIMER0.Please select correct Timer0  mode !
	#endif


	/*--------需要在中断中的处理的工作,等待补充。 Start-------*/






	/*--------需要在中断中的处理的工作,等待补充。 End-------*/
}

/******************************************************************
FuncationName	:timer1InterruptServerRoutine
Input			:N/A
Output			:N/A
Return 			:N/A
Note			:timer1 interrupt server routine 	
/******************************************************************/

void timer1InterruptServerRoutine(void) interrupt 3
{
	#if( (TMOD_TIMER1 == TIMER1_16BIT_COUNTER) || \
		 (TMOD_TIMER1== TIMER1_16BIT_TIMER))
	{
		TH1 = (65535-TIMER1_TICK+1) /256;
		TL1= (65535-TIMER1_TICK+1) %256 ;
	}
	#elif( (TMOD_TIMER1 == TIMER1_8BIT_COUNTER) ||
		   (TMOD_TIMER1 == TIMER1_8BIT_TIMER))
	{
		//Auto-load
	}
	#else
		#error --Invaild TMOD_TIMER1.Please select correct Timer1  mode !
	#endif


	/*--------需要在中断中的处理的工作,等待补充。 Start-------*/

	/*for timer1DelayMs()*/
	if(g_timerDelayTick)
	{
		g_timerDelayTick--;
	}

	/*--------需要在中断中的处理的工作,等待补充。 End-------*/
}

/******************************************************************
FuncationName	:timerInit
Input			:period (server ms)
Output			:N/A
Return 			:N/A
Note			:Timer  Delay  server  ms ,wait until time reach	
/******************************************************************/
void timerDelayMs(unsigned long  period)
{
	/* Ms to us*/
	period *= MS_TO_US ;
	g_timerDelayTick = period /TIMER1_TICK;

	TR0 = HIGH_LEVEL ;
	
	while(g_timerDelayTick)
	{
		;//Wait
	}
}

/*################timer.c start################*/

 


测试程序:

步骤0001 :在timer.c中添加代码

volatile unsigned int g_aa = 0;

步骤0002 : 在timer.h中添加代码

extern volatile unsigned int g_aa;			/*选择放在TIMER0或IMER1的中断服务程序中处理*/

步骤0003 : 在timer.c中的函数

          void timer0InterruptServerRoutine(void) interrupt 1 using 1

中添加代码 , 效果如下:

	/*--------需要在中断中的处理的工作,等待补充。 Start-------*/
	g_aa++;

	/*--------需要在中断中的处理的工作,等待补充。 End-------*/

 

步骤0004 : 测试主程序为:

#include <reg52.h>
#include "timer.h"

void main(void)
{
	P0 = 0x00;
	timerInit();

	/*测试版本一*/
	while(1)
	{
		if(g_aa == 20)
		{
			g_aa  = 0;
			P0=~P0 ;
		}	
	}	

	/*测试版本二*/
	while(1)
	{
		timerDelayMs(1000);
		P0 = ~P0;
	}