您的位置 首页 培训

单片机定时器中止原理和C言语代码详解

我之前都是用ARM7,单片机基本不会。但一个项目要用到51,所以克了一下51还是有点模糊,今天调了这个代码之后,对51定时器中断有些心得,拿

我之前都是用ARM7,单片机根本不会。但一个项目要用到51,所以克了一下51仍是有点含糊,今日调了这个代码之后,对51守时器中止有些心得,拿来和咱们同享。废话不说了,上代码。

#define _1231_C_
#include “reg51.h”
#include “1231.h”

//sbit OE=P2^3;

unsigned int SystemTime;

void timer0(void) interrupt 1 using 3 //中止部分代码,见下文的释疑
{

TH0 = 0xdb;
TL0 = 0xff;
// TF0 = 0;

SystemTime++;
}

void main()
{

TMOD &= 0xF0;
TMOD |= 0x01; //TMOD的值表明守时器作业办法挑选

TH0 = 0xdb; //写入初始值,初始值能够决议守时多久
TL0 = 0xff;
//依据下文的木桶比方的话,假如TH0 = 0x00;TL0 = 0x00;则表明从桶底开端装水。
//TH0 = 0xdb;TL0 = 0xff;能够这姿态了解相当于木桶里现已有部分液铅在里边,
//TH0和TL0这个两个值表明木桶里液铅的高度,即此刻桶里只能从液铅的高度以上开端装水,
//TH0 = 0xff;TL0 = 0xff;即表明桶的最高方位.

TF0 = 0; //计数届时TF0为1,即当TH0 = 0xff;TL0 = 0xff;再运转一步TF0 = 1;
TR0 = 1; //开端计数,从这时起,每运转一步TH0和TL0都会添加,直到TH0 = 0xff;TL0 = 0xff;
//相当于开水龙头,如TR0=0则TH0和TL0不变

ET0 = 1; //答应守时器0中止
EA=1; //开总中止

//下面是个死循环,程序里每运转一步TH0和TL0都会添加,当添加到TH0 = 0xff;TL0 = 0xff;
//单片时机从死循环里退出,去履行中止部分的代码,即开端运转void timer0(void) interrupt 1 using 3{}
//运转完中止部分的代码后,接着持续履行死循环里的代码。
//留意:当TH0 = 0xff;TL0 = 0xff;再运转,TF0并没有从0变为1,个人猜想TF0=1;时触发了中止,并从头被置零。
//如把ET0 = 1;和EA=1;注释掉,当TH0 = 0xff;TL0 = 0xff;再运转,TF0会变为1,此刻不会再履行中止部分代码。

while(1)
{
if ((SystemTime%100)<50) //SystemTime除以100,余数小于50为真
{
//这两行不必管,就作为是功用1
P0=0xf1;
P2=0xf0;

}
else
{
//这两行不必管,就作为是功用2
P0=0x00;
P2=0xf0;

}

};

}

释疑:void Timer0() interrupt 1 using 1

Timer0 是函数名,随意取的

interrupt xx using y

跟在interrupt 后边的xx 值得是中止号,便是说这个函数对应第几个中止端口,一般在51中

0 外部中止0

1 守时器0

2 外部中止1

3 守时器1

4 串行中止

实践上编译的时分便是把你这个函数的进口地址方到这个对应中止的跳转地址

using y 这个y是说这个中止函数运用的那个寄存器组,51里边一般有4组 r0 r7寄存器,一共有32个,假如你的终端函数和其他程序用的不是同一个寄存器组则进入中止的时分就不会将寄存器组压入仓库回来时也不会谈出来节约代码和时刻

初始值算法:守时器是当总数到达FFFFH后产生中止吧!那你要让它计数10000,是不是用FFFF(16进制)减去10000(十进制)的数当计数初值啊?TH0=-(10000/256); TL0=-(10000%256)跟FFFF(16进制)减去10000(十进制)的数是相同的。从TH0=-(10000/256); TL0=-(10000%256)开端计数,计数到10000刚好满。跟用FFFF(16进制)减去10000(十进制)的数相同!!!写起来更简略,不必算!!!
看看原码、补码就知道。正数的补码是对应的二进制数,符号位为零,负数的补码是它的绝对值对应的二进制数按位取反再加一,符号位为一。无符号数不考虑符号,那么这个成果就跟用FFFF减去它的绝对值相同

