一、前言
C8051F340单片的定时器0有4种工作方式,分别是:
方式0——13 位计数器/定时器
方式1——16 位计数器/定时器
方式2——自动重装载的 8 位计数器/定时器
方式3——两个 8 位计数器/定时器
本文介绍工作在方式3的情况。
在方式 3 时,定时器 0 被配置两个独立的 8 位定时器,计数值分别在 TL0 和 TH0中。在 TL0 中的定时器使用 TCON 和 TMOD 中定时器 0 的控制/状态位:TR0、C/T0、GATE0 和 TF0。TL0 既可以使用系统时钟也可以使用一个外部输入信号作为时基。TH0 寄存器,由系统时钟或分频时钟提供时基。TH0 使用定时器 1 的运行控制位TR1,并在发生溢出时将定时器 1 的溢出标志位 TF1 置‘1’,所以它控制定时器 1 的中断。TH0相当于是使用的定时器1的中断。
二、程序展示
1、程序简介
通过定时器0计时,控制两个LED灯的闪烁,其中一个定时器控制一个LED100ms闪烁一次,一个定时器控制LED 30ms闪烁一次。使用单片机内部的12M晶振,进行硬件48分频,并进行软件8分频。
X * 48*8/12000000=0.001(1ms) X=31,也就是计数器需要计31次数,两个定时器0都可以计2的8次方次数,也就是256次,因为是从0开始计,最多计导255次,现需要计31次,则计时器的初始值应该为255-31=224.
2、头文件部分
#include <C8051F340.h>
#define SYSCLK 12000000/8 //软件进行8分频
#define TIMER0_PRESCALE 48 //通过寄存器设置的分频数
#define LED_CHG_RATE 100 //设置LED灯的闪烁频率,100代表100ms
#define TIMER0_TICK_PER_MS SYSCLK/TIMER0_PRESCALE/1000
#define REG1 TIMER0_TICK_PER_MS
#define REG2 0xFF-REG1
#define RELOAD_HIGH REG2 // 高位重载值
#define RELOAD_LOW REG2 // 低位重载值
sbit LED1 = P2^2; //通过P2.2输出驱动LED灯闪烁
sbit LED2 = P2^3; //通过P2.3输出驱动LED灯闪烁
void Port_Init (void); //端口初始化
void Timer0_Init (void); //定时器0初始化
3、主程序部分
main ()
{
PCA0MD &= ~0x40; // 关闭看门狗
Timer0_Init (); // 定时器0初始化
Port_Init (); // 端口初始化
EA = 1; // 允许中断
while (1);
}
4、端口初始化
void Port_Init (void)
{
XBR1 = 0x40;
P2MDOUT = 0x0C; //设置P2.2、P2.3推挽输出
}
5、定时器0初始化程序
void Timer0_Init(void)
{
TH0 = RELOAD_HIGH;
TL0 = RELOAD_LOW;
TMOD = 0x03; // 设置工作在13位模式
CKCON = 0x02; // 设置系统时钟48分频
ET0 = 1; // 定时器0终端允许
ET1 = 1; // 定时器0终端允许
TCON = 0x10; // 定时器0打开
}
6、定时器0中断程序
void Timer0_ISR (void) interrupt 1
{
static unsigned int low_counter=0;
TL0 = RELOAD_LOW; // 重载低位值
if((low_counter++) == LED1_CHG_RATE)
{
low_counter = 0; // 复位100次值
LED1 = ~LED1; //LED1闪烁
}
}
7、定时器1中断程序
void Timer1_ISR (void) interrupt 3
{
static unsigned int high_counter=0;
TH0 = TIMER0_RELOAD_HIGH; // 重载TH0的值
if((high_counter++) == LED2_TOGGLE_RATE)
{
high_counter = 0; // 复位计数30次的值
LED2 = ~LED2; // LED2闪烁
}
}
定时器0的TH0高位定时器使用的是定时器1的中断,所以定时器1是没有方式3的。