51单片机定时器/计数器疑惑
本人单片机还学得不精,在定时器这部分重复看了几遍,与平时网上所阅览的有所差异,心有疑惑,今向各位请教!~~问题应该不深奥,各位别见笑~~我在书上看到了如下:
当采用Mode0时:TL0=(8192-X)%32; TH0=(8192-X)/32;
当采用Mode1时:TL1=(65536-X)%256; TH1=(65536-X)/256;
当采用Mode2时:TL2=256-X; TH2=256-X;
当在Mode 0方式工作时,每次最多可计数8192,约8毫秒,若只计数5000,则为5毫秒,必须重复50次才延迟0.25秒钟(5m×50);
当在Mode 1方式工作时,每次最多可计数65536,约65毫秒,若只计数50000,则为50毫秒,必须重复5次才延迟0.25秒钟(50m×5);
当在Mode 2或Mode 3方式工作时,每次最多可计数256,约0.25毫秒,若只计数250,则为0.25毫秒,必须重复1000次才延迟0.25秒钟(0.25m×1000)。
举个简单例子:
/* ch07-5-2.c - 计时器实验2-中断方式-高低位灯互闪*/
//==声明区================================
#include <reg51.h>
#define LEDP1 //定义LED接至Port 1
#define count 50000 //T0(MODE 1)之计量值,约0.05秒
#define TH_M1 (65636-count)/256 // T0(Mode 1)计量高8位元
#define TL_M1 (65636-count)%256 // T0(Mode 1)计量低8位元
int IntCount=0; // 宣告IntCount变数,计算T0中断次数
//==主程序================================
main() //主程序开始
{ IE=0x82; // 启用T0中断
TMOD&= 0xf1;TMOD |= 0x01; // 设定T0为mode 1
TH0=TH_M1;TL0=TL_M1; // 设置T0计数量高8位元、低8位元
TR0=1; // 启动T0
LED=0xf0; // LED初值=1111 0000,右4灯亮
while(1); // 无穷循环,程序停滞
} //主程序结束
//== T0中断子程序- 每中断5次,LED反相================
void timer0(void) interrupt 1 // T0中断子程序开始
{ TH0=TH_M1;TL0=TL_M1; // 设置T0计数量高8位元、低8位元
if(++IntCount==5) // 若T0已中断5次数
{ IntCount=0; // 重新计次
LED^=0xff; // 输出相反
} //if叙述结束
} //T0中断子程序
在网上对于定时器初值是这么做的:
假如要求定时器的定时时间为500µs,那么则:
振荡频率为12MHz,则机器周期为1µs。
设定时初值为X,
(65536-X)×1µs=500µs
X=65036=0FE0CH
定时器的初值为:TH0=0FEH,TL0=0CH
比较二者的差异,我的疑问是:
1、两者的赋初值方法是都正确的么?哪个更有优势呢?
2、对于书上的写法,取商和取余赋值是什么原理呢?我一直都转不过脑筋。。。。
3、那个程序例子中,出现了两次的模式设置:
TMOD &= 0xf1;TMOD |= 0x01; // 设定T0为mode 1
这是为什么呢?
1、明显宏定义的好
2、取商和取余赋值是什么原理呢? 这是C语言的基本运算
3、出现了两次的模式设置是因为一次设置不完,还需要第二次。 2、对于书上的写法,取商和取余赋值是什么原理呢?我一直都转不过脑筋。。。。
回答这个问题,因为计数器初值是16位(2字节)的,
取余(初值%256)得到低8位65036%256=12(0x0c)
取商(初值/256) 得到高8位65036/256=254.046875 (但是结果保留整数,所以为254 即 0xfe)
这样明白? 特别强调的是除法向下取整不四舍五入 一般使用T0 Mode1.
把十六进制换算成二进制,按位与、按位或运算可求出TMOD值,从而知道使用哪个定时计数器及工作方式。ok? amfan 发表于 2013-2-2 16:52 static/image/common/back.gif
2、对于书上的写法,取商和取余赋值是什么原理呢?我一直都转不过脑筋。。。。
回答这个问题,因为计数器初 ...
我是不明白为什么这样算之后就刚好是TH和TL的值了,觉得挺巧妙的,省去了初值的计算 一匹狼 发表于 2013-2-12 20:57 static/image/common/back.gif
一般使用T0 Mode1.
把十六进制换算成二进制,按位与、按位或运算可求出TMOD值,从而知道使用哪个定时计数器 ...
嗯嗯,这一点我倒是明白,不过好像不在我的疑问当中 hhxb 发表于 2013-2-2 16:54 static/image/common/back.gif
特别强调的是除法向下取整不四舍五入
嗯嗯,谢谢 hhxb 发表于 2013-2-2 16:40 static/image/common/back.gif
1、明显宏定义的好
2、取商和取余赋值是什么原理呢? 这是C语言的基本运算
3、出现了两次的模式设置是因 ...
1、第一种,只要看你计数多少,就设定多少数值,第二种则需要经过公式计算才能赋初值,明显第一中更简便,为何还演变出第二种做法呢?所以应该有他的自身优势吧;
2、可能我没有说清楚问题,我想明白的是为什么取商的值就是TH的值,余数值就是TL的值;
3、要将定时器设置为TO的模式一,只要TMOD=0X01就行不是?何必这么麻烦呢; 2012dove 发表于 2013-2-13 12:56 static/image/common/back.gif
我是不明白为什么这样算之后就刚好是TH和TL的值了,觉得挺巧妙的,省去了初值的计算 ...
1.两种方法本质上一样,百度下c语言的宏定义你就明白了....
后者免敲宏定义这行代码,若不需要多个定时器用后者即可
2.
12MHz,12分频嘛,计数1次1us
计数50000次50ms,即0.05s
IntCount计数5次,0.25s
3.
TMOD默认为0x00;
0x00 & 0xf1后TMOD=0x00;
0x00 | 0x01 后TOMD=0x01;
其实直接TMOD=0x01或TMOD|=0x01; 没学过c语言么
这很基础的 想想就明白了 宏定义的好,移植方便 hhxb 发表于 2013-2-2 16:40 static/image/common/back.gif
1、明显宏定义的好
2、取商和取余赋值是什么原理呢? 这是C语言的基本运算
3、出现了两次的模式设置是因 ...
看着看着,突然有明白了~~谢谢!! 一匹狼 发表于 2013-2-13 15:21 static/image/common/back.gif
1.两种方法本质上一样,百度下c语言的宏定义你就明白了....
后者免敲宏定义这行代码,若不需要多个定时器 ...
你答不到我想要的东西,不过谢谢哈,现在自己有点明白了~~ TMOD &= 0xf1; //TMOD = TMOD & 0xF1
// 0xF1 = 1111 0001 保护定时器1的所有位和定时器0的模式设置
TMOD |= 0x01; // TMOD = TMOD | 0x01 设定T0为mode 1
页:
[1]