51pic单片机定时器中断主函数较短,定时中断设定的定时时间较长。是不是主函数一直重复运行?

捷配欢迎您!
微信扫一扫关注我们
当前位置:&>>&&>>&&>>&跟我学51单片机(二):单片机内部定时/计数器和中断系统
  上讲通过讲述用控制一个外部的LED闪烁实验来向读者介绍了单片机的工作原理与开发流程。这一讲将介绍单片机内部非常重要的两个资源――定时/ 计数器和中断系统。通过该讲,读者可以掌握的工作原理和单片机的中断系统。
  从而设计定时器计数程序和中断服务程序。
  一、原理简介
  首先让我们举闹钟为例,将它定时在一分钟后闹铃,这就需要秒针走一圈(60 次)。即一分钟时间转化为秒针走的次数,也就是计数的次数,计数到了60 次然后闹铃,而每一次计数的时间是1 秒。
  单片机内部的定时/ 计数器跟闹钟类似,可以通过编程来设定要定时的时间、定时时间到了进行相应的操作。那么在单片机内部计数一次的时间是多少呢,51 单片机输入的时钟脉冲是由的输出经12 分频后得到的,所以定时器也可看作是对计算机机器周期的计数器。因为每个机器周期包含12 个振荡周期,故每一个机器周期定时器加1,可以把输入的时钟脉冲看成机器周期信号。故其频率为频率的1/12。如果频率为,则定时器每接收一个输入脉冲的时间刚好为1μs。在本实验套件中采用的是 的晶振,故每接收一个输入脉冲的时间约为1.085μs。实现精确定时在实际项目应用中非常重要,因为往往需要用到精确定时一段时间,然后定时时间到的时刻做相应的任务。
  那如何编程实现定时时间呢?首先先简单介绍下本实验板上单片机()内的定时器资源。STC89C52 内有三个定时/ 计数器, 分别为T0、T1 和T2。其中T0、T1 工作方式一样,一并介绍。
  T2 的工作方式稍有区别,这里不做介绍,实验套件光盘中有实际应用程序。同时,单片机中的定时器和计数器是复用的,计数器是记录外部脉冲的个数,而定时器则是由单片机内部时钟提供的一个非常稳定的计数源。本讲中,以T0、T1 作为定时器来进行实例介绍使用。
  了解了单片机内的定时器资源后,接下来我们来对定时器寄存器进行详细介绍。TMOD(见表1)、TCON(见表3)与定时器T0、定时器T1 间通过内部总线及连接,TMOD 用于设置定时器的工作方式,TCON 用于控制定时器的启动、停止,标志定时器的溢出和中断情况。当设置了定时器的工作方式并启动定时器工作后,定时器就按被设定的工作方式独立工作,不再占用CPU 的操作时间,只有在计数器计满溢出时才可能中断CPU 当前的操作。
表1 TMOD寄存器
  表中各位(从左至右为从高位到低位)含义如下。
  TMOD 的低4 位为定时器0 的方式字段,高4位为定时器1 的方式字段,它们的含义完全相同。
  M1 和M0 :工作方式控制位,其定义如表2 所示( 其中i=0,1)。
表2 定时器工作方式控制位
  :功能选择位。=0 时,设置为定时器工作方式;=1 时,设置为计数器工作方式。
  GATE :门控位。当GATE=0 时,软件控制位TR0 或TR1 置1 即可启动定时器。
  TR0 或TR1 置0 即可停止定时器工作;当GATE=1 时,软件控制位TR0 或TR1 需置1,同时还需(P3.2) 或(P3.3) 为高电平方可启动定时器,即允许外部中断启动定时器。
  值得注意的是TMOD 寄存器不能位寻址,只能用字节指令设置高4 位定义定时器1 上的工作方式或低4 位定义定时器0 的工作方式。而且在复位时,TMOD 所有位均置0。
