学习单片机已经有一段时间了,但是很多程序都缺少模块化的思想,之前以为只要把单个的功能封装在一个函数里面就是模块化,但是在公司经过了十多天实习,才真正有了模块化的编程思想,这里将我编写的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;
}