51单片机学习之路 —— 1.6 单片机的中断(2)

上一次我们简单了解了单片机的中断概念

这一次我们着重了解单片机的定时器中断

 

先补充点知识

补 : 单片机的几个周期

      1:时钟周期:也称振荡周期,就是外接晶振的倒数,如12M的晶振,时钟周期就是1/12um,他是最基本最小的时间单位。
       2:状态周期:时钟周期的两倍。
       3:机器周期。单片机的基本操作周期,在一个周期内单片机完成一项基本操作,他由12个时钟周期组成,比如12M的晶振,那么机器周期就是1um。其实机器周期就是完成一个单指令的时间。
       4:指令周期。他是指CPU执行一条指令所需的时间。比如有单周期指令,双周期指令三周期指令等等。

 

1  定时器简单概念了解

  

  1 定时器系统是单片机内部独立的一个硬件部分

  2 定时器与晶振cpu相连

  3 一但设置开始定时后,定时器在晶振的作用下自动开始计时

   

      

  

  

    注意:1 TMOD 的字节地址位89H是不可寻位址

        所以写代码的时候要不能位操作,只能TMOD = 0x01;这样子

       2 TMOD中高四位用于设置定时器1 低四位用于设置定时器0

       3 TMOD常用的模式有方式1(常用) 2(偶尔)其余几乎不用

       4 TMOD 只控制定时器的工作方式和功能选择

    举个栗子:

       TMOD = 0x01;// 0000 0001  

(定时器0,GATE=0 启动仅受寄存器TRX控制 C/T=0 定时器模式 M1=0 M0=1 工作模式1 16位定时器)

      

 2 TCON

    

    注意:1 TCON字节地址位88H 可进行位寻址

       2 单片机复位TCON全部被清零

    这里我们先着重记几个

       1 TF1 定时器1溢出标志位

       2 TF0 定时器0溢出标志位

         3 TR1 定时器1运行控制位  

       4 TR0 定时器0运行控制位 

 

3 工作原理

 

 

 

4  初值问题

    

      注意 :1 没有设置TH0和TL0 默认值都是0  

           所以要溢出需要65536个数  1111 1111 1111 1111

          (65535达到满值,65536则溢出将TF0 置1)

    举个栗子:

      假如我们要定时50ms(较常用的一个时间)

      单片机的晶振是12MHz  12个时钟周期位1个机器周期 (1/12MHz )*12 = 1微秒

      我们定时50ms一次  即装完初值后,在(50/1)*10^3 =50000个数后溢出

      所以初值为 65536-50000 = 15536个数

      15536 又要化成16进制 先分出高八位和低八位

      15536/256=60装入TH0 15536%256=176装入TL0

 

5   中断服务程序的写法

    

    

      定时器中断序号为3 定时器1

 

2  编程

   

   1 目标 : 实现第一个发光二极管以1s亮灭闪烁

     

   2 代码

 1 #include<reg52.h>
 2 #define uint unsigned int
 3 #define uchar unsigned char
 4 sbit LED1 = P1^0;
 5 uchar num;
 6 void main()
 7 {
 8     TMOD = 0x01; // 定时器0 工作方式1
 9     TH0  = (65536 - 45872)%256; 
10     TL0  = (65536 - 45872)/256;
11     EA   = 1;     //开关总断
12     ET0  = 1;     // 开定时器0中断
13     TR0  = 1;     //启动定时器0
14     while(1);     //程序停止等待中断发生
15 }
16 
17 void T0_time() interrupt 1
18 {
19     TH0  = (65536 - 45872)%256;
20     TL0  = (65536 - 45872)/256;
21     num++;
22     if(num == 20)
23     {
24         num = 0;
25         LED1 = ~LED1;
26     }
27 
28 }
一秒亮灭

 

   3 分析:

      

       1 设置好TMOD后 要对应ET0 TR0 TH0 TL0

       2 不要省事情把45872 写成 (5000/(12/11.0592))

       11.0592是小数,无法转化成 16进制

       3 为了确保定时器中断每次都是50ms 我们需要在中断函数中每次为TH0 和TL0

       重新装入初值

       4 定的是50ms 用一个变量num统计每二十次执行程序 即每1s亮灭

   改良代码:

    

 1 #include<reg52.h>
 2 #define uint unsigned int
 3 #define uchar unsigned char
 4 sbit LED1 = P1^0;
 5 uchar num;
 6 void main()
 7 {
 8     TMOD = 0x01; // 定时器0 工作方式1
 9     TH0  = (65536 - 45872)%256; 
10     TL0  = (65536 - 45872)/256;
11     EA   = 1;     //开关总断
12     ET0  = 1;     // 开定时器0中断
13     TR0  = 1;     //启动定时器0
14     while(1);     //程序停止等待中断发生
15     if(num == 20)
16     {
17         num = 0;
18         LED1 = ~LED1;
19     }
20 
21 }
22 
23 void T0_time() interrupt 1
24 {
25     TH0  = (65536 - 45872)%256;
26     TL0  = (65536 - 45872)/256;
27     num++;    
28 }
1s亮灭2

  

 

 

留一个作业 大家可以自己写写看

    用定时器0实现第一个发光二极管以200ms间隔闪烁 并且用定时器1 实现数码管前两位59s循环计时

      

 

以上的内容都是博主看书,自己的一些思考。大家还是应该多看些书籍才能够理解的更好

 

ok 假如你在博客中发现任何错误和不足之处,请及时联系博主,博主会及时更正博客,以免给大家带来误导 >_<  

posted @ 2016-10-16 22:46  cc陈  阅读(441)  评论(0)    收藏  举报