表3 TCON寄存器
  表中各位(从左至右为从高位到低位)含义如下。
  (1) TFl :定时器1 溢出标志位。当定时器1 计满数产生溢出时,由硬件自动置TF1=1, 向CPU发出定时器1 的中断请求,在中断允许时响应。进入中断服务程序后,由硬件自动清0。在中断屏蔽时,TF1 可作查询测试用,此时只能由软件清0。
  (2) TR1 :定时器1 运行控制位。由软件置1 或清0 来启动或关闭定时器1。
  当GATE=l,且为高电平时,TRI 置1 启动定时器l ;当GATE=0 时,TR1 置1 即可启动定时器1。
  (3) TF0 :定时器0 溢出标志位。其功能及操作情况同TF1。
  (4) TR0 :定时器0 运行控制位。其功能及操作情况同TR1。
  (5) IE1 :外部中断1() 请求标志位。
  (6) IT1 :外部中断1 触发方式选择位。
  (7) IE0 :外部中断0( ) 请求标志位。
  (8) IT0 :外部中断0 触发方式选择位。
  值得注意的是TCON 中的低4 位用于控制外部中断,与定时器/ 计数器无关,在以后的讲座中会提及。当系统复位时,TCON 的所有位也均清0。
  在上文中提到定时器溢出和中断,什么是定时器溢出呢?我们可以这样理解:往一个盆中滴水,水滴持续落下,盆中的水持续变满,最终会有一滴水使得盆中的水满了(这相当于计数到最大值)。这个时候如果再有一滴水落下,这时水就会漫出来,这就是“溢出”。当然,水溢出是流到地上,而定时器溢出后将使得TF0 变为“1”。一旦TF0 由0 变成1,就会产生中断。中断就是由于某个事件的发生,CPU 暂停当前正在执行的程序,转而执行处理该事件的一个程序。该程序执行完成后,CPU 接着执行被暂停的程序的这样一个过程。这正如我们本来在做某事,有人过来请求帮忙,我们停下手中的活去帮忙,完事之后回来接着做原来的事情。根据中断引发的不同,或者CPU 响应中断的不同条件,也可以把中断划分为可屏蔽中断(也就是说我们可以拒绝帮别人忙,继续做自己的事情)和不可屏蔽中断(事情做累了,必须休息)两种。
  了解了中断原理之后,我们来看中断允许控制寄存器IE(见表4)和中断优先寄存器IP(见表5)。
表4 IE寄存器
  EA:中断允许总控制位。EA=0,禁止所有中断;EA=1,开放所有中断,但是否允许各中断源的中断请求,还要取决于各中断源的中断允许控制位的状态。这点要注意,初学者往往容易忘了开放所有中断,从而导致没法进入中断源。
  ET2 :时器/ 计数器T2 的中断允许位。
  ES :串行口的中断允许位。
  ET1 :定时器/ 计数器T1 的中断允许位。
  EX1 :外部中断1(INT1) 的中断允许位。
  ET0 :定时器/ 计数器T0 的中断允许位。
  EX0 :外部中断0(INT0) 的中断允许位。
  以上7 个中断允许控制位为0 时,禁止中断,为1 时允许中断。
表5 IP寄存器
  PT2 :定时器/ 计数器T1 中断优先级控制位。
  PS :串行口中断优先级控制位。
  PT1 :定时器/ 计数器T1 中断优先级控制位。
  PX1 :外部中断1 优先级控制位。
  PT0 :定时器/ 计数器T0 中断控制位。
  PX0 :外部中断0 中断优先级控制位。
  以上6 个中断优先级控制位分别为“0”时为低级中断,为“1”时为高级中断。如果几个同一优先级的中断源同时向CPU 申请中断,CPU 通过内部顺序查询逻辑电路,按自然优先级顺序确定该响应哪个中断请求。自然优先级由硬件形成,其优先级别从高到底为外部中断0、定时器/ 计数器T0、外部中断1、定时器/ 计数器T1、串行口中断、定时器/ 计数器T2。
  至此,对定时器控制相关的重要寄存器都介绍完毕了,接下来通过编写程序来进行验证实践。
  二、电路详解
  此讲采用和上讲一样的电路,在此不做赘述(见图1)。
图1 定时器应用实验电路图
  三、程序设计
  定时器0 应用测试程序( 控制D1 闪烁)。
  #include&AT89X52.h& (1)
  #define led P0_0 (2)
  unsigned
count=0; (3)
  void main(void) (4)
  TMOD=0X01; (5)
  TH0=()/256; (6)
  TL0=()%256; (7)
  EA=1; (8)
  ET0=1; (9)
  TR0=1; (10)
  PT0=1; (11)
  while(1) ; (12)
  void timer0(void) interrupt 1 (13)
  TH0=()/256; (14)
  TL0=()%256; (15)
  count++; (16)
  if(count==10) (17)
  count=0; (18)
  led=! (19)
  1. 程序详细说明:
  (1)头文件包含。程序接下来调用的P0_0 就是该头文件中定义好的一个寄存器地址。在对单片机内部的寄存器操作之前,应申明其来处,有兴趣的读者可以看看AT89X52.h 文件中的内容。
  (2)宏定义led,便于直观理解也便于程序修改,将P0_0 口命名为led,这样在程序中就可以用led代替P0_0 口进行操作。
  (3)定义一个8 位的全局变量。
  (4)主函数入口。主函数不传递参数也不返回值。
  (5)设定定时器0 工作在模式1,为16 位的计数器。
  (6)定时器高8 位赋初值。对256 取整。
  (7)定时器低8 位赋初值。对256 取余。
  (8)开总中断。
  (9)开定时器0 中断。
  (10)定时器0 启动,开始计数。
  (11)设置开定时器0 中断为优先中断。
  (12)死循环,等待中断。
  (13)定时器0 中断服务函数入口。
  (14)定时器高8 位赋初值。对256 取整。
  (15)定时器低8 位赋初值。对256 取余。
  (16)对变量count 进行加1 操作。
  (17)如果count 增长到10。
  (18)count 变量清0。
  (19)led 输出取反。
  2. 程序流程图与实验现象
  程序流程如图2 所示。经编译下载程序到单片机内运行后,可以看到实验板上P0_0 口外接的LED 灯有规律的一亮一灭的闪烁见图3。亮灭的时间可以计算为10×5μs=542.5ms。
  实际的时间要比这稍多几个ms,这是因为没有把条件判断和程序调用的指令时间算在内。在要求非常精确的场合,应当实际微调。
图2 主程序和中断服务函数流程图
图3 实验现象效果
  四、总结
  本讲主要介绍了51 单片机内部定时器和中断系统以及编写第一个简单的定时器实验程序。通过该讲,大家可以发现单片机内的定时器和中断系统并不难学,只要记住应用的相关操作步骤多进行几次实践就可以很熟练的掌握这些资源的用法。鉴于本讲的理论内容较多,希望读者多*时间记下或者熟悉。下一讲,将要介绍如果单片机串口通信并给出实例,敬请期待。&&来源:
