at89c51定时器延时
时间: 2023-11-23 20:06:13 浏览: 117
在单片机应用中,经常需要进行短时间的延时,而at89c51单片机可以通过定时器来实现延时。通过设置定时器的计数器和预分频器,可以实现不同精度和时间长度的延时。同时,也可以通过C语言程序来实现延时,通过循环等待的方式来实现一定时间的延时。在使用C语言实现延时时,可以通过Keil C工具的仿真功能来调整延迟量,从而得到较理想的结果。虽然使用汇编语言实现延时的方式具有较大的优越性,但是通过合理地运用C语言,也可以达到与汇编语言相近的精度。
相关问题
AT89C51单片软件延时10ms
在AT89C51单片机中实现10毫秒的软件延时,通常使用中断法或者是定时器T0配合中断的方式来实现,因为单片机的CPU速度很快,直接循环计数延时效率不高。以下是通过定时器T0实现的一个简单示例:
1. 首先,我们需要启用定时器T0并设置其工作在模式1(16位自动重装模式),计数从TH0=0,TL0=0开始。
```c
TMOD = 0x01; // 设置定时器T0为模式1
TH0 = 0xFD; // 对于10ms,设高8位为0b11111111,低8位需计算
TR0 = 1; // 启动定时器T0
```
2. 计算低8位的值。对于10ms,由于系统频率通常为12MHz(实际频率可能会有所不同,这里以12MHz为例),所以需要找到对应的时间周期。12MHz / (16 * 2) ≈ 7812.5us。为了得到10ms,即100000us,我们取7812.5us的整数倍接近100000us,例如取12次(12*7812.5=93750,然后加100000正好)。
```c
while(TL0 < 0x0E); // 当TL0等于0x0E时,表示计数满了12次,这时相当于延时了约10ms
```
3. 注意这只是一个简单的延时实现,实际应用中可能需要考虑中断的优先级以及处理其他任务的情况。
AT89C51通过定时器输出两路PWM波,并能通过4*4的矩阵按键调制两路的频率和占空比,给出C51代码
好的,下面是AT89C51通过定时器输出两路PWM波,并能通过4*4的矩阵按键调制两路的频率和占空比的C51代码:
```c
#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int
// 矩阵按键扫描函数
uchar keyscan()
{
uchar row, col;
uchar code keymap[16] = {0xee, 0xde, 0xbe, 0x7e, 0xed, 0xdd, 0xbd, 0x7d, 0xeb, 0xdb, 0xbb, 0x7b, 0xe7, 0xd7, 0xb7, 0x77};
P2 = 0x0f; // 将 P2 的低 4 位置 0
if (P2 != 0x0f) // 如果有按键按下
{
for (col = 0; col < 4; col++)
{
P2 = 0x0f;
P2 &= ~(0x01 << col); // 将第 col 列置 0
for (row = 0; row < 4; row++)
{
if ((P2 & (0x10 << row)) == 0) // 如果第 row 行为 0
{
return keymap[row * 4 + col]; // 返回按键编码
}
}
}
}
return 0xff; // 没有按键按下,返回 0xff
}
void timer0_init()
{
TMOD &= 0xf0; // 设置定时器 0 为模式 1
TMOD |= 0x01;
TH0 = 0xff; // 定时器初值
TL0 = 0x00;
ET0 = 1; // 打开定时器 0 中断
TR0 = 1; // 启动定时器 0
EA = 1; // 打开总中断开关
}
void main()
{
uchar key, freq1, freq2, duty1, duty2;
uint T1, T2;
timer0_init(); // 初始化定时器 0
while (1)
{
key = keyscan(); // 扫描矩阵按键
if (key != 0xff) // 如果有按键按下
{
freq1 = key >> 4; // 频率1为按键编码的高四位
freq2 = key & 0x0f; // 频率2为按键编码的低四位
T1 = 65536 - (11059200 / 12 / (freq1 * 50)); // 根据频率计算计数器初值
T2 = 65536 - (11059200 / 12 / (freq2 * 50));
TH0 = T1 >> 8; // 将计数器初值分别写入 TH0 和 TL0
TL0 = T1 & 0xff;
duty1 = keyscan(); // 再次扫描矩阵按键,得到占空比
duty1 = duty1 & 0x0f; // 占空比为按键编码的低四位
duty1 = duty1 * 10 + 10; // 计算占空比
duty1 = (duty1 * (T1 / 256)) / 100; // 根据占空比计算高电平时间
TH1 = T2 >> 8; // 将计数器初值分别写入 TH1 和 TL1
TL1 = T2 & 0xff;
duty2 = keyscan(); // 再次扫描矩阵按键,得到占空比
duty2 = duty2 >> 4; // 占空比为按键编码的高四位
duty2 = duty2 * 10 + 10; // 计算占空比
duty2 = (duty2 * (T2 / 256)) / 100; // 根据占空比计算高电平时间
TR1 = 1; // 启动定时器 1
while (TF1 == 0); // 等待定时器 1 溢出
TR1 = 0; // 关闭定时器 1
P1_0 = 1; // 输出 PWM1
delay(duty1);
P1_0 = 0;
delay(T1 / 256 - duty1);
P1_1 = 1; // 输出 PWM2
delay(duty2);
P1_1 = 0;
delay(T2 / 256 - duty2);
}
}
}
void timer0_isr() interrupt 1
{
static uchar cnt = 0;
TH0 = 0xff; // 重新赋值
TL0 = 0x00;
cnt++;
if (cnt == 20) // 20 次定时器 0 中断为 1 秒
{
cnt = 0;
P0 = ~P0; // 每秒翻转一次 P0
}
}
```
注意:上述代码中的 `delay()` 函数需要自行实现,可用 `for` 循环实现延时。同时,定时器 1 的初始化和中断处理函数也需要自行实现。
阅读全文