51单片机延时0.1s
时间: 2023-07-30 12:10:54 浏览: 84
在51单片机中,可以使用定时器来实现延时。具体的实现方式如下:
1. 设置定时器的计数值,计算公式如下:
计数值 = (晶振频率 / 12) × 延时时间 × 1000 - 1
其中,晶振频率为单片机所接入的晶振频率,延时时间为所需延时的时间,单位为秒。例如,如果晶振频率为12MHz,需要延时0.1秒,则计数值为:
计数值 = (12MHz / 12) × 0.1 × 1000 - 1 = 9999
2. 设置定时器的工作模式为定时模式,并启动定时器。
3. 在定时器中断服务程序中进行计数器的累加,直到计数器的值达到设定的计数值为止,表示延时完成。
以下是一个基本的延时函数的代码示例:
```
void delay(unsigned int ms)
{
unsigned int i, j;
for (i = 0; i < ms; i++) {
for (j = 0; j < 120; j++) {
// 等待约1毫秒
}
}
}
```
该函数中的嵌套循环可以实现大约1毫秒的延时,调用该函数时传入所需延时的毫秒数即可实现延时功能。
相关问题
51单片机定时器定时0.1ms程序
51单片机的定时器如Timer1或Timer0可以用来实现毫秒级的定时,通常通过软件计数器配合中断的方式来达到高精度定时。下面是一个简单的使用Timer1作为定时器的例子,假设我们使用的是16位模式,定时时间为0.1ms(实际会因为系统时钟频率而有所不同,这里以8MHz为例计算):
```c
#include <reg52.h> // 包含51单片机头文件
// 设置定时器1的工作模式和初值
void timer1_init(void) {
TMOD = 0x01; // 设置TMOD为模式1,即16位自动重装定时器
TH1 = 0xFF; // 设置TH1寄存器为最大值减去计数值
TL1 = 0xFE; // 设置TL1寄存器为最大值减去计数值
}
// 定义外部中断服务函数,周期性地更新定时器
void interrupt() _at_ TI() { // 当T1溢出时触发中断
if (TF1 == 0) return; // 检查是否已溢出
TF1 = 0; // 清除溢出标志
TH1++; // 更新定时器的高字节
TL1++; // 更新定时器的低字节
if ((TH1 & 0xFF) == 0 && TL1 == 0xFE) { // 如果溢出,则达到0.1ms
// 这里处理0.1ms时间到了的逻辑,例如延时结束后开启某个操作
// ...
// 再设置定时器为新的初始值,继续计时
TH1 = 0xFF;
TL1 = 0xFE;
}
}
int main(void) {
timer1_init();
EA = 1; // 开启全局中断
ET1 = 1; // 开启Timer1的外部中断
TR1 = 1; // 启动Timer1
while(1); // 无限循环,等待定时器中断
}
```
51单片机写一个不用延时函数的流水灯,0.1s流转间隔,同时在数码管上显示1234,也不能使用延时,并且在CPU等待的时候,让CPU进入空闲模式
首先,我们需要了解单片机的时钟周期。以STC89C52RC为例,它的时钟频率是11.0592MHz,一个机器周期为12个时钟周期,即一个机器周期需要1.085us。
流水灯的实现方法是通过一个变量不断左移或右移,然后通过端口控制LED灯亮灭。在这个过程中,我们需要让程序在不占用CPU的情况下等待一定时间,以达到流水灯流动的效果。
为了不使用延时函数,我们可以利用定时器和中断来实现等待功能。具体实现方法如下:
1. 配置定时器,使其产生1ms的中断。由于一个机器周期为1.085us,我们可以设置定时器的初值为1000-12=988,这样当定时器计数器减到0时,正好1ms过去。
2. 在定时器中断中,将计数器减1,并判断是否等于0。如果等于0,则将流水灯的变量左移或右移一位,同时更新数码管显示的值。如果不等于0,则继续等待。
3. 在主函数中,使单片机进入空闲模式。空闲模式下,单片机不会执行任何指令,但定时器中断仍然可以正常工作。这样,程序就可以在不占用CPU的情况下等待一定时间。
下面是代码实现:
```c
#include <reg52.h>
sbit LED1 = P1^0; // 定义LED引脚
sbit LED2 = P1^1;
sbit LED3 = P1^2;
sbit LED4 = P1^3;
sbit DIG1 = P2^4; // 定义数码管引脚
sbit DIG2 = P2^5;
sbit DIG3 = P2^6;
sbit DIG4 = P2^7;
unsigned char led = 0x01; // 流水灯变量,初始为0000 0001
unsigned char dig = 1; // 数码管变量,初始为1
void timer0_init() // 定时器0初始化函数
{
TMOD |= 0x01; // 设置为模式1,16位定时器
TH0 = 0xfc; // 设置定时器初值,产生1ms中断
TL0 = 0x18;
ET0 = 1; // 开启定时器0中断
EA = 1; // 开启总中断
TR0 = 1; // 启动定时器0
}
void timer0_isr() interrupt 1 // 定时器0中断函数
{
TH0 = 0xfc; // 重新设置定时器初值
TL0 = 0x18;
if (--led == 0) // 流水灯变量左移或右移一位
{
led = 0x80;
dig++; // 更新数码管显示的值
if (dig > 4) dig = 1; // 数码管变量取值范围为1~4
}
switch (dig) // 数码管显示控制
{
case 1: DIG1 = 0; DIG2 = 1; DIG3 = 1; DIG4 = 1; P0 = 0x3f; break; // 显示1
case 2: DIG1 = 1; DIG2 = 0; DIG3 = 1; DIG4 = 1; P0 = 0x06; break; // 显示2
case 3: DIG1 = 1; DIG2 = 1; DIG3 = 0; DIG4 = 1; P0 = 0x5b; break; // 显示3
case 4: DIG1 = 1; DIG2 = 1; DIG3 = 1; DIG4 = 0; P0 = 0x4f; break; // 显示4
}
}
void main()
{
timer0_init(); // 初始化定时器0
while (1)
{
PCON |= 0x01; // 进入空闲模式
}
}
```
在以上代码中,我们利用定时器0产生1ms的中断,在中断函数中实现流水灯和数码管的控制,然后在主函数中让单片机进入空闲模式。这样,程序就可以在不占用CPU的情况下等待一定时间,同时实现流水灯和数码管的效果。
阅读全文