C51 定时器 TL0=(65536-50000)%256是怎么推导出来的?

本文介绍如何根据所需定时时间和单片机晶振频率计算定时器的初始值,通过具体实例展示了计算过程及其在代码中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文章1:如果你选的单片机的晶振一定,比如12MHZ来说吧,机器周期是1us,就是说每1us产生一次计数,就拿50ms来说,这是你想要的计时,意思是,对机器周期进行50000计数就可以得到我想要的,可T0是一个可以对机器周期能进行65536次计数,也就是说我想要的50MS不能让T0溢出,怎么办,那么先给这个定时器里面放些数,放多少,就是我们想要的50MS在加上一个多少就能等于65536,也就是65536和50000的差值,这个值就是我们说的初值。

      为什么除以256,因为我们的计时器是两个8位组成的,那么要把那些差值装进这两个8位,那么低8位最多能装256个机器周期,那么256计满了就用高8位的,就是说低8位满一次高8位加1,那么高8位装多少,低8位就满了几次,算法就是用差值除一下256取其整数,剩下的,就是还剩了小于256次数的就放在低8位,就是差值 的余数。如果我要放一个超过256的数,肯定是超过先放高八位,把剩下的部分放在低八位中了,TH0=(65536-50000)/256就是把TL0中放不下的部分放在TH0中,再把剩下的部分放在TH0中。

 void timer0() interrupt 1

{

TH0=(65536-50000)/256;

TL0=(65536-50000)%256;

flag++;

if(flag==20)//当定时到1秒时执行花括号里面的语句

{    }

}

