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