51微控制器计时器的概述
计时/计数器是电路的脉冲计数器。当计数脉冲来自微控制器的内部机器周期时,我们被用来称其为计时器,当计数脉冲来自微控制器外的输入信号时,它称为计数器。 8051系列微控制器在芯片上集成了两个可编程的计时/计数器,称为“定时/计数器0”(T0)和Timing/Counter 1(T1),它们都具有定时和计数函数。
这两个定时计数器可以独立配置为计时器或计数器。当配置为计时器时,运行一段时间后将生成溢出中断。当配置为计数器时,如果在微控制器的外部中断引脚上检测到脉冲信号,则计数器将增加1,并且当达到预设事件的数量时将生成中断事件。
51微控制器的定时计数器由内部寄存器和外部引脚组成,T0(P3.4)引脚和T1(P3.5)引脚用于接收外部脉冲信号。
51个微控制器的52个子系列还具有16位的计数计数器T2,这与这两个计数器大不相同。 T2的最常见功能是用作串行端口的波特率发生器。我们将稍后解释这部分。
51微控制器通过操作相应的寄存器实现了定时计数器的控制。这些寄存器包括工作模式控制寄存器TMOD(计时器模式寄存器)和控制寄存器TCON(计时器控制寄存器)。此外,T0和T1分别具有两个8位数据寄存器TH0,TL0,TH1和TL1。
TMOD是正时计数器的工作模式控制寄存器。可以通过更改T0和T1的工作模式来更改寄存器的操作。该寄存器的内部结构和描述如下图所示。此寄存器不支持BIT地址,并且在MicroController重置后清除。
TCON是定时计数器控制寄存器。在解释外部中断时,我们已经在上一节中介绍了它。其内部结构显示在表下的下图中。重置51个微控制器后,清除所有位。
TH0,TL0/TH1和TL1分别是T0/T1的高/低寄存器,并且都是8位。当定时计数器接收驱动程序事件(定时,计数)时,相应数据寄存器的内容增加了1。当数据寄存器的值达到最大值时,将生成溢出中断。重置微控制器后,所有寄存器的值都将初始化为0x00,并且这些寄存器都不能被压缩。
51微控制器计时器的工作原理
正时函数:通过计数计数来实现正时函数。计数脉冲来自微控制器,每个机器周期都会生成1个计数脉冲,也就是说,每个机器周期的计数器增加了1个。由于1个机器周期等于12个振荡脉冲循环,因此计数器的计数频率为振荡器频率的1/12。如果晶体振荡器的频率为fosc = 12MHz,则计数器的计数频率为fcont = fosc×1/12,即1MHz,即,计数器添加至每微秒1。这样,微控制器的时序函数是计算微控制器的机器循环数。从中,我们可以看到计数器的计数脉冲周期是:
t = 1/fcont = 1/(fosc×1/12)= 12/fosc
在公式中,FOSC是微控制器振荡器的频率。 FCONT是计数脉冲的频率,FCONT = FOSC /12。在实际应用中,可以根据计数值计算时间安排时间,也可以根据计时时间要求计算计数器的初始值。
微控制器的计时器用于定时,定时时间取决于计数初始值和所选计数器的长度(例如8位,13位或16位)。
计数函数:计数函数是计数外部事件。外部事件的出现由输入脉冲表示,因此计数函数基本上是计数外部输入脉冲。 STC89系列微控制器的T0(P3.4),T1(P3.5)或T2(P1.0)信号引脚用作计数器的外部计数输入端子。当外部输入脉冲信号从1到0产生负跳跃时,计数器值会增加1。
在计数模式下,计数器在每个机器周期的S5P2期间对外部脉冲输入进行采样。如果在第一个机器周期中对高级“ 1”进行采样,并且在第二个机器周期中对有效的负跳跃脉冲进行采样,即低级“ 0”,则计数器在第三台机器周期的S3P1中增加1。可以从中可以看出,需要2个机循环才能将负跳跃计数脉冲从“ 1”到“ 0”,即24振荡器循环,因此计数器的最大计数频率为fcont = fosc = fosc×1/24。例如,如果微控制器的工作频率为12MHz,则最高采样频率为0.5MHz。
外部脉冲的占空比没有限制,但是必须将高和低水平的外部计数脉冲保存在一个以上的机器周期中,以确保在更改之前至少对给定水平进行采样一次。
51微控制器计时器模式设置
51个微控制器T0和T1计时器有4个模式,由TMOD寄存器中间的两个位M1和M0的设置控制。寄存器配置的操作模式如下图:
接下来,让我们看一下这些模式的设置和功能。
工作模式0:当M1和M0设置为“ 00”时,计时器在工作模式0中工作。目前,计时计数器的内部结构在图中显示。
在工作模式0中,计时器的内部计数值为13位,由8位TH0/TH1和TL0/TL1的下部5位组成;当TL0/TL1溢出时,它将携带到TH0/TH1,而TH0/TH1溢出时,会发生相应的溢出中断。工作模式下的驱动程序事件的来源由门位和C/T#位控制。
工作模式1:当M1和M0设置为“ 01”时,计时器在工作模式1中工作。此时,计时计数器的内部结构在图中显示。
与工作模式0相比,工作模式1之间的唯一差异是此时内部计数器的宽度为16位,分别由8位Th0/Th1和8位TL0/TL1组成。驱动程序事件的溢出方法以及源和工作模式相同。 51系列微控制器的定时计数器通过添加1来使用计数方法,即,当收到驱动程序事件时,计数器会增加1,并且当计数器溢出,生成相应的中断请求时,并生成了第一个驱动程序事件,并且会产生中断请求。
51接收驾驶员事件后,计数器增加了1,并且当计数器溢出时,会生成相应的中断请求。在正时模式下,定时计数器的驾驶事件是微控制器的机器周期,即外部时钟频率的1/12。根据计时器的工作原理,在工作模式0和工作模式1中的最大时间长度t被计算为:
通过将初始化值分配给定时计数器的数据寄存器,计时计数器可以从0到最大正时长度获得任何选定的时序长度。初始化值n的计算公式如下:
注意:正时计数器的工作模式0和工作模式1没有自动重新加载初始化值的功能,因此,如果要循环以获得一定的时序长度,则必须在启动计时器之前重新定位数据寄存器。这通常是在中断服务程序中完成的。
工作模式2:当M1和M0设置为“ 10”时,计时器在工作模式2中工作。目前,计时计数器的内部结构在图中显示。
定时计数器的工作模式2与前两个工作模式大不相同。在工作模式2中8位计数器的初始化值可以自动重新加载。在工作模式2中,TL0/TL1是一个独立的8位计数器,TH0/TH1用于存储时间常数。当T0/T1产生溢流中断时,TH0/TH1中的初始化值会自动加载到TL0/TL1中。这种方法可以大大减少程序的工作量,但其定时长度也大大降低了。在更多应用程序的情况下,用作串行端口的较短重复计时或波特率发生器。
工作模式3:当M1和M0设置为“ 11”时,计时器在工作模式3中工作。此时,计时计数器的内部结构如图所示。
以这种工作方式,T0分为两个独立的8位计数器TH0和TL0。 TL0使用T0自己的控制和中断资源,而TH0占据T1的TR1和TF1作为起始控制位和溢出标志。在这种情况下,T1将停止运行,其数据寄存器将保持当前值,因此将T0设置为工作模式3也可以关闭T1时正时计数器而不是重置TR1。
下一个
51微控制器计时器中断
51系列微控制器集成了两个计时器/计数器,分别提供了两个定时中断来源:TF0和TF1。
TF0中断,计时器/计数器0中断请求,中断请求号为1。
TF1中断,计时器/计数1中断请求,中断请求号为3。
当51微控制器的中断控制寄存器中的EA位和ET0/ET1设置为“ 1”时,启用了正时计数器0/1的中断。在此状态下,如果计数溢出事件发生在计时计数器0/1中,则将触发正时计数器中断事件。可以通过在中断优先寄存器IP中修改PT0/PT1位来增加计时计数器的中断优先级。 MCS-51微控制器的定时计数器中断处理函数的结构如下:
void函数名称(void)中断中断矢量号(使用工作组寄存器)
//中断代码
51微控制器计时器计数功能的应用
现在,我们设计了一个简单的电路来练习如何使用计时器。
在图中显示的电路中,我们将键K5连接到对应于T0的外部脉冲引脚,以测试计时器的计数函数。
正常计数器:P3.4的水平变化后,计数器是积累的。如果将初始计数值设置为0xFF,则每个按键之后,计数器将溢出,并设置标志位。在程序中,通过扫描计数器标志位状态来切换数字。
/*
*这是计时器计数应用程序
*目的是使用计时器计数函数捕获计数
*/
#包括
#包括
typedef unsigned char u8;
typedef unsigned int u16;
u8 data_l,data_h;
u8 num = 0;
u8代码num_codelist [10] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
void延迟(U8 ms);
void count_func(void);
void data_init(void);
void t0_init(void);
void显示(void);
空间主(void)
t0_init();
而(1)
count_func();
data_init();
展示();
空隙延迟(U8 ms)
u8 i,j;
对于(i = 0; i
for(j = 0; j
void data_init(void)
data_l = num;
data_h = num/10;
空隙显示(void)
p2 = 0xfe;
p0 = num_codelist [data_h];
延迟(1);
p2 = 0xfd;
p0 = num_codelist [data_l];
延迟(1);
void count_func(void)
//查询标志位
如果(1 == TF0)
th0 = 0xff;
tl0 = 0xff;
如果(20 == num)
num = 0;
别的
num ++;
TF0 = 0;
void t0_init(void)
//将计时器0设置为模式2
tmod = 0x05;
//设置初始计数值(模式2具有自动重新安装)
th0 = 0xff;
tl0 = 0xff;
//中断用法设置,只有计时器在此处不使用中断函数
ET0 = 0;
tr0 = 1;
EA = 0;
中断计数器:此处的操作原理类似于上述普通程序。中断已启用,因此无需执行循环扫描操作。计时器中断是计数的。捕获P3.4级别更改后,计数器增加1。当数据寄存器值溢出时,可以在中断中处理中断。
/*
*这是计时器中断计数应用程序
*目的是使用计时器中断函数来计数
*/
#包括
#包括
typedef unsigned char u8;
typedef unsigned int u16;
u8 data_l,data_h;
u8 num = 0;
u8代码num_codelist [10] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
void延迟(U8 ms);
// void count_func(void);
void data_init(void);
void t0_init(void);
void显示(void);
空间主(void)
t0_init();
而(1)
data_init();
展示();
空隙延迟(U8 ms)
u8 i,j;
对于(i = 0; i
for(j = 0; j
void data_init(void)
data_l = num;
data_h = num/10;
空隙显示(void)
p2 = 0xfe;
p0 = num_codelist [data_h];
延迟(1);
p2 = 0xfd;
p0 = num_codelist [data_l];
延迟(1);
void t0_init(void)
//将计时器0设置为模式2
tmod = 0x05;
//设置初始计数值
th0 = 0xff;
tl0 = 0xff;
//中断使用设置,启用中断
ET0 = 1;
tr0 = 1;
EA = 1;
// void count_func(void)
// {
// if(1 == tf0)//如果查询溢出
// {
// th0 = 0xff; //重新分配值
// tl0 = 0xff;
// if(99 == num)
// {
// num = 0;
//}
// 别的
// {
// num ++;
//}
// tf0 = 0;
//}
//}
void count_func(void)中断1
//重新分配值
th0 = 0xff;
tl0 = 0xff;
/////这个位将在中断中清除,因此您无需写这句话
// tf0 = 0;
// //这等同于删除按钮,并且在使用时适当地使用它。
//延迟(15);
//查询外部输入脉冲的更改
如果(0 == T0)
如果(20 == num)
num = 0;
别的
num ++;
这两个程序中的很大一部分是相同的。区别在于计数处理部分。第一个程序不使用中断。我们定义一个void count_func(void)。在第二个程序中,我们使用计时器中断。中断函数是void count_func(void)中断1。程序之间的主要区别在于,这两个函数void count_func(void)是需要定义,解释和调用的普通函数,而void count_func(void)中断1是一个中断函数。它只需要定义。我们刚才提到的两个函数之间的其他函数差异。一种是不断扫描主函数循环中的寄存器标志位,另一个是在中断期间查询销钉状态。其他程序段相对简单且易于理解。让我在此处简要解释:void data_init(void)函数单一和十个显示数据。 void Display(void)是数字管显示处理功能。我之前在谈论数字管时介绍了它,但是在这里,我只是将其包装到一个函数中。 void t0_init(void)此函数是计时器T0的初始化函数,其中包括计时器模式,计数初始值,中断和其他设置。如果您不了解上述程序,则可以留言或分析参考材料。最后,让我们看一下电路模拟情况。
两个程序实现的功能都是相同的。现在考虑使用计数函数在使用计数函数时是否通过一些特殊处理(例如将初始计数值设置为最大值0xFF)的中断函数非常相似,与前面提到的外部引脚p3.3和p3.4的中断非常相似。如果按键,则会产生一个中断。因此,如果某些程序需要多个外部中断,并且微控制器没有太多的中断引脚,则可以使用此方法来增加微控制器函数。当然,这都是不合时宜的。当您真正开发时,您可能不会使用此微控制器。当前的微控制器功能强大!但这是开发人员应该拥有的一种想法,这并不意味着当您想到某种方法时,您可以派上用场,但是有必要在日常生活中积累一些“棘手的技巧”,如果您有一天使用它,该怎么办!也许您的软件优化之一会节省公司的产品很多。如果它是一种每月产量为N千或n千或更高输出的产品,那么老板如果不给您加薪,谁会给您加薪呢?对于那些有这种想法的人,无论他们拥有什么地位,我都会像对待自己的孩子一样对待自己的工作,我认为如果他们见面,就值得成为合作伙伴,并且他们可以直接提供股票以共同创造未来。这是你的个人。从某种意义上说,工作能力是工作场所的信誉,声誉是市场的硬币,声誉也是真正的财富代码。当我们工作时,我们会获得良好的薪水,因为老板认识到您所做的工作,我们发现名人可以认可该产品。当我们选择它时,我们很可能会相信那个名人。对于具有一定声誉水平的产品,它已成为一种信誉。就像股市一样,购买某种股票的主要原因是您已经研究了公司并得出结论,即您信任公司。以上是我的个人分析。当然,并不是每个人(老板)会这样认为,但是我认为,如果您真正信任员工,那么就业关系可以通过与规则和合同的合作关系来取得更好的结果。这是一种相互信任的机制。这些都是我对过去“海”出现的回顾的真实想法,但是过去“回头看不起”,所以我不会谈论这个故事。如果将来有机会这样做,我将再次沟通。我将在5年或10年内再次阅读这段话,也许到那时我将不再成为“权力指挥官”。
51微控制器计时器计时功能的应用
通过以上两个例程,您应该能够掌握计时器计数函数。验证您是否掌握的最快方法是键入代码并自己运行以查看结果是否匹配。如果您在键入代码后自己运行代码,或者实验板上没有结果,请记住根据程序仔细检查它以查看出了什么问题。
接下来,我们将继续介绍计时器的计时函数。我们希望查看一块代码,我们可以尝试查看是否可以在不查看后续分析的情况下阅读程序的结果。
/*
*这是计时器的计时申请
*目的是使用计时器计时模式来控制数字管和LED显示
*/
#包括
#包括
typedef unsigned char u8;
typedef unsigned int u16;
u8 data_l,data_h;
U8 T0_CNT = 0;
u8 t0_s = 0;
u8 t1_cnt = 0;
u8 crol = 0xfe;
u8代码num_codelist [10] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
void延迟(U8 ms);
void data_init(void);
void Timer_init(void);
void显示(void);
空间主(void)
timer_init();
p1 = crol;
而(1)
data_init();
展示();
空隙延迟(U8 ms)
u8 i,j;
对于(i = 0; i
for(j = 0; j
void data_init(void)
data_l = t0_s;
data_h = t0_s/10;
空隙显示(void)
p2 = 0xfe;
p0 = num_codelist [data_h];
延迟(1);
p2 = 0xfd;
p0 = num_codelist [data_l];
延迟(1);
void Timer_init(void)
//启用中断主开关
EA = 1;
//启用计时器中断
ET0 = 1;
ET1 = 1;
//设置工作模式1
tmod = 0x11;
//设置计时器0时间50ms
th0 =(65536-50000)/256;
TL0 =(65536-50000)%256;
//设置时间1时间50ms
th1 =(65536-50000)/256;
th1 =(65536-50000)%256;
//设置控制寄存器:启动计时器
tr0 = 1;
tr1 = 1;
void t0_func(void)中断1
//重新分配值
th0 =(65536-50000)/256;
TL0 =(65536-50000)%256;
//时间1s
t0_cnt ++;
if(20 == t0_cnt)
t0_cnt = 0;
t0_s ++;
如果(60 == t0_s)
t0_s = 0;
void t1_func(void)中断3
//重新分配值
th1 =(65536-50000)/256;
TL1 =(65536-50000)%256;
//时间0.5s
t1_cnt ++;
如果(5 == T1_CNT)
t1_cnt = 0;
//轻偏
crol = _crol_(Crol,1);
p1 = crol;
该程序的功能是使用Timing T0来控制数字管以更改每秒的数字,并使用Timer T1控制LED,以每秒4个灯光进行移动和点亮4个灯。
让我们看一下首先运行的程序的结果。
让我们立即分析该程序。该程序总体上是非常基本的。他们中的许多人被封锁了很多次。让我们主要介绍几个新功能。
void Timer_init(void)是计时器T0和T1的初始化函数,其中包含中断控制位配置,数据寄存器初始化分配和计时器开关设置。在这里,计时器T0和T1设置为模式1,即16位计时器函数。在此模式下,计时器数据寄存器没有自动重新安装函数,因此必须在每个中断后执行初始值操作。计时器中断中有此代码。计数是由上一个内容中的公式获得的。这是每50ms中断的设置。
许多初学者必须不了解计算初始值的观点,因此他们需要阅读更多信息。该原理实际上很简单。 51个微控制器的计算器计数向上计数,即,从0〜是16位设置的计时器数据寄存器的最大值,因此为0xffff(十进制为65535)。计数到0xffff时,再次记住此数字并溢出,从而导致溢出中断。目前,在中断函数中,我们重新分配数据寄存器程序并重新值。头开始计数,因此最大定时时间是0xffff机循环。 51个微控制器的机器周期为12个时钟周期。如果使用12m晶体振荡器,则只有一个机循环对应于1US。如果我们只需要计时1US数据寄存器,则将值0xFFFF分配给数据寄存器,即65536-1,一个机器周期后将发生中断。如果时间为2U,则将设置为65536-2,依此类推。
void t0_func(void)中断1此函数是计时器0的中断函数。首先,将初始值分配给计时器数据寄存器,然后设置一个1秒的累积技术操作,以便每隔第二次添加一个变量t0_s,然后在添加60s时清除它。然后,再次计数,数字管将显示当前的第二个值。
void t1_func(void)中断3此函数是计时器T1中断函数。在这里,设置为0.25s的LED照明移动操作。
此程序的主要内容在这里共享。如果您不明白,则可以及时留言,以便您也可以与所有人分析您的疑问。
,有
结论:
51微控制器的计时器是非常重要的部分,对于其他微控制器也是如此。计时器是项目开发必不可少的一部分,也非常灵活地使用,因此您必须精通使用它。
有关上一节中矩阵键的参考测试代码,请参见第二篇文章的内容。
添加代码,这是另外10,000个单词的长篇文章。写作并不容易。如果您已经阅读了,请将其转发,收集或喜欢。感谢您的支持!