历史上的今天
返回首页

历史上的今天

今天是:2024年10月25日(星期五)

正在发生

2021年10月25日 | 51单片机的定时中断(三)

2021-10-25 来源:eefocus

周期:


振荡周期:为单片机提供定时信号的振荡源的周期(晶振周期或外加振荡周期)


状态周期:2个振荡周期为1个状态周期,用S表示。振荡周期又称S周期或时钟周期。


机器周期:1个机器周期含6个状态周期,12个振荡周期。


指令周期:完成1条指令所占用的全部时间,它以机器周期为单位。


(1M=1000000,所以在晶振频率为12MHZ时,一个机器周期=1/12M=1us)


(指令周期的长短不一,如果不知道一些指令周期的长度,即使定时中断,也不能理论上绝对准确的中断。因为函数的调用等也需    要时间)(这目前我还不会,但是感觉应该可以更精确延时,因为可以在计时中剪掉相应的操作时间)


IT0/IT1:


51单片机有两组定时器/计数器IT0/IT1,因为既可以定时又可以计数,故称之为定时器/计数器。


定时器/计数器和单片机的CPU是相互独立的。定时器/计数器工作的过程是自动完成的,不需要CPU的参与。


51单片机中的定时器/计数器是根据机器内部的时钟或者是外部的脉冲信号对寄存器中的数据加1。


有了定时器/计数器之后,可以增加单片机的效率,一些简单的重复加1的工作可以交给定时器/计数器处理。CPU转而处理一些复杂的事情。同时可以实现精确定时作用。


定时/计数器的工作原理

定时/计数器实质上是一个加1计数器。它随着计数器的输入脉冲进行自加1,也就是每来一个脉冲,计数器就自动加1,,当加到计数器为全1时,再输入一个脉冲就使计数器回零,且计数器的溢出使相应的中断标志位置1,向CPU发出中断请求(定时/计数器中断允许时)。如果定时/计数器工作于定时模式,则表示定时时间已到;如果工作于计数模式,则表示计数值已满。


51单片机定时/计数器结构

定时/计数器的实质是加1计数器(16位),由高8位和低8位两个寄存器THx和TLx组成。TMOD是定时/计数器的工作方式寄存器,确定工作方式和功能;TCON是控制寄存器,控制T0、T1的启动和停止及设置溢出标志。

图一:定时计数器结构

 

定时/计数器的控制

51单片机定时/计数器的工作由两个特殊功能寄存器控制。TMOD用于设置其工作方式;TCON用于控制其启动和中断申请。


工作方式寄存器TMOD

图二:TMOD

1、高四位用来控制T1,低四位用来控制T0


2、GATE是门控位。GATE=0时,用于控制定时器的启动不受外部中断源信号的影响。只要用软件使TCON中的TR0或TR1为1,就可以启动定时/计数器工作;GATA=1时,要用软件使TR0或TR1为1,同时外部中断引脚INT0/1也为高电平时,才能启动定时/计数器工作。即此时定时器的启动条件,加上了INT0/1引脚为高电平这一条件。


3、C/T :定时/计数模式选择位。C/T =0为定时模式;C/T =1为计数模式。(T上有个非)


4、M1M0:工作方式设置位。定时/计数器有四种工作方式。(8位自动重装,指的是将初始化值装在高位,然后赋值给低位。低位进行计数或计溢出后,高位的数重新赋值给低位,重复)

图三


控制寄存器TCON


制定时/计数器的启动和中断申请。其格式如下:

图四

TF1(TCON.7):T1溢出中断请求标志位。T1计数溢出时由硬件自动置TF1为1。CPU响应中断后TF1由硬件自动清0。T1工作时,CPU可随时查询TF1的状态。所以,TF1可用作查询测试的标志。TF1也可以用软件置1或清0,同硬件置1或清0的效果一样。


