单片机定时器中断时间误差的解决方案

单片机定时器中断时间误差的解决方案
单片机定时器中断时间误差的解决方案

单片机定时器中断时间误差的解决方案

时间:2012-06-12 14:04:04 来源:作者:

1 前言

单片机内部一般有若干个定时器。如8051单片机内部有定时器0和定时器1。在定时器计数溢出时,便向CPU发出中断请求。当CPU正在执行某指令或某中断服务程序时,它响应定时器溢出中断往往延迟一段时间。这种延时虽对单片机低频控制系统影响甚微,但对单片机高频控制系统的实时控制精度却有较大的影响,有时还可能造成控制事故。为扩大单片机的应用范围,本文介绍它的定时器溢出中断与CPU响应中断的时间误差、补偿误差的方法和实例。

2 误差原因、大小及特点

产生单片机定时器溢出中断与CPU响应中断的时间误差有两个原因。一是定时器溢出中断信号时,CPU正在执行某指令;二是定时器溢出中断信号时,CPU正在执行某中断服务程序。

2.1. CPU正在执行某指令时的误差及大小

由于CPU正在执行某指令,因此它不能及时响应定时器的溢出中断。当CPU执行此指令后再响应中断所延迟的最长时间为该指令的指令周期,即误差的最大值为执行该指令所需的时间。由于各指令都有对应的指令周期,因此这种误差将因CPU正在执行指令的不同而不同。如定时器溢出中断时,CPU正在执行指令MOV A, Rn,其最大误差为1个机器周期。而执行指令MOV Rn, direct时,其最大误差为2个机器周期。当CPU正在执行乘法或除法指令时,最大时间误差可达4个机器周期。在8051单片机指令系统中,多数指令的指令周期为1~2个机器周期,因此最大时间误差一般为1~2个机器周期。若振荡器振荡频率为fosc,CPU正在执行指令的机器周期数为Ci,则最大时间误差为Δtmax1=12/fosc×

Ci(us)。例如fosc=12MHZ,CPU正在执行乘法指令(Ci=4),此时的最大时间误差为:

Δtmax1=12/fosc×Ci=12/(12×106)×4=4×10-6(s)=4(μs)

2.2 CPU正在执行某中断服务的程序时的误差及大小

定时器溢出中断信号时,若CPU正在执行同级或高优先级中断服务程序,则它仍需继续执行这些程序,不能及时响应定时器的溢出中断请求,其延迟时间由中断转移指令周期T1、中断服务程序执行时间T2、中断返回指令的指令周期T3及中断返回原断点后执行下一条指令周期T4(如乘法指令)组成。中断转移指令和中断返回指令的指令周期都分别为2个机器周期。中断服务程序的执行时间为该程序所含指令的指令周期的总和。因此,最大时间误差Δtmax2为:

Δtmax2=(T1+T2+T3+T4)12/fosc=(2+T2+2+4)12/ fosc=12(T2+8)/ fosc

若设fosc=12MHZ,则最大时间误差为:

Δtmax2=12(T2+8)/ fosc =12(T2+8)/12×106=(T2+8)×10-6(s)=T2+8(μs)。

由于上式中T2一般大于8,因此,这种时间误差一般取决于正在执行的中断服务程序。当CPU正在执行中断返回指令RETI、或正在读写IE或IP指令时,这种误差在5个机器周期内。

2.3 误差非固定性特点

定时器溢出中断与CPU响应中断的时间误差具有非固定性特点。即这种误差因CPU正在执行指令的不同而有相当大的差异。如CPU正在执行某中断服务程序,这种误差将远远大于执行一条指令时的误差。后者误差可能是前者误差的几倍、几十倍、甚至更大。如同样只执行一条指令,这种误差也有较大的差别。如执行乘法指令MUL AB 比执行MOV A, Rn指令的时间误差增加了3个机器周期。这种误差的非固定不仅给误差分析带来不便,同时也给误差补偿带来困难。

3 误差补偿方法

由于定时器产生溢出中断与CPU响应中断请求的时间误差具有非固定性,因此,这种误差很难用常规方法补偿。为此,本文介绍一种新方法。现介绍该方法的基本思路、定时器新初值及应用情况。

3.1 基本思路

为使定时器溢出中断与CPU响应中断实现同步,该方法针对中断响应与中断请求的时间误差,对定时器原有的计数初值进行修改,以延长定时器计数时间,从而补偿误差。在该方法中,当定时器溢出中断得到响应后,即停止定时器的计数,并读出计数值。该计数值是定时器溢出后,重新从OOH开始每个机器周期继续加1所计的值。然后,将这个值与定时器的停止计数时间求和。若在定时器原计数初值中减去这个和形成新计数初值,则定时器能在新计数初值下使溢出中断与CPU响应中断实现同步,从而达到误差的补偿要求。

3.2 定时器新计数初值

若定时器为计数方式,操作方式为1,则计数器初值X0=216-t0×fosc/12。式中fosc为振荡器的振荡频率。t0为需要定时的时间,也为中断的间隔时间。X0为定时器原计数初值。在对定时器溢出中断与CPU响应中断时间误差进行补偿时,定时器的新计数初值X1为:

X1=216-t3× fosc/12

t3=t0+t1+t2

式中t0为中断间隔时间。t1为定时器停止计数时间,该时间为定时器停止计数到重新启动计数之间所有程序指令周期数的总和。t2为定时器溢出中断后,重新从OOH开始直至计数器停止时计的值。在误差补偿中,若将定时器计数初值X1取代X0,则可使定时器下次的溢出中断与CPU响应中断实现同步。

3.3 实例

要求补偿定时器每1ms产生一次溢出中断时的中断响应延迟的误差。若振荡器振荡频率fosc=12MHZ,定时器工作在计数方式,工作模式为1,则补偿中断响应时间误差时的定时器新初值X1为:

