三:定时器

定时器和计数器其实一个寄存器配置,他们工作模式相同,都是对脉冲计数,不同的是脉冲来源不同,计数器是对外部脉冲计数,定时器是对内部时钟计数。

定时器/计数器0有4种工作模式:

模式0(16位自动重装载模式),

模式1(16位不可重装载模式),

模式2 (8位自动重装模式) ,

模式3 (不可屏蔽中断的16位自动重装载模式)。

工作流程,模式0 ,16位定时器就是最大跑到65535,从0或者从设置的重装载值跑到65535就进入定时器中断,模式1就是需要每一次进入中断的时候设置一下重装载值,不然会从0开始。

定时器配置步骤:



一:配置时钟,确定定时多长时间进入中断,我们要先设置好时钟。

当定时器/计数器T0、T1及T2工作在定时模式时,特殊功能寄存器AUXR中的TOx12,T1x12和T2x12分别决定是系统时钟/12还是系统时钟/1 (不分频)后让TO、TI和T2进行计数。

当定时器/计数器T3和T4工作在定时模式时,特殊功能寄存器T4T3M中的T3x12和T4x12分别决定是系统时钟/12还是系统时钟/1 (不分频)后让T3和T4进行计数。当定时器/计数器工作在计数模式时,对外部脉冲计数不分频。

例如:设置T0为系统频率不分频,AUXR的B7位置1;

程序:AUXR |= 0x80; //定时器时钟1T模式


二: 配置模式,强力推荐模式0;

TMOD的B3位置1控制定时器需要INO引脚外部上来才能使用定时器,这个置0,不要这么麻烦;B2位设置定时器还是计数器,定时器置0;B1,B0就是设置工作模式,都为0设置为16位自动重装载模式。

程序:TMOD &= 0xF0; //设置为定时器,模式0工作方式,16位自动重装载模式

与等于0XF0,其实就是把后4位置0,0XF0二进制是11110000;


三:设置定时器初值;

用初值来决定多长时间进入一次定时器中断,单片机主频是35MHZ,设置的定时器频率等于单片机主频也是35MHZ,然后换算一下,16位就是65535,每加1就是1/35us微秒,1ms毫秒就是1000us微秒,(1/35)*1000=35000,定时器1毫秒计数到35000就行;即定时器1毫秒的初值等于65536-35000=30536,30536转换为16进制是7748;

妈的,得要2个寄存器来设置定时器初值,7748,高8位77,低8位48;

程序:

TL0 = 0x48; //设置定时初值

TH0 = 0x77; //设置定时初值


四:清除定时器中断开启定时器;

先清除一下定时器中断是防止上电就进入定时器中断,

清除中断;定时器0产生中断TCON的B5位置1,

程序;TF0 = 0; //清除TF0标志

打开定时器0,是B4位;

程序:TR0 = 1; //定时器0开始计时



五: 开启定时器中断和总中断

程序:

ET0 = 1; //允许定时器T0溢出中断

EA = 1; // 打开总中断


六:中断服务函数

查找中断服务函数列表,找到定时器0

让红色LED在2秒间隔亮一次,目前配置的是1毫秒进一次中断,即中断2000次是2秒。那么设置一个全局变量加到2000就点灯。

程序:

/* 定义一个16位全局变量 用于计数 */

unsigned int cnt=0;

/* 定时器T0中断处理函数 */

void TM0_Isr() interrupt 1

{

cnt++;

if(cnt == 2000)

{

cnt = 0;

LED_R = !LED_R;

}

}


七:完整的程序贴上来

#include “stc8g.h”

#include “intrins.h”

/* 发光二极管引脚定义 */

sbit LED_R = P0^5; // 红色LED

sbit LED_Y = P0^6; // 黄色LED

sbit LED_G = P0^7; // 绿色LED

/* 定义一个16位全局变量 用于计数 */

unsigned int cnt=0;

/* 定时器T0中断处理函数 */

void TM0_Isr() interrupt 1

{

cnt++;

if(cnt == 2000)

{

cnt = 0;

LED_R = !LED_R;

}

}

/* 定时器T0初始化为1ms产生中断 @35MHz */

void Timer0Init(void) //1毫秒@35MHz

{

AUXR |= 0x80; //定时器时钟1T模式

TMOD &= 0xF0; //设置定时器模式

TL0 = 0x48; //设置定时初值

TH0 = 0x77; //设置定时初值

TF0 = 0; //清除TF0标志

TR0 = 1; //定时器0开始计时

ET0 = 1; //允许定时器T0溢出中断

EA = 1; // 打开总中断

}

/* 主函数 */

void main()

{

P0M0 = 0x00; //设置P0.0~P0.7为双向口模式

P0M1 = 0x00;

 

Timer0Init(); // 定时器T0初始化

 

while(1)

{

 

}

}