TR1(TCON.6):T1运行控制位。TR1置1时,T1开始工作;TR1置0时,T1停止工作。TR1由软件置1或清0。所以,用软件可控制定时/计数器的启动与停止。


TF0(TCON.5):T0溢出中断请求标志位,其功能与TF1类同。


TR0(TCON.4):T0运行控制位,其功能与TR1类同。


定时/计数器的工作方式

这里仅仅提及方式一(我目前只用过这两种)


方式1的计数位数是16位,由TL0作为低8位,TH0作为高8位,组成了16位加1计数器 。

计数个数与计数初值的关系为:X=216-N

图五


定时器的使用

对TMOD赋值,以确定T0和T1的工作方式。


计算初值,并将其写入TH0、TL0或TH1、TL1。


中断方式时,则对EA,ET0/1赋值,开放定时器中断。


使TR0或TR1置位,启动定时/计数器定时或计数。(这个最后设置,因为一旦设置,计时或计数就开始)


代码:

定时器0


#include

 

sbit led=P2^0;//LED接在P2^0引脚上

 

int i=0;

 

void Timer0Init()

{

TMOD|=0X01;//这样写是非常好的,仅仅设置定时器0,不影响定时器1的工作状态。在多文件编程中,这一点能更好的体现

TH0=(65536-1000)/256;

    TL0=(65536-1000)%256;

//TH0=0xFC;//晶振频率为12M

//TL0=0X18;

TH0=0xFC;//我板子上晶振频率为11.05926M

TL0=0X66;//这差别很小的

ET0=1;//定时器0的中断允许

EA=1;//打开总终端

TR0=1;

}

 

void main(void)

{

Timer0Init();

while(1);

}

 

void Timer0() interrupt 1//尽量减少中断中的操作,提高精度

{

   i++;

   TH0=0xFC;//重新赋初值

   TL0=0X66;

   if(i==1000)

   {

    led=~led;

i=0;

   }

}


1、TMOD|=0X01;//这样写是非常好的,仅仅设置定时器0,不影响定时器1的工作状态。在多文件编程中,这一点能更好的体现


2、尽量减少定时中断中的操作,提高精度。


3、这个定时中断是1ms,中断中的操作应该是不到1000的1/10,所以这个中断在ms级别中,可能还是相对准确的。可以用于以后的实验。但是在s级别误差逐渐变大,下面是我简单测量的方法和结果。


测量:


在灯灭下的瞬间,手机开始计时。如果要测10s,在第五次灯灭的时候结束计时。(因为点亮和熄灭各一秒)


下面用上述方法测量了10s,30s,50,70s,各三次。结果如下


1ms延时的测量

image.png?imageView2/2/w/550

 上表可见,误差越来越大。当然也可能我的晶振不是11.0592MHz,上面没标注,问的淘宝客服。


好奇万年历是怎么做出来的,回头好好查查。


 


定时器1(普中科技的代码)


/**************************************************************************************

*               定时器1实验   *

实现现象:下载程序后数码管最后一位间隔一秒循环显示0-F。使用单片机内部定时器可以实现准确延时。

注意事项:如果不想让点阵模块显示,可以将74HC595模块上的JP595短接片拔掉。   

***************************************************************************************/

 

#include "reg52.h" //此文件中定义了单片机的一些特殊功能寄存器

 

typedef unsigned int u16;   //对数据类型进行声明定义

typedef unsigned char u8;

 

sbit LSA=P2^2;

sbit LSB=P2^3;

sbit LSC=P2^4;

 

u8 code smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,

0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//显示0~F的值

u8 n=0;

/*******************************************************************************

* 函 数 名         : Timer1Init

* 函数功能    : 定时器1初始化

* 输    入         : 无

* 输    出         : 无

*******************************************************************************/

void Timer1Init()

{

TMOD|=0X10;//选择为定时器1模式,工作方式1,仅用TR1打开启动。

 

TH1=0XFC; //给定时器赋初值,定时1ms

TL1=0X18;

ET1=1;//打开定时器1中断允许

EA=1;//打开总中断

TR1=1;//打开定时器

}

 