X1=216-t3× fosc/12=216-(t0+ t1)- t2=216-(1000+ 13)- t2

误差补偿程序为:

……

0 CLR EA ;关CPU中断

1 CLR TRi ;停止定时器计数

2 MOV R0, #OOH ;R0清零

3 MOV R0, #LOW(216) ;定时器最大计数值的低8位送R0

4 MOV A, R0

5 SUBB A, #LOW(1000+13) ;216的低8位减去( t0+ t1)的低8位送累加器A

6 SUBB A, TLi ;216的低8位减去( t0+ t1+ t2)的低8位送TLi

7 MOV TLi, A

8 MOV R0, #OOH ;R0清零

9 MOV R0, #HIGH(216) ;216 的高8位送R0

10 MOV A, R0

11 SUBB A, #HIGH(1000+13) ;216的高8位减去( t0+ t1)的高8位送A

12 SUBB A, THi ;216的高8位减去( t0+ t1 +t2)的高8位送A

13 MOV THi, A

14 SETB TRi ;重新启动定时器

……

在上式和上段程序中,由于fosc=12MHZ,中断间隔时间为1ms,因此t0的机器周期数为1000。由于第1条指令到第14条指令的指令周期的机器周期数之和为13,因此,t1为13个机器周期。CPU虽在执行第一条指令CLR TRi后停止定时器计数,但在TLi、THi中分别保存了t2的低位数据和高位数据。

4 结束语

由于本文介绍的误差补偿方法能对定时器溢出中断与CPU响应中断的非固定性时间误差进行有效补偿,因此,该方法对于提高高频控制系统实时控制精度和扩大单片机应用范围都有较高的实用价值。

原文网址: https://www.360docs.net/doc/4810624745.html,

单片机中断程序大全

