采用定时器/计数器 T0 对外部脉冲进行计数,每计数 10 个脉冲后,T0 转为定时工作方式。 定时 10s 后,又转为计数工作方式,如此循环不止。假定 AT89S51 单片机的晶体振荡器的频 率为 6MHz,请使用方式 1 实现,要求编写程序。
时间: 2024-03-24 15:38:38 浏览: 105
单片机原理及应用6:AT89S51单片机的定时器计数器.pptx
以下是一个使用方式 1 实现的 AT89S51 单片机程序,用于计数外部脉冲并定时 10 秒。请注意,此程序可能需要根据具体的硬件配置进行适当修改。
```c
#include <reg51.h>
#define FREQ 6000000L // 晶体振荡器频率
#define PULSES_PER_COUNT 10 // 每计数的脉冲数
#define COUNTS_PER_TIMER (FREQ / 12 / PULSES_PER_COUNT / 65536) // 每定时器计数的计数数
void timer0_init(void)
{
TMOD &= 0xF0; // 清零 T0 模式位
TMOD |= 0x01; // 设置 T0 为模式 1
TH0 = 0; // 初始化定时器高位
TL0 = 0; // 初始化定时器低位
TR0 = 1; // 启动定时器
}
void main(void)
{
unsigned long count = 0; // 计数器
unsigned char timer_count = 0; // 定时器计数器
unsigned char mode = 0; // 工作模式,0 为计数模式,1 为定时模式
timer0_init(); // 初始化定时器
while (1) {
if (TF0) { // 定时器溢出
TF0 = 0; // 清除溢出标志
TH0 = 0; // 重新初始化定时器高位
TL0 = 0; // 重新初始化定时器低位
timer_count++;
if (timer_count == COUNTS_PER_TIMER) { // 达到定时器计数数
timer_count = 0;
if (mode == 0) { // 切换到定时模式
mode = 1;
TR0 = 0; // 停止计数器
TH0 = 65536 - (10000 / 12) / 256; // 设置定时器高位,定时 10s
TL0 = 65536 - (10000 / 12) % 256; // 设置定时器低位
TR0 = 1; // 启动定时器
} else { // 切换到计数模式
mode = 0;
count = 0; // 重置计数器
TR0 = 1; // 启动计数器
}
}
} else { // 计数器计数
if (TF0 == 0 && TR0 == 1) { // 计数器未溢出且正在计数
if (TF0) { // 计数器溢出
TF0 = 0; // 清除溢出标志
count++; // 计数器加 1
}
}
if (count == PULSES_PER_COUNT) { // 达到每计数的脉冲数
count = 0; // 重置计数器
TR0 = 0; // 停止计数器
TH0 = 65536 - (10000 / 12) / 256; // 设置定时器高位,定时 10s
TL0 = 65536 - (10000 / 12) % 256; // 设置定时器低位
TR0 = 1; // 启动定时器
}
}
}
}
```
在该程序中,我们使用了定时器/计数器 T0 来计数外部脉冲并定时 10 秒。每计数 10 个脉冲后,T0 转为定时工作方式,定时 10s 后,又转为计数工作方式,如此循环不止。该程序的原理如下:
1. 初始化定时器/计数器 T0,使其工作在计数模式下。
2. 在每次计数器计数时,检查是否已经计数了 10 个脉冲。如果是,则停止计数器,并设置定时器 T0 的初值,使其工作在定时模式下,定时 10 秒后再次切换到计数模式。
3. 在每次定时器溢出时,检查是否已经定时了 10 秒。如果是,则停止定时器,并设置计数器 T0 的初值,使其工作在计数模式下,计数 10 个脉冲后再次切换到定时模式。
该程序可以根据具体的硬件配置进行适当修改,以确保其能够正确地工作。同时,程序中的一些常量(如晶体振荡器频率、每计数的脉冲数等)也可以根据需要进行修改。
阅读全文