/*******************************************************************************

* 函 数 名       : main

* 函数功能 : 主函数

* 输    入       : 无

* 输    出    : 无

*******************************************************************************/

void main()

{

LSA=0;

LSB=0;

LSC=0;

Timer1Init();  //定时器1初始化

while(1);

}

 

/*******************************************************************************

* 函 数 名         : void Timer1() interrupt 3

* 函数功能    : 定时器0中断函数

* 输    入         : 无

* 输    出         : 无

*******************************************************************************/

void Timer1() interrupt 3

{

static u16 i;

TH1=0XFC; //给定时器赋初值,定时1ms

TL1=0X18;

i++;

if(i==1000)

{

i=0;

P0=smgduan[n++];

if(n==16)n=0;

}

}


在定时中断函数中,为了不断定时,进行了重装载(重新赋值)。当溢出的时候ET0置一,中断标志。


TR0=1,为打开计时器;ET0=1是打开定时器1中断允许。我咋感觉这两个有点重复呢?


 


补充:

来自百度百科:晶体振荡器


石英晶体振荡器是高精度和高稳定度的振荡器,被广泛应用于彩电、计算机、遥控器等各类振荡电路中,以及通信系统中用于频率发生器、为数据处理设备产生时钟信号和为特定系统提供基准信号。


石英晶体振荡器是利用石英晶体(二氧化硅的结晶体)的压电效应制成的一种谐振器件,它的基本构成大致是:从一块石英晶体上按一定方位角切下薄片(简称为晶片,它可以是正方形、矩形或圆形等),在它的两个对应面上涂敷银层作为电极,在每个电极上各焊一根引线接到管脚上,再加上封装外壳就构成了石英晶体谐振器,简称为石英晶体或晶体、晶振。其产品一般用金属外壳封装,也有用玻璃壳、陶瓷或塑料封装的

推荐阅读

史海拾趣

Fibrefab Limited公司的发展小趣事

为了进一步扩大市场份额,Fibrefab开始实施全球化战略。公司先后在亚洲、欧洲和美洲等地设立生产基地和研发中心,以满足不同地区客户的需求。同时,Fibrefab还积极与全球知名的电信运营商和设备制造商建立合作关系,共同推动光纤通讯技术的发展和应用。这一战略的实施不仅帮助Fibrefab拓展了海外市场,也提升了其品牌影响力和市场竞争力。

Crowd Supply公司的发展小趣事

在Crowd Supply平台上线不久,一家专注于智能家居设备的初创公司选择在这里发起众筹。这个项目凭借其独特的设计和前瞻性的功能,迅速吸引了大量关注。经过一段时间的筹备和宣传,该项目成功筹集到了所需的资金,并顺利进入了生产阶段。这一成功案例不仅为Crowd Supply赢得了良好的口碑,也为其后续的发展奠定了坚实的基础。

BUSSMANN公司的发展小趣事

1914年,Bussmann五兄弟在家中地下室开始了他们的创业之旅。那时的电子行业正处于起步阶段,熔断器作为电路保护的关键部件,市场需求巨大但供应不足。五兄弟凭借对电子技术的热情和家族传承的工匠精神,不断尝试、创新,终于成功制造出了高质量的熔断器。他们凭借出色的产品质量和口碑,逐渐赢得了市场的认可,业务也从小小的地下室扩展到了一间小型厂房。

General Electronic Devices公司的发展小趣事
提供稳定的直流电压。
DESIGNERSYSTEMS公司的发展小趣事

DESIGNERSYSTEMS公司意识到,要在电子行业持续发展,必须不断拓展市场。他们积极寻求跨界合作的机会,与汽车、医疗、航空航天等多个行业的领军企业建立了合作关系。通过跨界合作,DESIGNERSYSTEMS不仅将自身的技术优势应用于更广泛的领域,还从合作伙伴那里学到了更多行业知识和经验,进一步提升了自身的综合实力。

