您的位置:首页 > 其它

51定时器中断程序编写 [李园7舍_404]

2012-12-01 08:17 267 查看
上篇笔记记录到51单片机的中断允许寄存器定时器/计数器工作方式寄存器(TMOD)、定时器/计数器控制寄存器(TCON)各位的作用。这些寄存器都是用来为编写定时器中断程序编写的初始化部分而服务的。然后今天再这里补填中断函数的编写格式,以后就可以编写定时器中断程序了。



1.中断服务程序的写法

C51的中断函数格式如下:

void 函数名() 中断号 using 工作组

{

中断服务程序内容

}

与一般的C语言程序相比,中断服务程序有一下特点

中断函数不能返回任何值,所以函数名前用void;
函数名随便起,但不能与C51语言中的关键字同名(同C语言函数要求)
中断函数不能带任何参数,故函数名后的括号内为空
中断号是指单片机中的几个中断源的序号,列表如下(红方框内内容)



图1.51单片机中的中断源

此序号是编译器识别不同中断的唯一符号,在程序编写中定要写正确

“using 工作组”是指这个中断函数使用单片机内存中4组工作寄存器中的哪一组,C51编译器在编译程序时会自动分配工作组,因此这句话经常被省略不写。

2.定时器1中断程序编写

#include <reg52.h>

#define uint unsigned int

#define MANY_KEY_DELAY  1
#define TOTAL_TIME_NUM  5
#define ONE_SECOND      20

uint num;
uint num1;

uint flag_key;

//流水灯的第一列
sbit led1 = P1^0;
//第一个按钮位
sbit key = P3^1;
//按钮的接地端
sbit h_key6 = P3^6;

//函数申明
void T1_end_AND_change_status();
void delayms(uint xms);
void init_timer();
void data_init();
void key_scan();

void main()
{
        //初始化数据变量
        data_init();

        //初始化T1定时器
        init_timer();

        while(1){

                //不断检测此按钮是否被按下
                key_scan();

                //检测一个大周期定时是否完成
                //使按下按钮后相应的位发生电平反转
                T1_end_AND_change_status();
        }
}

//自定义函数:数据初始化
void data_init()
{
     num        = 1;
     num1       = 1;
     flag_key   = 0;
     h_key6     = 0;   
}

//自定义函数:初始化TMOD、TCON、中断寄存器,并装入计数初值
void init_timer()
{
        //选中定时器1
        TMOD    = 0x10;

        //定时器1的初值
        TH1     = (65536 - 45872) / 256;
        TL1     = (65536 - 45872) % 256;
        
        //开总中断,     
        //定时器1中断
        EA         = 1;
        ET1        = 1;
}

//自定义函数:延迟xms ms
void delayms(uint xms)
{
        uint i, j;

        for(i = xms; i > 0; i--)
                for(j = 110; j > 0; j--);
}

//自定义函数:检测哪一个按键被按下
void key_scan()
{
        if(key == 0){
                //<1>.待按钮被按下后的稳定状态
                delayms(10);
    
                //<2>.操作:
                //开启定时器,由T1时间到达关闭T1定时器
                TR1 = 1;
    
                //记住按钮已被按下
                flag_key    = 1;
    
                //点亮响应的流水灯
                led1        = 0;
    
                //<3>.等待按键的释放
                while(!key);    
        }      
}

void T1_end_AND_change_status()
{
        //T1计时完成
        if(num >= TOTAL_TIME_NUM * ONE_SECOND){
                num     = 0;
                
                //检测有哪些按钮被按下,结束其高低电平的转换
                if(flag_key){
                        flag_key       = 0;

                        //按钮信号以低电平结束
                        led1    = 1;
                                
                        //一旦检测到总的计时时间到则关闭定时功能
                        //当有任何按钮再次被按下时,T1定时器再被开启
                        //需要在按钮被按下的前提下设置此语句,防止没有任何按钮按下时到达定时器时间设置
                        TR1     = 0;
                 }
        }
        
        //按钮的电平反转
        if(num1 >= MANY_KEY_DELAY * ONE_SECOND){
                num1    = 0;
                if(flag_key){
                        led1    = ~led1;
                }
        }
             
}

//中断函数编写
void T1_time() interrupt 3
{
     TH1        = (65536 - 45872) / 256;
     TL1        = (65536 - 45872) % 256; 
     
     num++;
     num1++;    
}


此源程序经编译链接生成可执行文件后,下载到单片机中,按下key对应的按键时,流水灯1就会以1s的高低电平交换显示。照片一张作为纪念:



图2.闪烁的流水灯

3.程序分析

程序从main函数出开始运行。自在main函数中对个寄存器初始化后,待按键按下(TR1=1)时,定时器1开始从当前值开始计时,当计数计满溢出时,TCON的TF1向CPU申请中断从而进入中断函数内执行中断函数内的语句,当把中断函数内的语句执行完毕后,再返回到main函数开始中断处。当在中断函数中重新给定时器赋新值后(若不赋新值,则从0开始计),则将又会过与原来一样长的时间后发生中断。
此程序的中断周期是50ms(晶振频率为11.0592)。此程序随时等待按钮被按下,只有按钮被按下时才开始计时,中断程序才会生效。定时器被启动后,将会以50ms的周期进行中断产生,当计满1s时,流水灯的状态反转一次。当计满5s后定时器再次被关闭。程序重新等待按钮被按下。

4.总结

使用定时器中断的方式可以得到以高低电平反转的方波。在现实生活中我们可以用这种方波做很多事情,如红外遥控器就是采用的此种原理对不同按钮进行编码,经发射电路将此方波发射出去,再由相应的接收电路接受此方波,然后对其进行解码,得到原信号进而可以判断此信号是想要做出什么样的操作。
当然,使用单片机编写程序不再是单纯的写代码,还需要会阅读各种电路图和电器件的特性。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: