Dotcpp  >  编程教程  >  定时器  >  单独文件封装

单独文件封装

点击打开在线编译器,边学边练

1.再遇多文件编程

因为定时器经常在后面的教程中使用到,所以我们也把这部分功能代码单独使用文件封装起来。

在第六章的教程中已经教过大家多文件创建,这里点到为止。

创建好“timer.c”和“timer.h”

定时器12


添加进工程中

定时器13


2.timer.c的代码

#include <reg52.h> 
#include <function.h> //详见第六章第8讲
  
u8 T0RH,T0RL,T1RH,T1RL;
  
void TIM0_Init(u32 us,int trim)//trim:微调
{
    u32 tmp;  //临时变量
    
    tmp = 11059200 / 12;            //定时器计数频率
    tmp = ( tmp * (us/100) )/10000; //计算所需的计数值
    tmp = 65536 - tmp;              //计算定时器重载值
    tmp = tmp+trim;                 //微调计数值使其定时更精确到我们想要的定时时间
    T0RH = (unsigned char)(tmp>>8); //定时器重载值拆分为高低字节  
    T0RL = (unsigned char)tmp;
    TMOD &= 0xF0; //清0低四位 
    TMOD |= 0x01; //设置定时器0为工作模式1   
    TH0 = T0RH;   //加载T0重载值   
    TL0 = T0RL;
    ET0 = 1;      //闭合定时器0中断的开关        
    TR0 = 1;      //启动定时器0         
}  
 
void TIM1_Init(u32 us,int trim)//trim:微调
{
    u32 tmp;  //临时变量
    
    tmp = 11059200 / 12;            //定时器计数频率
    tmp = ( tmp * (us/100) )/10000; //计算所需的计数值
    tmp = 65536 - tmp;              //计算定时器重载值
    tmp = tmp+trim;                 //微调计数值使其定时更精确到我们想要的定时时间
    T1RH = (unsigned char)(tmp>>8); //定时器重载值拆分为高低字节    
    T1RL = (unsigned char)tmp;
    TMOD&=0x0F;//清0高四位
    TMOD|=0x10;//设置定时器1为工作模式1 
    TH1 = T1RH;//加载T1重载值     
    TL1 = T1RL;
    ET1 = 1;   //闭合定时器1中断的开关        
    TR1 = 1;   //启动定时器1         
}

“TMOD&=0xF0;”的作用跟数码管显示小数点的代码技巧一样,保持前面4位的值不变,清0后四位,然后“TMOD|=0x01;”就是不改变原来高四位的值,然后把低四位设成 0001。

如果在TIM0_Init()函数中只写“TMOD=0x01;”

在TIM1_Init()函数中只写“TMOD=0x10;”

然后初始化时像这样按顺序来写

TIM0_Init(20000,20);//定时20ms,20微调使定时精度更高

TIM1_Init(50000,20);//定时50ms,20微调使定时精度更高

那么执行TIM1_Init()的函数内容时就会执行“TMOD=0x10;”把人家低四位给清0了,原本想让定时器0工作在模式1,现在低2位的值变了也就不是工作在模式1了。

所以“TMOD&=0x0F; TMOD|=0x10;”的写法是不干涉互相的位。

我们定义了“T0RH,T0RL,T1RH,T1RL”四个8位的全局变量(R:reload)用来在中断函数里重新赋值。

因为工作模式1都是需要在中断函数中重新赋初值,所以这四个变量是存取初始化时给THx和TLx的初值。


3.timer.h的代码

#ifndef __TIMER_H__
#define __TIMER_H__
  
extern u8 T0RH,T0RL,T1RH,T1RL;
 
void TIM0_Init(u32 us,int trim);//trim:微调 
void TIM1_Init(u32 us,int trim);//trim:微调 

#endif


4.main.c的代码

这样,实现间隔50ms的流水灯在书写上就相当简洁了

#include <reg52.h> 
#include <function.h> //详见第六章第8讲
#include <timer.h>

void main()
{
    LED_Init();         //初始化LED硬件模块
    EA = 1;             //闭合总中断开关
    TIM0_Init(50000,20);//用定时器0定时50ms,20是微调使中断函数里的i均匀地50.00ms后自加,精度更高
    while(1);
}

void TIM0_IRQHandler() interrupt 1
{
    static u8 i; 
    TH0 = T0RH;  //重新加载重载值
    TL0 = T0RL;

    P0=~(0x01<<i);
    i++;
    if(i>=8)i=0; 
}

本文固定URL:https://www.dotcpp.com/course/380

上一课:

微调定时精确时间

下一课:

输入捕获

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

单片机教程
第一章 单片机入门
第二章 LED及入门
第三章 蜂鸣器
第四章 数码管
第五章 独立按键
第六章 多文件编程
第七章 外部中断
第八章 定时器
第九章 舵机与超声波模块
第十章 串口通信
第十一章 1602液晶屏
第十二章 IIC通信
第十三章 红外遥控与温度传感器
第十四章 AD与DA
第十五章 混合例程
第十六章 完结
Dotcpp在线编译      (登录可减少运行等待时间)