RTI -- 实时中断

实时中断并不复杂,简单地说,就是一个定时模块,定时溢出,产生中断。功能跟
PIT差不多,都能用于定时。 对于PIT 时钟电路每固定一段时间都必须更新一次时间信息,这个更新的责任就落到了MCU身上。对于那种比较繁重的系统而言,“进行一次更新”会耗费许多的资源。而RTI只专注于记时工作,使MCU可以空出来处理其它的工作。外部晶振时钟可以直接“驱动”RTI。
RTI定时不会很准,因为它没有经过复杂的时钟处理,经过配置之后,可以变为a2^b
倍数,因为a
2^b不能是任意数整数,不能配成你想要的任何频率,所以说RTI定时不会很准,不过它用起来还是很灵活、方便的。

本例通过用MC9S12XS128MAA来做一个实时中断。
以下为本例所用到的寄存器的介绍:

RTICTL寄存器

在这里插入图片描述
RTDEC(十进制或二进制分频器选择位) = 1 时,为十进制分频器
= 0 时,为二进制分频器

RTR[6:0]为有效分频因子,RTR[3:0]为低4位m ,RTR[6:4]为高3位n,RTI的参考时钟是外部晶振的时钟OSCCLK,即外部物理晶振提供的时钟
当RTDEC=0时,分频系数=(m+1)*2^(n+9)
当RTDEC=1时,分频系数=(m+1)*RTR[6:4]下表对应值
在这里插入图片描述
RTR[6:4]=000时RTI实时中断被禁止,只要当RTR[6:4] 不全为0时,实时中断就开启

CRGINT寄存器
在这里插入图片描述
RTIE = 1 时,实时中断开启
= 0 时,实时中断禁止

LOCKIE = 1 时,LOCKIF置位就会引起中断请求
= 0 时,LOCK中断请求无效

SCMIE = 1 时,SCMIF置位就会引起中断请求
= 0 时,SCM中断请求无效

CRGFLG寄存器
在这里插入图片描述
RTIF = 1 时,产生RTI中断
= 0 时,未发生RTI中断

PORF = 1 时,上电复位中断
= 0 时未产生上电复位中断

LVRF = 1 时,低压复位中断
= 0 时,未发生低压复位中断

LOCKIF = 1 时,LOCK位状态改变
= 0 时,LOCK位没有改变

LOCK = 1 时,VCOCLK在目标频率误差允许范围内
= 0 时,VCOCLK不在目标频率误差允许范围内

ILAF = 1 时,非法地址重置
= 0 时,未发生非法地址重置

SCMIF = 1 时,SCM位状态改变
= 0 时,SCM位没有改变

SCM = 1 时,MCU在自时钟模式下工作,OSCCLK处于未知状态,所有时钟都是由PLLCLK产生的
= 0 时,MCU正常工作,OSCCLK可用

实时中断设置步骤:
1.设置TRICTL里面设置多少个时钟脉冲中断一次
2.CRGINT里使能RTI中断
3.写中断函数interrupt 7 void rti(void)
{
//这里写中断需要执行的程序
CRGFLG_RTIF=1;//中断标志清零
}

以下是实现RTI中断的完整代码:

#include             
#include "derivative.h"      
#define LED PORTB_PB0      //定义连接发光二级管的PORTB_PB0口数据寄存
                           //器为LED,写'0'亮,写'1' 灭

#define LED_dir DDRB_DDRB0  //定义连接发光二级管的PORTB_PB0口方向寄存器
                            //为LED_dir,写'0'做输入口,写'1'做输出口

unsigned char times = 0;   //定义定时中间变量


void INIT_RTI(void)    //初始化RTI
{
  CRGINT = 0x80;       // RTIE=1 使能实时中断
                     
  RTICTL = 0x6f;       //设置RTICTL为 0110 1111 溢出周期为 (15+1)*2^(6+9)/(16M)= 16*2^15/(16M)
                       //16M是外部晶振的频率,实时中断以外部晶振时钟为参考时钟
                       //设置实时中断的时间间隔为32.768ms     
}


#pragma CODE_SEG __NEAR_SEG NON_BANKED   //中断函数置于非分页区内

interrupt VectorNumber_Vrti void a(void)     //实时中断函数
{
  if(CRGFLG_RTIF == 1)      //CRGFLG_RTIF实时中断的标志位
    CRGFLG_RTIF = 1;        //向CRGFLG_RTIF 写1,可以清零标志位
  times += 1;              //定时中间变量自加
  if(times == 15)          //定时中间变量等于15时,即定时等于15* 32.768ms=492ms时执行下面程序
  {
    times = 0;             //定时中间变量清零
    LED = ~LED;             //指示灯翻转一次,现象闪烁
  }
}

#pragma CODE_SEG DEFAULT   //后续代码置于默认区域内  



void main(void) {
  DisableInterrupts;   //禁止所有中断打开
  INIT_RTI();          //实时中断模块初始化
  LED_dir = 1;         //设置连接发光二级管的PORTK_PB0口为输出口
  LED = 0;             //初始化发光二极管为亮
  EnableInterrupts;    //开启所有中断打开

  for(;;) {}           //主函数空循环时单片机处于执行状态,程序在rti中断函数中执行
}

将中断里写入LED取反,可以直观的看到RTI中断的效果,可以修改 if(times == 15) 此行代码,如if(times == 30),可以发现指示灯大约1s闪烁一次

你可能感兴趣的:(单片机)