咱们学习了用指令延时闪灯,可是用指令办法闪灯有cpu不能做其他作业的缺陷。
这一课,咱们将学习怎样运用守时器办法使灯闪耀。
中止的了解。
这儿将涉及到单片机中止的运用,在cpu的一步步依照指令运转的过程中(主程序),或许会有其它的更紧迫的需求做的作业(中止服务程序),需求cpu暂时中止当时的程序(主程序),做完了(中止服务程序)之后,又能够持续去运转从前的程序(主程序)。就像你正在吃饭,一边又在给水桶里放水,吃着吃着,水满了,你就得赶快去把水龙头关掉或许换一个空的水桶,再回来吃饭。
单片机的守时器就像是一个水桶,你让它启动了,也便是水龙头打开了;开端装水了;守时在每个机器周期不断主动加1,最终溢出了;水桶的水不断添加,最也就满出来了;守时器溢出时,你就要去做处理了;水桶的水满了,你也应该处理一下了;处理完后,单片机又能够回到刚刚开中止的当地持续运转;水桶处理了,从前你在做什么也能够持续去做什么了。
单片机的主程序是从0x0000开端运转的,单片机服务程序从哪里开端运转呢?在51里,有多个中止服务程序进口,0号进口是外中止0,地址在0x0003;1号进口是守时器0,在 0x000B;2号进口是外中止1;地址在0x0013,3号进口是守时器2;地址在0x001B,等等。当中止产生时,程序就记下当时运转的方位,跳到对应的中止进口去运转中止服务程序,运转完之后,又跳回到本来的方位持续运转。
在C51中,你不必理睬中止服务程序放在哪里,会怎样跳转。你只要把某个函数标识为几号中止服务函数就能够了。在产生了对应的中止时,就会主动的运转这个函数。
请看一下相关的51的硬件的书,对守时器作业的寄存器设置做进一步的了解。也能够做完实验再了解,由于例程中都现已为您设置好了。
请看程序,主程序里的循环里是个死循环,什么也没有做,在实践运用中这儿是放的主程序。
在守时器服务函数里,需求从头置入守时器的值,这样才干确保每次溢出时,都是你指定的时刻。这儿置入的是0x0006,还需求走 0x10000-0x0006个机器周期才溢出。换成10进制也便是每65530个机器周期中止一次。咱们仿真的晶振是22118400HZ,每12个时钟一个机器周期。65530×12/22118400=0.036秒。也便是差不多28HZ的闪耀频率。
由于51的守时器最大只要0xffff,溢出的速度很快,无法做出更久的闪耀频率来,这一课就先调查一下这个28HZ左右频率。鄙人一课咱们会用静态变量的办法,做一个长达1秒钟的LED闪耀频率。
别的,由于51从中止产生到进入中止的时刻不定,是3至8个机器周期,咱们在进入了中止后才从头置新的守时器初始值,这样就会存在守时差错。也便是不是准确守时,假如要准确守时,需求运用守时器主动装载办法,也便是在守时器溢出的一起,硬件逻辑就主动把守时器初始值装载进去了,而不是在中止服务程序里赋初始值,这样就能够完成准确守时,差错只呈现晶振的频率上。这是下一颗的内容。
现在请细心研究一下程序,并编译,进入仿真,全速运转,调查运转成果。咱们能够看到P10上的LED在快速闪耀。
趁便,也请再操练一下中止,单步,断点等等的调试办法。
一个特别的当地,运用DX516在单步时运转时,或许无法进入到中止服务函数中。这是由于中止函数或许在单步处理的瞬间现已运转过去了。假如要单步调试中止服务函数,请在中止服务函数内设置断点,再点全速。稍后就会中止在断点上,就能够持续单步运转了。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/changshang/peixun/260868.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部