技术资料出处:berlin0699
该文章仅供学习参考使用,版权归作者所有。
因本网站内容较多,未能及时联系上的作者,请按本网站显示的方式与我们联系。
【】【】【】【】
上一篇:下一篇:
本文已有(1)篇评论
发表技术资料评论,请使用文明用语
字符数不能超过255
9:19:00用户IP: 122.234.209.*
看着累死了,为什么公式会换行的……
12345678910
12345678910
12345678910
无线通讯的频谱有限,分配非常严格,相同频宽的电磁波只能使用一次,为了解决僧多粥少的难题,工程师研发出许多“调变技术”(ModulaTIon)与“多工技术”(MulTIplex),来增加频谱效率,因此才有了 3G、4G、5G 不同通讯世代技术的发明,那么在我们的手机里,是什...[][][][][][][][][][]
IC热门型号
IC现货型号
推荐电子百科在51单片机中,使用同时使用两个定时器,执行的时候会有先后顺序吗?_百度知道如何用51单片机的定时器中断功能输出一个8khz,误差很小(为1hz)的方波??
我的代码如下(现在只会汇编的)能在8k附近但就是达不到…师兄说是可以做到精读很高的。ORG 0000H 一下程序起始地址0000HJMP MAIN 上电 转向主程序MAINORG 001BH 定时器1 矢量地址 LJMP TIMER1 长跳转到中断服务程序TIMER1ORG 0040HMAIN: 主程序 初始化 开中断
MOV TMOD,#20H貌似用模式1和模式2都会有挺大的误差,用示波器达到了124us或者126us……
MOV TH1 ,#0FAH
MOV TL1 ,#0FAH这个是随便写的数字,因为是凭记忆打的代码
SETB EAHERE:
SJMP HERE 等待定时器中断TIMER1:
PUSH ACC 入栈
CPL P1.1 P1.1翻转输出
RETI END//问题以解决,谢谢大家回复
蟹妖~中断输出方波在现在越来越没有实际价值的,如果是一定要这么做的话就只有不断的调试参数,主要就是重载时间,要把中断的进出栈时间扣掉。我不记得51的定时器详细信息了,也不会汇编,如果C的话我可以帮你看看程序,但是如果你的误差是可以重复且稳定的话,那么还是有优化余地的。比方说你只有这一个任务的话,可以在主函数里面去不断读free run的定时器,这样就省掉了进出栈的开销。又或者换一个快一点的单片机,不能消除误差但是能让误差小一点~其实你这里的需求最合适的就是用52单片机的T2做一个对时钟信号的分频器,精度可以达到晶振的精度。另外你提供的信息也不是很全,我不知道你的测试条件,有时候不是你的程序不准,是你测的不准也是可能的。
谢邀,现在不懂汇编,N年前会。先看你的晶振输出频率是否准确。再看你是否有扣除中断响应的时间。建议使用自动重载模式。还有,数字类的问题不要邀我。
已有帐号?
无法登录?
社交帐号登录查看: 420|回复: 3
定时器中断的问题
主题帖子精华
中级会员, 积分 260, 距离下一级还需 240 积分
在线时间0 小时
[C] 纯文本查看 复制代码void usart_init(void)//*(*(256-X)))
TMOD = 0X20;
SCON = 0X50;
//PCON &= 0X7F;
//TH0=(256-/(bound*32)/12);
//TL0=(256-/(bound*32)/12);
//EA=1;//在main函数打开
void T1_Timer() interrupt 3
if(num&=333)//num=333大概1ms时间到
UartRxMonitor(1);
[C] 纯文本查看 复制代码
大家帮我看看T1中断为什么不会产生啊,我用P1=0x00;来点亮LED来验证,结果灯不亮,说明中断没有产生!还有一个问题是我是不是中断时间太小了才产生这样错误的?因为num==333才1ms. & & & 主函数就是对串口初始化,打开EA.
主题帖子精华
新手上路, 积分 36, 距离下一级还需 14 积分
在线时间0 小时
检查下num是不是定义成char&型了,另外T1要作为串口波特率发生器。改用T0试试。
不做浮躁的嵌入式攻城狮。。。。
主题帖子精华
初级会员, 积分 161, 距离下一级还需 39 积分
在线时间8 小时
赋初值有问题吗
主题帖子精华
中级会员, 积分 260, 距离下一级还需 240 积分
在线时间0 小时
回复【3楼】day&&day&&up:
---------------------------------
没有,可能定时的时间太短了导致的。。。
Powered by51学习之定时器中断
呵呵,从网上抄了个程序,自己改了下。能用了。不过有些地方还是不太了解,呵呵,明天来细写。
定时器中断可用两种方式处理:查询和进入中断处理。
void Init_T0 (void) &
定时器初始化&
& & TMOD = 0x01;
& & TH0 = ()
& & TL0 = ()
& & EA = 1;
& & ET0 = 1;
& & TR0 = 1;
void Main() & &主函数
{ & &Init_T0 ();
& & &Speak1
&if(TF0==1) &查询中断标志
& &Speak1=~Speak1;
& &//TH0 = ()
& &//TL0 = ()
2.进入中断处理
void Init_T0 (void) &
定时器初始化&
& & TMOD = 0x01;
& & TH0 = ()
& & TL0 = ()
& & EA = 1;
& & ET0 = 1;
& & TR0 = 1;
void Time0_Int() interrupt 1 &中断处理函数
& Speak1=~Speak1;&
& //TH0 = ()
& //TL0 = () %6;
void Main() &主函数
& &Init_T0 ();
& &Speak1 =1;
& &while(1);
对于查询方式,一定要手动清楚中断标志。
上面2段程序,我屏蔽了,中断时重新装计数初值的语句,程序都可正常运行,所以我认为无论对于那种处理方式,重装初值都不必要。
初始化时,可定义输出口的初始状态。而在处理中断时,一定要用取反语句。手动置0或1,程序不能正常运行。
对于方式2,开始main中没写最后的while(1),程序不正常运行。
上述定时最大为65535,约65ms.如果计时大于此,可在中断中处理。
程序如下:
void Time0_Int() interrupt 1
& & if(a++==20)
&Speak1=~Speak1;
,在写上面这一小段时,开始没写a=0,灯一直亮,后来参考下,发现不清0.a一直变大,程序只能执行一次。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。}

我要回帖

更多关于 单片机定时器中断 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信