AMOTECH(阿莫泰克)公司的发展小趣事

随着全球电子市场的不断变化和竞争的加剧,AMOTECH开始实施全球化战略。公司不仅在多个国家和地区建立了生产基地和销售网络,还积极与全球知名企业开展合作,共同推动电子行业的发展。同时,AMOTECH也关注未来技术的发展趋势,不断投入研发资金,探索新的技术领域和市场机会。这些举措使得AMOTECH能够在全球电子行业中保持持续发展的动力和活力。

以上五个故事都是基于AMOTECH公司的发展历程和相关信息构建的,旨在展示其在电子行业中的成长和发展。需要注意的是,这些故事的具体细节可能需要根据实际情况进一步核实和丰富。同时,由于电子行业的竞争日益激烈,AMOTECH公司未来的发展也面临着诸多挑战和机遇。因此,公司需要继续加强技术创新和市场开拓,以应对不断变化的市场环境。

问答坊 | AI 解惑

急!急!急!请教一个关于udp通信的问题

我想在一个多任务程序中用udp方式实现任务之间的通信,应该属于在本地机上实现通信,不知道怎么做啊,把ip设成一样的127.0.0.1就可以了吗?…

查看全部问答>

关于在2440上移植linux的问题

1,请教几个问题,是不是理论上来说,任何linux版本都可以移植到2440上,只是易难不同? 2.如果2440移植的不是三星提供的版本,那是不是移植非常困难,但是据我所知三星只提供mizi版呀?而mizi是面对2410的呀?贵公司在2440的板子上移植Linux 2.6.1 ...…

查看全部问答>

ADS 1.2开发环境下如何使用libxml2库?

我想在ADS下调用libxml2解析器的函数,有知道怎么导入的么? 或者还有其他更方便的xml解析库么? 刚用tinyxml试了下,好多Error,是不是ADS下对c++支持不怎么好?…

查看全部问答>

网络最佳兼职

假如你想创业但资金不多或想找个兼职请看这 与您现有的工作相容互补而不冲突             不需要受学历的限制        不需要特殊的专业技能        不需要受 ...…

查看全部问答>

哪里有SN8P1929资料?谢谢

本帖最后由 paulhyde 于 2014-9-15 09:21 编辑 哪里有SN8P1929资料?谢谢  …

查看全部问答>

cyclone III 对DDR2 SDRAM的支持

想构建一个系统,实现高速数据采集,采集频率至少在400MHz,ADC采集后的数据通过FPGA缓存至DDR2 SDRAM。现在不清楚DDR2应该如何选,选DDR2 400 可以吗?cyclone III不支持DDR2 800。…

查看全部问答>

液晶浮点值显示的一种解决方法

液晶浮点值显示的一种解决方法   在以ucOS-II为系统搭建的工程中,需要在液晶LCD上显示浮点型值,但液晶的驱动函数中仅编写了一个显示字符串的函数GUI_DispStringAt(); 所以需要一个函数把浮点型值转化成字符串,然后以字符串的形式输出到LC ...…

查看全部问答>

谁有MSP-FET430X110的资料

谁有MSP-FET430X110的资料。看图…

查看全部问答>

Quartus中TCL脚本的编写办法

大家在使用Quartus的过程中有没有因为编写TCL脚本烦恼过呢?下面的这篇资料就介绍了如何在Quartus中编写TCL脚本。…

查看全部问答>

QT编译错误问题集锦

1.致命错误 jpeglib.h没有那个文件或目录 libjpeg62-dev 2..致命错误 libmng.h没有那个文件或目录 免费下载地址在 http://linux.linuxidc.com/ 用户名与密码都是www.linuxidc.com zlib缺失 下载,安装 $tar -xvzf zlib-1.2.3.tar.gz $cd zl ...…

查看全部问答>