(Fromhttp://bbs.ednchina.com/BLOG_ARTICLE_3012623.HTM


文章2:

其实很简单,不管你使用多大的晶振,使用51单片机,一般都是12分频出来,也就可以得出一个机器周期
机器周期=12/n(n指晶振频率),假设你要定时的时间为M
那么定时的初值为:
M/机器周期=初值;
TH0=(65536-初值)/256;         
TL0=(65536-初值)%256;
将(65536-初值)所得的值化成16进制,其高位就是TH0的值,低位为TL0的值
例如用12M晶振做1ms定时计算如下:
机器周期=12/12*10^6=1us(微秒)
定时初值=(1*10^-3)/(1*10^-6)=1000;
所以:TH0=(65536-1000)/256;(求模运算,即可求出高八位的值)
      TL0=(65536-1000)%256;(求余运算,因为低八位最大能装255)
将65536-1000=64536化为16进制为:0xFC18
TH0=0xFC;
TL0=0X18;

(Fromhttp://blog.sina.com.cn/s/blog_5134d7020100ey3i.html

#include <REGX52.H> //0.05 50 50000 sbit Add=P3^5; sbit Sub=P3^6; unsigned char num=20; unsigned char shi=12,fen=59,miao=59; unsigned char code duanxuan[]={ 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f }; void Display(); void shezhi(); void Delay(unsigned char x) { unsigned char i=0,j=0; for(i=0;i<110;i++) for(j=0;j<x;j++); } void T0_init() { TMOD=0X01; TH0=(65535-50000)/256; TL0=(65535-50000)%256; EA=1; ET0=1; TR0=1; } void T0_isr() interrupt 1 { TH0=(65535-50000)/256; TL0=(65535-50000)%256; num--; if(num==0) { num=20; miao--; } if(miao<0) { miao=59; fen--; } if(fen<0) { fen=59; shi--; } if(shi<0) { shi=23; } } void main() { T0_init(); while(1) { Display(); shezhi(); } } void Display() { P2=0x00;// P0=duanxuan[miao%10]; Delay(4); P2=0x04;// P0=duanxuan[miao/10]; Delay(4); P2=0x08;//-- P0=0X40; Delay(4); P2=0x0C;//-- P0=duanxuan[fen%10]; Delay(4); P2=0x10;//-- P0=duanxuan[fen/10]; Delay(4); P2=0x14;//-- P0=0X40; Delay(4); P2=0x18;//-- P0=duanxuan[shi%10]; Delay(4); P2=0x1C;//-- P0=duanxuan[shi/10]; Delay(4); } void shezhi() { if(Sub==0) { Delay(200); if(Sub==0) { shi--; Delay(200); } } }#include <REGX52.H> //0.05 50 50000 sbit Add=P3^5; sbit Sub=P3^6; unsigned char num=20; unsigned char shi=12,fen=59,miao=59; unsigned char code duanxuan[]={ 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f }; void Display(); void shezhi(); void Delay(unsigned char x) { unsigned char i=0,j=0; for(i=0;i<110;i++) for(j=0;j<x;j++); } void T0_init() { TMOD=0X01; TH0=(65535-50000)/256; TL0=(65535-50000)%256; EA=1; ET0=1; TR0=1; } void T0_isr() interrupt 1 { TH0=(65535-50000)/256; TL0=(65535-50000)%256; num--; if(num==0) { num=20; miao--; } if(miao<0) { miao=59; fen--; } if(fen<0) { fen=59; shi--; } if(shi<0) { shi=23; } } void main() { T0_init(); while(1) { Display(); shezhi(); } } void Display() { P2=0x00;// P0=duanxuan[miao%10]; Delay(4); P2=0x04;// P0=duanxuan[miao/10]; Delay(4); P2=0x08;//-- P0=0X40; Delay(4); P2=0x0C;//-- P0=duanxuan[fen%10]; Delay(4); P2=0x10;//-- P0=duanxuan[fen/10]; Delay(4); P2=0x14;//-- P0=0X40; Delay(4); P2=0x18;//-- P0=duanxuan[shi%10]; Delay(4); P2=0x1C;//-- P0=duanxuan[shi/10]; Delay(4); } void shezhi() { if(Sub==0) { Delay(200); if(Sub==0) { shi--; Delay(200); } } } 识别错误
06-24
#include <reg52.h> #define uint unsigned int #define uchar unsigned char sbit K1 = P3^2; // 按键K1 sbit DIG1 = P2^0; // 十位数码管位选 sbit DIG2 = P2^1; // 个位数码管位选 // 共阳数码管0-9段码表 uchar code segTable[] = { 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90 }; uchar second = 0; // 秒计数器 bit running = 0; // 运行标志 bit keyPressed = 0; // 按键标志 // 延时函数 void delay(uint t) { while(t--); } // 显示函数 void display(uchar num) { uchar shi = num / 10; // 十位 uchar ge = num % 10; // 个位 DIG1 = 1; DIG2 = 0; // 选中十位数码管 P0 = segTable[shi]; // 输出十位段码 delay(100); // 短暂延时 DIG1 = 0; DIG2 = 1; // 选中个位数码管 P0 = segTable[ge]; // 输出个位段码 delay(100); // 短暂延时 } // 定时器0初始化 void timer0Init() { TMOD = 0x01; // 定时器0工作方式1 TH0 = (65536 - 50000) / 256; // 50ms定时初值 TL0 = (65536 - 50000) % 256; ET0 = 1; // 允许定时器0中断 EA = 1; // 开启总中断 } // 主函数 void main() { timer0Init(); // 初始化定时器 while(1) { // 按键检测 if(K1 == 0) { // 按键按下 delay(1000); // 消抖 if(K1 == 0 && !keyPressed) { keyPressed = 1; // 设置按键标志 if(running) { // 停止计时 running = 0; TR0 = 0; // 关闭定时器 } else { // 开始/继续计时 running = 1; TR0 = 1; // 启动定时器 } } } else { keyPressed = 0; // 按键释放 } // 显示当前秒数 display(second); } } // 定时器0中断服务函数 void timer0() interrupt 1 { static uchar count = 0; // 中断计数 TH0 = (65536 - 50000) / 256; // 重装初值 TL0 = (65536 - 50000) % 256; count++; if(count == 20) { // 1秒到达(50ms*20=1000ms) count = 0; if(running) { second++; if(second >= 100) second = 0; // 99秒后归零 } } }
最新发布
06-24
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值