51单片机定时器和中断知识
  RGE9SaKkXr6k 2023年11月19日 20 0

什么是定时器/计数器? --- 既可以定时,也能计数的一种单片机内部资源,主要用于软件计时和软件延时等场合。但同一时刻只能使用其中一种功能。

定时器的核心功能简单一句话说就是“启动定时器后,每个机器周期到来,初值寄存器自动加1,直到计满溢出”。

定时器的工作流程:

1.启动信号

2.预设机器周期--以12MHZ为例,单片机时钟信号÷12=1MHZ,等于一个机器周期是1us

3.按预设初值寄存器来启动计算; TH0=高八位,TL0=低八位;初值都为00H;

4.满足条件自动加1;TL0低位开始+1,+至1111 1111(255); 从高位继续+1,+至1111 1111 1111 1111;继续+1则溢出;

5.溢出;(65535)再+1变成1 0000 0000 0000 0000; 此时溢出,定时结束


那么如果要定时50ms,该如何实现呢?

首先要进行初值计算:

定时时长:65536us,计算机周期个数:65536个;

定时时长:50000us,计算机周期个数:50000个;

计算方法为:初值X=65536-50000=15536; 

15536换算为16进制为3Cb0H;

即初值为:TH0=0x3c;  TL0=0xb0;

TH0存放的是256取整;TL0存放的是小于256的余数;

所以可以写成:TH0=(65535-50000)/256;

TL0=(65535-50000)%256;

以上就解决了初值计算的问题,假设需要定时大于65536的时间,比如1秒,则需要再程序内部加循环,1s=50ms×20次;或者10ms×100次;


定时器的编程实现步骤:

1.报备---2.置初值---3.启动---4.等待---5.重置初值---6.清溢出

1.报备  

TMOD (89H)

D7

D6

D5

D4

D3

D2

D1

D0

工作模式寄存器

GATE

C/T

M1

M0

GATE

C/T

M1

M0


        T1字段

        T0字段

GATE:门控位,为0时,将TR0=1,则启动定时器。   为1时,TR0=1还需要加上外部中断引脚INT0共同启动。

C/T:0定时;1计数;

M1/M0(工作方式):00:方式0; 01:方式1;  10:方式2; 11:方式3; 最后得到TMOD的值:0000 0001;0x01;


2.置初值

50ms为例: TH0=0x3c; TL0=0xb0;


3.启动

TR0=1; 启动

TR0=0; 停止

TCON(88H)

TF1

TR1

TF0

TR0

IE1

IT1

IE0

IT0











4.等待

TF0溢出位,溢出自动置1;

为了保证下一次溢出时能够正常置1;需要将TF0手动清0;TF0=0;

while(TF0==0); 查询TF0是否为1,来判断溢出;为1就是时间到了,溢出了;

5.重置初值

如果定时1s就需要50ms×20次,在溢出后要重置初值并循环20次

6.清溢出

溢出后TF0=1;为了保证下次溢出正常计数,需要手动置0:TF0=0;



中断的基本知识

中断源

中断允许标志位

中断请求形式

中断请求标志位

中断号

外部中断INT0

EX0

低电平

IE0

0

定时器T0

ET0

溢出

TF0

1

外部中断INT1

EX1

低电平

IE1

2

定时器T1

ET1

溢出

TF1

3

串口

ES

接收或发送结束

TX/RX

4


  IE寄存器 中断允许寄存器

D7

D6

D5

D4

D3

D2

D1

D0

EA

X

X

ES

ET1

EX1

ET0

EX0

EA:总中断允许标志位


中断流程:

中断源---中断允许---中断请求---中断响应---断点---中断号---中断返回


中断服务程序示例:

timer0:函数名字可以随便取;  interrupt:中断关键字; 1:中断号;

void timer0 () interrupt 1

{

}

中断演示--定时50ms,循环2次,即100ms,LED灯循环左移一次

代码分为两部分:1.主函数部分;2.中断服务程序部分

uchar k = 0;  //由于K将要在中断服务函数中调用,所以K需要定义为全局变量

void main()
{
	uchar n = 0; i = 0;
  TMOD=0x01;         //工作模式
  TH0=(65536-50000)/256;		//定时器置初值
  TL0=(65536-50000)%256;		//定时器置初值
  EA=1;				//中断总开关
  ET0=1;			//中断允许标志位
  TR0=1;			//启动计时器
  while(1)
  {
  	n=0x01;   
    for(i=0;i<8;i++)    //循环8次
    {
    	P0=~n;						//进入第一次循环,并点亮第一颗灯
      while(k<2);				 //等待,等待时间到来,然后进入中断
      k=0;							 //中断服务程序中的内容执行完以后,K置0重新计数;
      n=n<<1;						 //LED灯左移一位
    }
  }
}
中断服务程序
//定时器T0中断服务程序
void timer0 () interrupt 1
{
	TH0=(65536-50000)/256;
  TL0=(65536-50000)%256;
  K++;
}


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月19日 0

暂无评论

推荐阅读
RGE9SaKkXr6k
最新推荐 更多