单片机中断程序大全公司内部编号:(GOOD-TMMT-MMUT-UUPTY-UUYY-DTTI-

//实例42:用定时器T0查询方式P2口8位控制L E D闪烁#include // 包含51单片机寄存器定义的头文件void main(void) { // EA=1; //开总中断 // ET0=1; //定时器T0中断允许 TMOD=0x01; //使用定时器T0的模式1 TH0=(65536-46083)/256; //定时器T0的高8位赋初值 TL0=(65536-46083)%256; //定时器T0的高8位赋初值 TR0=1; //启动定时器T0 TF0=0; P2=0xff; while(1)//无限循环等待查询 { while(TF0==0) ; TF0=0; P2=~P2; TH0=(65536-46083)/256; //定时器T0的高8位赋初值 TL0=(65536-46083)%256; //定时器T0的高8位赋初值 //实例43:用定时器T1查询方式控制单片机发出1KHz音频

#include // 包含51单片机寄存器定义的头文件sbit sound=P3^7; //将sound位定义为P3.7引脚 void main(void) {// EA=1; //开总中断 // ET0=1; //定时器T0中断允许 TMOD=0x10; //使用定时器T1的模式1 TH1=(65536-921)/256; //定时器T1的高8位赋初值 TL1=(65536-921)%256; //定时器T1的高8位赋初值 TR1=1; //启动定时器T1 TF1=0; while(1)//无限循环等待查询 { while(TF1==0); TF1=0; sound=~sound; //将P3.7引脚输出电平取反 TH1=(65536-921)/256; //定时器T0的高8位赋初值 TL1=(65536-921)%256; //定时器T0的高8位赋初值 } } //实例44:将计数器T0计数的结果送P1口8位LED显示 #include // 包含51单片机寄存器定义的头文件sbit S=P3^4; //将S位定义为P3.4引脚

定时器中断程序设计实验

实验一定时器/中断程序设计实验 一、实验目的 1、掌握定时器/中断的工作原理。 2、学习单片机定时器/中断的应用设计和调试 二、实验仪器和设备 1、普中科技单片机开发板; 2、Keil uVision4 程序开发平台; 3、PZ-ISP 普中自动下载软件。 三、实验原理 805l 单片机内部有两个 16 位可编程定时/计数器,记为 T0 和 Tl。8052 单片机内除了 T0 和 T1 之外,还有第三个 16 位的定时器/计数器,记为 T2。它们的工作方式可以由指令编程来设定,或作定时器用,或作外部脉冲计数器用。定时器 T0 由特殊功能寄存器 TL0 和 TH0 组成,定时器 Tl 由特殊功能寄存器 TLl 和 TH1 组成。定时器的工作方式由特殊功能寄存器 TMOD 编程决定,定时器的运行控制由特殊功能寄存器 TCON 编程控制。T0、T1 在作为定时器时,规定的定时时间到达,即产生一个定时器中断,CPU 转向中断处理程序,从而完成某种定时控制功能。T0、T1 用作计数器使用时也可以申请中断。作定时器使用时,时钟由单片机内部系统时钟提供;作计数器使用时,外部计数脉冲由 P3 口的 P3.4(或 P3.5)即 T0(或 T1)引脚输入。 方式控制寄存器 TMOD 的控制字格式如下: 低 4 位为 T0 的控制字,高 4 位为 T1 的控制字。GATE 为门控位,对定时器/计数器的启动起辅助控制作用。GATE=l 时,定时器/计数器的计数受外部引脚输入电平的控制。由由运行控制位 TRX (X=0,1)=1 和外中断引脚(0INT 或 1INT)上的高电平共同来启动定时器/计数器运行;GATE=0时。定时器/计数器的运行不受外部输入引脚的控制,仅由 TRX(X=0,1)=1 来启动定时器/计数器运行。 C/-T 为方式选择位。C/-T=0 为定时器方式,采用单片机内部振荡脉冲的 12 分频信号作为时钟计时脉冲,若采用 12MHz 的振荡器,则定时器的计数频率为 1MHZ,从定时器的计数值便可求得定时的时间。 C/-T=1 为计数器方式。采用外部引脚(T0 为 P3.4,Tl 为 P3.5)的输入脉冲作为计数脉冲,当 T0(或 T1)输入信号发生从高到低的负跳变时,计数器加 1。最高计数频率为单片机时钟频率的 1/24。 M1、M0 二位的状态确定了定时器的工作方式,详见表。

51单片机中断定时器浅谈

51单片机中断定时器浅谈 中断处理函数原型 void timer1() interrupt0 using 0 timer1() 函数名 interrupt 表示是中断处理函数 0 表示是第几个中断源的处理函数 using 0 表示是使用第几组工作寄存器一般在C语言里面编译器屏蔽了会自动分配程序员一般不用关心。 注意:如果在中断处理函数中进行处理数据不能处理的数据量太大,因为定时器时间已到它就会又进入下一个中断处理函数,也就是这个中断处理函数还没有处理完下一个中断又来了。这样会造成结果错误或异常。 定时器: 定时器又2个寄存器控制,一个是TMOD 用于选择定时器、计数器 T0,T1的工作模式和工作方式。另一个是TCON 用于控制TO,T1的启动和停止,同时包含了T0,T1的状态,这2个寄存器在单片机复位时候所有位都被清0. TMOD 是不能位寻址的,因为它的地址是89H不能被8

整除。只能赋值或者进行与或运算进行赋值,其中有位是C/T 是把它配置成定时器还是计数器 0 表示是 定时器 M0,M1 这2位进行是定时器的模式几共4种模式其中方式1为16 高8位 TH0,低8位在 TL0 (65536-50000)/256 这就是高8位(65536-50000)%6 放入低8位是大约50毫秒前提是晶振为12兆赫。凡是用11.0592 的晶振是因为单片机要进行串口通讯因为 实现标准的波特率 4800 2400 115200 好计算。才选用11.0592的晶振。单片机的晶振可以选12兆一下的晶振都可以。12兆算是最快的速度了。当然不排除其他高速的单片级,可能达到更高运算速度。定时器最高一次定时为65535的数字,也就是大概65毫秒,因为是16位高8位低8位。所以如果用定时器长时间定时可以设置多次定时然后在main里面判断。实现长时间定时。定时器是一个加1的寄存器。初值最小为0 。最大65535 ,单片机做延时不占用MCU的资源比用 while 或 for循环好,能提高效率,当时浪费一个I/O口,所以用时综合考虑。 在一般情况下都是定时器与中断一起使用的,如:定时器时间到发生中断,一般都是IE TMOD TCON 三个寄存器联合使用 TCON 控制TR0 TR1 运行与停止 TMOD 控制工作模式 IE 控制总中断与对应的那个中断的开关

51单片机独立按键程序查询法和外部中断两种

//以下程序都是在VC++6.0 上调试运行过的程序,没有错误,没有警告。 //单片机是STC89C52RC,但是在所有的51 52单片机上都是通用的。51只是一个学习的基础平台,你懂得。 //程序在关键的位置添加了注释。 //用//11111111111111111代表第一个程序。//2222222222222222222222222代表第二个程序,以此类推 //1111111111111111111111111111111111111111111111111111111111111111111 //1111111111111111111111111111111111111111111111111111111111111111111 /****************************************************************************** * * 实验名: 左右流水灯实验 * 使用的IO : LED使用P2,键盘使用P3.1 * 实验效果: 按下K1键, * 注意: ******************************************************************************* / #include #include #define GPIO_LED P2 sbit K1=P3^1; void Delay10ms( ); //延时10ms /****************************************************************************** * * 函数名: main * 函数功能: 主函数 * 输入: 无 * 输出: 无 ******************************************************************************* / void main(void) { unsigned int i,j; j=0xfe; //1111_1110 while(1) { GPIO_LED=j; if(K1==0) //检测按键K1是否按下 { Delay10ms(); //消除抖动 if(K1==0) {

定时器中断产生方波源程序

①fangbo.asm。利用定时器Timer0在XF脚产生周期1s的的方波 .title "fangbo.asm" .mmregs .def CodeStart ;程序入口 .def TINT0_ISR ;Timer0中断服务程序 STACK .usect "STACK",10H ;分配堆栈空间 ;设定定时器0控制寄存器的内容 K_TCR_SOFT .set 0B<<11 ;TCR第11位soft=0 K_TCR_FREE .set 0B<<10 ;TCR第10位free=0 K_TCR_PSC .set 0B<<6 ;TCR第9-6位,可跟TDDR一样,也可不设自动加载 K_TCR_TRB .set 1B<<5 ;TCR第5位TRB=1此位置1,PSC会自动加载的 K_TCR_TSS .set 0B<<4 ;TCR第4位TSS=0 K_TCR_TDDR .set 1001B<<0 ;TCR第3-0位TDDR=1001B K_TCR .set K_TCR_SOFT|K_TCR_FREE|K_TCR_PSC|K_TCR_TRB|K_TCR_TSS|K_TCR_TDDR K_TCR_STOP .set 1B<<4 ;TSS=1时计数器停止 .data DATA_DP: XF_Flag: .word 1 ;当前XF的输出电平标志,如果XF_Flag=1,则XF=1 ;================================================ ;主程序: ;================================================ .text CodeStart: STM #STACK+10H,SP ;设堆栈指针SP LD #DATA_DP,DP ;设数据地址DP STM #XF_Flag,AR2 ;AR指向XF标志 ;改变中断向量表位置 K_IPTR .set 0080h ;指向0080H,默认是FF80 LDM PMST,A AND #7FH,A ;保留低7位,清掉高位 OR #K_IPTR,A ; STLM A,PMST ;初始化定时器0 ;f=100Mhz,定时最大是:10ns*2^4*2^16=10ms, ;要输出1s的方波,可定时5ms,再在中断程序中加个100计数器 ;Tt=10ns*(1+9)*(1+49999)=5ms ;f=50M, Tt=20ns*(1+9)*(1+49999)=10ms ;再加50计数器 CounterSet .set 49 ;定义计数次数 PERIOD .set 49999 ;定义计数周期 .asg AR1,Counter ;AR1做计数指针,重新命名以便识别 STM #CounterSet,Counter ;设计数器初值 STM K_TCR_STOP,TCR ;停止计数器0 ; STM #PERIOD,TIM ;可设成跟PRD一样,也可不设自动加载STM #PERIOD,PRD ;设定计数周期 STM #K_TCR,TCR ;开始Timer0 stm #0008h,IMR ;允许Timer0中断 STM #0008h,IFR ;清除挂起的中断 RSBX INTM ;开中断 end: nop B end ;================================================ ;Timer0中断服务程序:TIN0_ISR ;================================================

51单片机定时中断C语言的写法步骤

51单片机定时中断C语言的写法步骤 程序说明:51单片机定时器0工作于方式一,定时50ms中断一次 晶振为12M #include void main { TOMD = 0X01;//配置定时器0工作于方式一 TH1 = (65536-50000)/256; //高八位装入初值 TL1 = (65536-50000)%256; //低八位装入初值 ET0 = 1; //开定时器0中断 EA = 1; //开总中断 TR0 = 1; //启动定时器0 while(1) { ; } } void Timer0_int() interrupt 1 { //重新装初值 TH1 = (65536-50000)/256; //高八位装入初值 TL1 = (65536-50000)%256; //低八位装入初值 } /****************************************************************************** *********************************/ 上面是比较好理解的。如果实在要求简洁的话,看下面的,跟上面功能一样 #include void main { TOMD = 0X01;//配置定时器0工作于方式一 TH1 = 0x3c; //高八位装入初值 TL1 = 0xb0; //低八位装入初值 IE = 0x82;//开总中断并开定时器0中断 TR0 = 1; //启动定时器0 while(1) { ; } }

void Timer0_int() interrupt 1 { //重新装初值 TH1 = 0x3c; //高八位装入初值TL1 = 0xb0; //低八位装入初值}

单片机实验 中断、定时器

大连理工大学实验报告(模板) 实验时间:年月日星期时间::~ : 实验室(房间号):实验台号码:班级:姓名: 指导教师签字:成绩: 实验三外部中断/INT0实验 一、实验目的和要求 学习、掌握单片机的中断原理。正确理解中断矢量入口、中断调用和中断返回的概念及物理过程。学习编写“软件防抖”程序,了解“软件防抖”原理。 对/int0、/int1两个外部中断进行编程,其中: ●主程序的功能:LDE灯“全亮”、“全灭”交替进行 --------(状态2); ●Int0中断服务程序功能:2个相邻的LED灯被点亮且循环左移(状态0); ●Int1中断服务程序功能:1个LED灯被点亮且循环右移 ---(状态1);【注意】:实验仪上的LED灯物理位置最左侧为d0;最右侧为d7。 二、实验算法 1 在主程序中利用CPL P3.3的指令驱动其电平不断地转换(由逻辑笔电路做程序状态监视)。 2 在中断服务程序中将P3.3置位(P3.3=1),实现对计数器“加1”并(通过P1口)显示的功能。 3 中断结束后回到主程序,程序继续对P3.3的电平不断取反。 三、实验电路图

四、实验流程图 主程序入口INT0入口 设置中断允许P3.2置1 设置中断优先级调用延时子程序 设TCON 计数器加一并显示 CLR A开中断 (P0)—(A) P3.2=0? 调用延时子程序调用延时子程序 (A)—(A) RETI INT1同理 五、程序清单 ORG 0000H LJMP START ORG 0003H LJMP INT_0 ORG 0013H LJMP INT_1 ORG 0100H ;主程序 START: MOV SP,#60H MOV IE,#85H

51单片机C语言中断程序定时计数器

51单片机C语言中断程序定时/计数器 程序一 利用定时/计数器T0从P1.0输出周期为1s 的方波,让发光二极管以1HZ闪烁, #include //52单片机头文件 #include //包含有左右循环移位子函数的库#define uint unsigned int //宏定义 #define uchar unsigned char //宏定义 sbit P1_0=P1^0; uchar tt; void main() //主函数 { TMOD=0x01;//设置定时器0为工作方式1 TH0=(65536-50000)/256; TL0=(65536-50000)%256; EA=1;//开总中断 ET0=1;//开定时器0中断 TR0=1;//启动定时器0 while(1);//等待中断产生 }

void timer0() interrupt 1 { TH0=(65536-50000)/256; TL0=(65536-50000)%256; tt++; if(tt==20) { tt=0; P1_0=~P1_0; } } 程序二 利用定时/计数器T1产生定时时钟, 由P1口控制8个发光二极管, 使8个指示灯依次一个一个闪动, 闪动频率为10次/秒(8个灯依次亮一遍为一个周期),循环。#include //52单片机头文件 #include //包含有左右循环移位子函数的库 #define uint unsigned int //宏定义 #define uchar unsigned char //宏定义

51单片机外部中断与定时器的实用

中断使能寄存器 通过设置中断使能寄存器 IE 的 EA 位 使能所有中断 每个中断源都有单独的使能位 可通过软件设置 IE 中相应的使能位在任何时候使能或禁能中断 中断使能寄存器 IE 的各 位如下所示 中断使能寄存器IE 位地址 0AFH 0AEH 0ADH 0ACH 0ABH 0AAH 0A9H 0A8H 位符号 EA / ET2 ES ET1 EX1 ET0 EX0 EA 使能标志位 置位则所有中断使能 复位则禁止所有中断保留 ET2 定时器2 中断使能 ES 串行通信中断使能 ET1 定时器 1 中断使能 EX1 外部中断 1 使能 ET0 定时器0 中断使能 EX0 外部中断 0使能 8051 支持两个中断优先级 有标准的中断机制, 低优先级的中断只能被高优先级的中断所中断 ,而高优先级的中断不能被中断。 中断优先级寄存器 每个中断源都可通过设置中断优先级寄存器IP 来单独设置中断优先级 如果每个中断源的相应位被置位 则该中断源的优先级为高,如果相应的位被复位, 则该中断源的优先级为低, 如果你觉得两个中断源不够用 ,别急以后我会教你如何增加中断优先级 表 A-5 示出了 IP 寄存器的各位 此寄存器可位寻址 IP 寄存器 位地址 0BFH 0BEH 0BDH 0BCH 0BBH 0BAH 0B9H 0B8H 位符号 / / / PS PT1 PX1 PT0 PX0 编号 中断源 中断向量 上电复位 0000H 0 外部中断0 0003H 1 定时器0溢出 000BH 2 外部中断1 0013H 3 定时器1溢出 001BH 4 串行口中断 0023H 5 定时器2溢出 002BH PT2 定时器 2中断优先级 PS 串行通信中断优先级 PT1 定时器 1中断优先级 PX1 外部中断1 优先级 PT0 定时器0中断优先级 PX0 外部中断0 优先级

实验五 8051单片机定时中断实验

实验五8051单片机定时中断实验 一实验目的: 了解8051系列单片机的定时中断基本工作原理。掌握8051系列单片机定时中断的用法。 二实验原理: 在上一个实验里我们介绍了8051单片机的外中断应用,本实验要介绍的是定时器中断的应用。 8051系列单片机至少有两个16位的内部定时器/计数器,既可以编程为定时器使用,也可以作为计数器使用。如果是计数内部晶振驱动时钟,它是定时器,如果是计数8051的输入管脚的信号,就是计数器。 MCS-51单片机内部的定时/计数器的结构如图5-1所示,定时器T0特性功能寄存器TL0(低8位)和TH0(高8位)构成,定时器T1由特性功能寄存器TL1(低8位)和TH1(高8位)构成。特殊功能寄存器TMOD控制定时寄存器的工作方式,TCON则用于控制定时器T0和T1的启动和停止计数,同时管理定时器T0和T1的溢出标志等。程序开始时需对TL0、TH0、TL1和TH1进行初始化编程,以定义它们的工作方式和控制T0和T1的计数。 图5-1 TMOD特殊功能寄存器的格式参见下表(表5-1): 表5-1 高4位为定时器/计数器1的控制字,低4位为定时器/计数器0的控制字。其中GATE 为门控信号,C/T为定时器或计数器的选择,而M1,M0是工作方式选择位。 当M1M0=00时,T/C工作在方式0。方式0为13位的T/C,其计数器由TH的8位和TL的5

位构成,计数器的计数值范围是: 1—8192(213),但是启动前可以预置计数初值。当C/T为 0时,T/C为定时器,计数脉冲为振荡源12分频的信号;当C/T为1时,T/C为计数器,对输入端T0或T1输入的脉冲进行计数。计数脉冲加到计数器上与否决定于启动信号。当GATE=0时,TR=1时T/C便启动,当GATE=1时,启动受到TR与INT的双重控制,即二者同时为高 时才启动。当计数满时,TH向高位进位,这时中断溢出标志TF置1,即产生中断请求。而当CPU转向中断服务程序时,TF自动清零。 当M1M0=01时,T/C工作在方式1。方式1和方式0的区别仅在于方式0的计数器位数为13位,而方式1的为16位。 当M1M0=10时,T/C工作在方式2。区别于前面的两种工作方式的是,方式2具有自动重装载的功能。TH和TL作为两个8位的计数器,TH中的8位初值始终保持不变,由TL进行8位计数。在计数溢出时不但会产生中断请求,而且自动将TH中的值加载至TL 中,即自动重装载。 当M1M0=11时,T/C工作在方式3。但是这种工作方式只存在于T/C0中,这时TH0与TL0成为两个独立的计数器。只有在T/C1作为串行口的波特率发生器使用,而造成定时器不够用时,T/C0才能工作在方式3。 下面是定时器时间常数计算公式,这个公式在方式1,即16 位定时或计数模式可用。 THX=(65536-定时时长[μS]/(机器周期数/时钟频率[MHz])/256; TLX=(65536-定时时长[μS]/(机器周期数/时钟频率[MHz])%256; 在定时器重装载过程中因为TL1=0可以不写。 三实验内容: 利用中断方式在LED上输出10HZ方波,系统晶体频率11.059MHz。 四实验电路图:

单片机外部中断详解及程序

单片机外部中断详解及程序 单片机在自主运行的时候一般是在执行一个死循环程序,在没有外界干扰(输入信号)的时候它基本处于一个封闭状态。比如一个电子时钟,它会按时、分、秒的规律来自主运行并通过输出设备(如液晶显示屏)把时间显示出来。在不需要对它进行调校的时候它不需要外部干预,自主封闭地运行。如果这个时钟足够准确而又不掉电的话,它可能一直处于这种封闭运行状态。但事情往往不会如此简单,在时钟刚刚上电、或时钟需要重新校准、甚至时钟被带到了不同的时区的时候,就需要重新调校时钟,这时就要求时钟就必须具有调校功能。因此单片机系统往往又不会是一个单纯的封闭系统,它有些时候恰恰需要外部的干预,这也就是外部中断产生的根本原由。 实际上在第二个示例演示中,就已经举过有按键输入的例子了,只不过当时使用的方法并不是外部中断,而是用程序查询的方式。下面就用外部中断的方法来改写一下第二个示例中,通过按键来更改闪烁速度的例子(第二个例子)。电路结构和接线不变,仅把程序改为下面的形式。 #include ;

unsigned int t=500; //定义一个全局变量t,并设定初始值为500次 //===========延时子函数,在8MHz晶振时约 1ms============= void delay_ms(unsigned int k) { unsigned int i,j; for(i=0;i

单片机定时器中断时间误差的解决方案

单片机定时器中断时间误差的解决方案 时间:2012-06-12 14:04:04 来源:作者: 1 前言 单片机内部一般有若干个定时器。如8051单片机内部有定时器0和定时器1。在定时器计数溢出时,便向CPU发出中断请求。当CPU正在执行某指令或某中断服务程序时,它响应定时器溢出中断往往延迟一段时间。这种延时虽对单片机低频控制系统影响甚微,但对单片机高频控制系统的实时控制精度却有较大的影响,有时还可能造成控制事故。为扩大单片机的应用范围,本文介绍它的定时器溢出中断与CPU响应中断的时间误差、补偿误差的方法和实例。 2 误差原因、大小及特点 产生单片机定时器溢出中断与CPU响应中断的时间误差有两个原因。一是定时器溢出中断信号时,CPU正在执行某指令;二是定时器溢出中断信号时,CPU正在执行某中断服务程序。 2.1. CPU正在执行某指令时的误差及大小 由于CPU正在执行某指令,因此它不能及时响应定时器的溢出中断。当CPU执行此指令后再响应中断所延迟的最长时间为该指令的指令周期,即误差的最大值为执行该指令所需的时间。由于各指令都有对应的指令周期,因此这种误差将因CPU正在执行指令的不同而不同。如定时器溢出中断时,CPU正在执行指令MOV A, Rn,其最大误差为1个机器周期。而执行指令MOV Rn, direct时,其最大误差为2个机器周期。当CPU正在执行乘法或除法指令时,最大时间误差可达4个机器周期。在8051单片机指令系统中,多数指令的指令周期为1~2个机器周期,因此最大时间误差一般为1~2个机器周期。若振荡器振荡频率为fosc,CPU正在执行指令的机器周期数为Ci,则最大时间误差为Δtmax1=12/fosc× Ci(us)。例如fosc=12MHZ,CPU正在执行乘法指令(Ci=4),此时的最大时间误差为: Δtmax1=12/fosc×Ci=12/(12×106)×4=4×10-6(s)=4(μs)

单片机实验――利用中断控制LED灯(精)

单片机实验——利用中断控制LED灯 1.实验目的 (1掌握单片机中断的基本原理。 (2掌握单片机中断程序的编制方法。 2.预习要点 (1单片机中断基本原理 (2中断程序编制方法 3.实验设备 计算机、单片机实验箱、信号发生器。 4.实验内容 基本要求: 将信号发生器输出的脉冲信号连接到CPU的INT0上,将CPU的P1.0到P1.7和八个LED连接,脉冲信号为5V、100Hz,每输入一百个脉冲LED灯亮一次,并且LED灯顺序循环移位一次,形成跑马灯。 扩展要求: 提高输入脉冲频率,但跑马灯的显示频率不变。 实验4 ORG 0000H AJMP MAIN

;****************************************** ;中断子程序入口地址 ORG 0003H LJMP EXINT0 ;****************************************** ;主程序 ORG 0030H MAIN:MOV SP,#70H SETB IT0 ;设置为下降沿触发 SETB EX0 ;开INT0的中断开关 SETB EA ;开总中断开关 MOV R0,#01H ;只让一盏灯亮,R0赋给P1口 MOV R3,#00H ;R3用来记中断次数 MOV A,R0 MOV P1,A HERE:SJMP HERE ;死循环,还有另外一种形式是SJMP $ ;****************************************** ;外中断0服务程序 EXINT0:INC R3 ;每来一次中断R3自加1

CJNE R3,#100,NEXT ;当来了100次中断之后,R3清零,然后P1口的MOV R3,#00H ;数左移一位,也就是让下一个LED亮 MOV A,R0 RL A MOV P1,A MOV R0,A ;保存左移之后的结果 NEXT:RETI ;****************************************** END 实验4扩展 ORG 0000H AJMP MAIN ;****************************************** ;中断入口地址 ORG 0003H LJMP EXINT0 ;****************************************** ;主程序 ORG 0030H

51单片机定时器与中断

例1:查询方式 ORG 0000H AJMP START ORG 30H START: MOV P1,#0FFH ;关所灯 MOV TMOD,#00000001B ;定时/计数器0工作于方式1 MOV TH0,#15H MOV TL0,#0A0H ;即数5536 SETB TR0 ;定时/计数器0开始运行 LOOP:JBC TF0,NEXT ;如果TF0等于1,则清TF0并转NEXT处 AJMP LOOP ;不然跳转到LOOP处运行 NEXT:CPL P1.0 MOV TH0,#15H MOV TL0,#9FH;重置定时/计数器的初值 AJMP LOOP END AJMP LOOP END 键入程序,看到了什么?灯在闪烁了,这可是用定时器做的,不再是主程序的循环了。简单地分析一下程序,为什么用JBC呢?TF0是定时/计数器0的溢出标记位,当定时器产生溢出后,该位由0变1,所以查询该位就可知宇时时间是否已到。该位为1后,要用软件将标记位清0,以便下一次定时是间到时该位由0变1,所以用了JBC指令,该指位在判1转移的同时,还将该位清0。 以上程序是能实现灯的闪烁了,可是主程序除了让灯闪烁外,还是不能做其他的事啊!不,不对,我们能在LOOP:……和AJMP LOOP指令之间插入一些指令来做其他的事情,只要保证执行这些指令的时间少于定时时间就行了。那我们在用软件延时程序的时候不是也能用一些指令来替代DJNZ吗?是的,但是那就要求你精确计算所用指令的时间,然后再减去对应的DJNZ循环次数,很不方便,而现在只要求所用指令的时间少于定时时间就行,显然要求低了。当然,这样的办法还是不好,所以我们常用以下的办法来实现。 程序2:用中断实现 ORG 0000H ,https://www.360docs.net/doc/4810624745.html, AJMP START ORG 000BH ;定时器0的中断向量地址 AJMP TIME0 ;跳转到真正的定时器程序处 ORG 30H START: MOV P1,#0FFH ;关所灯 MOV TMOD,#00000001B ;定时/计数器0工作于方式1 MOV TH0,#15H MOV TL0,#0A0H ;即数5536 SETB EA ;开总中断允许 SETB ET0 ;开定时/计数器0允许 SETB TR0 ;定时/计数器0开始运行 LOOP: AJMP LOOP ;真正工作时,这里可写任意程序 TIME0: ;定时器0的中断处理程序

单片机定时器实验

实验三单片机内部定时器应用 实验目的 1、理解单片机内部定时器的工作原理及使用方法 2、了解单片机定时中断程序的编写和调试方法 3、掌握定时器的基本使用方法 实验仪器 单片机开发板、万利仿真机、稳压电源、计算机 实验原理 1、单片机定时器的工原理 MCS-51 单片机内部有两个16 位可编程的定时器/计数器T0 和T1。它们即可用作定时器方式,又可用作计数器方式。其中T0 由TH0 和TL0 计数器构成;T1 由TH1 和TL1 计数器构成。 工作于定时器方式时,通过对机器周期(新型51单片机可以对振荡周期计数)的计数,即每一个机器周期定时器加1,来实现定时。故系统晶振频率直接影响定时时间。如果晶振频率为12MHZ,则定时器每隔(1/12MHZ)×12=1us 加1。 工作于计数器方式时,对P3.4 或P3.5 管脚的负跳变(1→0)计数。它在每个机器周期的S5P2 时采样外部输入,当采样值在这个机器周期为高,在下一个机器周期为低时,计数器加1。因此需要两个机器周期来识别一个有效跳变,故最高计数频率为晶振频率的1/24。 特殊功能寄存器TMOD 用于定时器/计数器的方式控制。高4 位用于设置T1,低4 位用于设置T0。如图4-7所示。 图4-7 定时器模式控制字格式 TCON 寄存器用于定时器的计数控制和中断标志。如图4-8所示。 图4-8 定时控制寄存器数据格式 编写程序控制这两个寄存器就可以控制定时器的运行方式。 单片机内部定时器/计数器的使用,简而概之:(1)如需用中断,则将EA和相关中断控制位置1;(2)根据需要设置工作方式,即对TMOD设置;(3)然后启动计数,即对TR0或TR1置1。(4)如使用中断,则计数溢出后硬件会自动转入中断入口地址;如使用查询,则必须对溢出中断标志位TF0或TF1进行判断。

51单片机中断系统程序实例

51单片机中断系统程序实例(STC89C52RC) 51单片机有了中断,在程序设计中就可以做到,在做某件事的过程中,停下来先去响应中断,做别的事情,做好别的事情再继续原来的事情。中断优先级是可以给要做的事情排序。 单片机的学习不难,只要掌握学习方法,学起来并不难。什么是好的学习方法呢,一定要掌握二个要点: 1. 要知道寄存器的英文全拼,比如IE = interrupt中断 不知道全拼,要去猜,去查。这样就可以理解为什么是这个名称,理解了以后就不用记忆了。 2. 每个知识点要有形像的出处 比如看到TF0,脑子里马上要形像地定位到TCON寄存器的某位 看到ET0, 马上要形像地定位到IE寄存器的第2位 https://www.360docs.net/doc/4810624745.html,/tuenhai/独家揭秘:形像是记忆的最大技巧。当人眼看到某个图时,是把视觉信号转化成电信号,再转化成人能理解的形像。当我们回忆形像时,就是在重新检索原先那个视觉信号,并放大。在学习过程中,不断练习检索、放大信号,我们的学习能力就会越来越强。 写程序代码时,也要把尽量把每行代码形像化。 51单片机内中断源 8051有五个中断源,有两个优先级。与中断系统有关的特殊功能寄存器有IE(中断允许寄存器)、IP(中断优先级控制寄存器)、中断源控制寄存器(如TCON、SCON的有关位)。51单片机的中断系统结构如下图(注意,IF0应为TF0):

8052有6个中断源,它比8051多一个定时器/计数器T2中断源。 8051五个中断源分别是: (1)51单片机外部中断源 8051有两个外部中断源,分别是INT0和INT1,分别从P3.2和P3.3两个引脚引入中断请求信号,两个中断源的中断触发允许由TCON的低4位控制,TCON的高4位控制运行和溢出标志。 INT0也就是Interrupt 0。在这里应该看一下你的51单片机开发板的电路原理图。离开形像的记忆是没有意义的。读到上面这句,你应该回忆起原理图上的连接。任何记忆都转化为形像,这是学习的根本原理,我们通过学习单片机要学会这种学习方法,会让你一辈子受益无穷。 TCON的结构如下图: (a)定时器T0的运行控制位TR0

单片机定时器汇编

我们在学单片机时我们第一个例程就是灯的闪烁,那是用延时程序做的,现在回想起来,这样做不很恰当,为什么呢我们的主程序做了灯的闪烁,就不能再干其它的事了,难道单片机只能这样工作吗当然不是,我们能用定时器来实现灯的闪烁的功能。例1:查询方式ORG 0000H AJMP START ORG 30H START: MOV P1,#0FFH ;关所灯 MOV TMOD,#00000001B ;定时/计数器0工作于方式1 MOV TH0,#15H MOV TL0,#0A0H ;即数5536 SETB TR0 ;定时/计数器0开始运行 LOOP: JBC TF0,NEXT ;如果TF0等于1,则清TF0并转NEXT处(LOOP:JNB TF0,$) AJMP LOOP ;不然跳转到LOOP处运行 NEXT: CPL MOV TH0,#15H MOV TL0,#9FH;重置定时/计数器的初值 AJMP LOOP END 键入程序,看到了什么灯在闪烁了,这可是用定时器做的,不再是主程序的循环了。简单地分析一下程序,为什么用JBC呢TF0是定时/计数器0的溢出标记位,当定时器产生溢出后,该位由0变1,所以查询该位就可知宇时时间是否已到。该位为1后,要用软件将标记位清0,以便下一次定时是间到时该位由0变1,所以用了JBC指令,该指位在判1转移的同时,还将该位清0.以上程序是能实现灯的闪烁了,可是主程序除了让灯闪烁外,还是不能做其他的事啊!不对,我们能在LOOP:……和AJMP LOOP指令之间插入一些指令来做其他的事情,只要保证执行这些指令的时间少于定时时间就行了。那我们在用软件延时程序的时候不是也能用一些指令来替代DJNZ吗是的,但是那就要求你精确计算所用指令的时间,然后再减去对应的DJNZ循环次数,很不方便,而现在只要求所用指令的时间少于定时时间就行,显然要求低了。当然,这样的办法还是不好,所以我们常用以下的办法来实现。程序2:用中断实现 ORG 0000H AJMP START ORG 000BH ;定时器0的中断向量地址 AJMP TIME0 ;跳转到真正的定时器程序处 ORG 30H START: MOV P1,#0FFH ;关所灯 MOV TMOD,#00000001B ;定时/计数器0工作于方式1 MOV TH0,#15H MOV TL0,#0A0H ;即数5536 SETB EA ;开总中断允许 SETB ET0 ;开定时/计数器0允许 SETB TR0 ;定时/计数器0开始运行 SJMP $ ;LOOP: AJMP LOOP ;真正工作时,这里可写任意程序 TIME0:

51单片机定时器中断

一.定时器相关寄存器 1. 工作方式寄存器(TMOD) 该寄存器用于设置定时/计数器的工作方式,低四位用于定时器0,高四位用于定时器1。GATE:门控位。GATE=0时,只要用软件使TCON中的TR0或TR1为1,就可以启动定时/计数器工作;GATA=1时,要用软件使TR0或TR1为1,同时外部中断引脚INT0/1也为高电平时,才能启动定时/计数器工作。即此时定时器的启动条件,加上了INT0/1引脚为高电平这一条件。 C/T:定时/计数模式选择位。C/T=0为定时模式;C/T=1为计数模式。

2. 定时器/计数器控制寄存器控制寄存器(TCON) 该寄存器的低4位用于控制外部中断,已在前面介绍,高4位用于控制定时/计数器的启动和中断申请。 TF1:T1溢出中断请求标志位。T1计数溢出时由硬件自动置TF1为1。CPU响应中断后TF1由硬件自动清0。 TR1:T1运行控制位。TR1置1时,T1开始工作;TR1置0时,T1停止工作。TR1由软件置1或清0。所以,用软件可控制定时/计数器的启动与停止。 TF0:T0溢出中断请求标志位,其功能与TF1类同。 TR0:T0运行控制位,其功能与TR1类同。 3. 中断允许控制寄存器(IE) ET0:定时/计数器T0中断允许位; ET1:定时/计数器T1中断允许位; EA :CPU中断允许(总允许)位。

二.定时器溢出中断的处理过程 1、设置定时器工作方式 2、为定时器装入初值 3、定时器中断允许位置为1 4、开总中断 5、开定时器,等待产生溢出中断请求 三.实现简单时钟 说明: 1.使用动态数码管显示 2.选择工作方式1,以16位的定时器0进行工作,即TMOD=0x01,中断编号为1; 3.定时50ms,即每隔50ms产生一次中断: TH0=(65536-50000)/256; //16位定时器的高8位 TL0=(65536-50000)%256; //16位定时器的低8位 具体的时间与单片机的晶振有关,请了解机器周期、指令周期、时钟周期等相关知识。#include #define uchar unsigned char#define uint unsigned int uchar hour,min,sec; uchar code wei[8]= {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //共阴极数码管位选编码

51单片机中断程序大全

//实例42:用定时器T0查询方式P2口8位控制LED闪烁#include<> // 包含51单片机寄存器定义的头文件 void main(void) { // EA=1; //开总中断 // ET0=1; //定时器T0中断允许 TMOD=0x01; //使用定时器T0的模式1 TH0=(65536-46083)/256; //定时器T0的高8位赋初值 TL0=(65536-46083)%256; //定时器T0的高8位赋初值 TR0=1; //启动定时器T0 @ TF0=0; P2=0xff; while(1)//无限循环等待查询 { while(TF0==0) ; TF0=0; P2=~P2; TH0=(65536-46083)/256; //定时器T0的高8位赋初值 TL0=(65536-46083)%256; //定时器T0的高8位赋初值 | //实例43:用定时器T1查询方式控制单片机发出1KHz音频#include<> // 包含51单片机寄存器定义的头文件 sbit sound=P3^7; //将sound位定义为引脚 void main(void) {// EA=1; //开总中断 // ET0=1; //定时器T0中断允许 TMOD=0x10; //使用定时器T1的模式1 TH1=(65536-921)/256; //定时器T1的高8位赋初值 TL1=(65536-921)%256; //定时器T1的高8位赋初值 TR1=1; //启动定时器T1 — TF1=0; while(1)//无限循环等待查询 { while(TF1==0); TF1=0; sound=~sound; //将引脚输出电平取反 TH1=(65536-921)/256; //定时器T0的高8位赋初值

相关文档
最新文档