原创 匠人DIY旋转时钟全程实播(连载21:中断服务源程序)

2008-3-5 22:58 3295 8 8 分类: MCU/ 嵌入式

相关连接:jhinfo.gif [匠人DIY旋转时钟 系列文章 (连载中…)]


//--------------------------------------------------------
// 项目:
// 模块:中断服务
// 说明:
// 设计:程序匠人(版权所有,引用者请保留原作者姓名)
//--------------------------------------------------------
/*
版本说明:
Interruption.c  2008-2-10 15:36



*/
//--------------------------------------------------------



//--------------------------------------------------------
//插入文件包
//--------------------------------------------------------
#include "common.h"
//--------------------------------------------------------



//--------------------------------------------------------
//显示段码表(模拟表盘)
//--------------------------------------------------------
const tU08 LED_TAB_12369[]=
{          //编号 字符
 0X3E, 0X0, 0X0, 0X3A, 0X2A, 0X2A, 0X2A, 0X2A, 0X2E, //0 12 正向
 0X3E, 0X2, 0X2, 0X2, 0X3E, 0X2, 0X2, 0X2, 0X3E, //1 3 左旋90度
 0X2E, 0X2A, 0X2A, 0X2A, 0X2A, 0X2A, 0X2A, 0X2A, 0X3E, //2 6 左旋180度
 0X3E, 0X20, 0X20, 0X20, 0X3E, 0X22, 0X22, 0X22, 0X3E, //3 9 左旋270度
};


//--------------------------------------------------------
//显示段码表
//--------------------------------------------------------
const tU08 LED_TAB_A[]=
{          //编号 字符
 0X3E, 0X22, 0X22, 0X22, 0X22, 0X22, 0X22, 0X22, 0X3E, //0 0   
 0X0, 0X0, 0X20, 0X24, 0X3E, 0X20, 0X20, 0X0, 0X0, //1 1   
 0X3A, 0X2A, 0X2A, 0X2A, 0X2A, 0X2A, 0X2A, 0X2A, 0X2E, //2 2   
 0X2A, 0X2A, 0X2A, 0X2A, 0X2A, 0X2A, 0X2A, 0X2A, 0X3E, //3 3   
 0X18, 0X18, 0X14, 0X14, 0X12, 0X3E, 0X10, 0X10, 0X10, //4 4
 0X2E, 0X2A, 0X2A, 0X2A, 0X2A, 0X2A, 0X2A, 0X2A, 0X3A, //5 5   
 0X3E, 0X2A, 0X2A, 0X2A, 0X2A, 0X2A, 0X2A, 0X2A, 0X3A, //6 6   
 0X2, 0X2, 0X2, 0X2, 0X2, 0X32, 0XA, 0X6, 0X2, //7 7   
 0X3E, 0X2A, 0X2A, 0X2A, 0X2A, 0X2A, 0X2A, 0X2A, 0X3E, //8 8   
 0X2E, 0X2A, 0X2A, 0X2A, 0X2A, 0X2A, 0X2A, 0X2A, 0X3E, //9 9
 0X0, 0X0, 0X0, 0X0, 0X14, 0X0, 0X0, 0X0, 0X0, //10 :   
 0X2, 0X0, 0X0, 0X1C, 0X22, 0X22, 0X22, 0X22, 0X22, //11 ℃ 
 0X8, 0X1C, 0X1C, 0X3E, 0X3E, 0X3E, 0X1C, 0X1C, 0X8, //12 钟摆小球 
 0X0, 0X0, 0X0, 0X0, 0X0, 0X0, 0X0, 0X0, 0X0, //13 空白
 0X0, 0X4, 0X4, 0X4, 0X1E, 0X24, 0X24, 0X14, 0X0, //14 t
 0X8, 0X8, 0X8, 0X8, 0X8, 0X8, 0X8, 0X8, 0X8, //15 -
 
};


 



//--------------------------------------------------------
//中断服务程序
//--------------------------------------------------------
void interrupt ISR(void)
{
 tU08 i,j ;


 //================
 //TMR1中断,用于显示扫描控制
 //================
 if ( TMR1IF && TMR1IE)     
 {
  TMR1IF = 0 ;     //清除中断标志
  TMR1ON = 0 ;     //TMR1暂停
  TMR1HL = TMR1HL + DISP_TIME_SET ;  //TMR1重新赋初值
  TMR1ON = 1 ;     //TMR1启动


  if ( ++TIMR1_JSQ > 250 ) TIMR1_JSQ = 250 ; //TIMR1溢出计数器+1,>最大值,=最大值


  if ( ++DISP_LINE > 179 ) DISP_LINE = 0 ; //显示列计数器+1,>最大值,=0
  
  //========
  //根据显示列计数器,刷新显示缓冲区
  //========
  
  //清IO临时缓冲区
  PORTA_TMP = 0B00111100 ; 
  PORTB_TMP = 0B11111110 ;
  PORTC_TMP = 0B00001011 ;


  if ( MOTOR_ST_FLAG )     //电机状态标志=1?(0=关闭,1=开启)
  {
   //显示状态
   if ( SET_EN_FLAG == 0 )
   {
    //根据显示状态判断
    switch( DISP_MODE )     
    {
     case  0:     //显示状态0:模拟钟  
                    
      //标整点,以及显示数字12,3,6,9
      if ( (DISP_LINE >= 176) || (DISP_LINE <= 4))  //12点
      {
       i=DISP_LINE+4+9*0 ;
       if ( i>=180) i="i-180" ;
      }
      else if ( (DISP_LINE >= 41) && (DISP_LINE <= 49)) //3点
      {
       i=DISP_LINE-41+9*1 ;
      }
      else if ( (DISP_LINE >= 86) && (DISP_LINE <= 94)) //6点
      {
       i=DISP_LINE-86+9*2 ;
      }
      else if ( (DISP_LINE >= 131) && (DISP_LINE <= 139)) //9点
      {
       i=DISP_LINE-131+9*3 ;
      }
      else
      { 
       i = 255 ;     //禁止后面的查表动作
       switch (DISP_LINE)    
       {
        case 180*1/12 :    //1点
        case 180*2/12 :    //2点
        case 180*4/12 :    //4点
        case 180*5/12 :    //5点
        case 180*7/12 :    //6点
        case 180*8/12 :    //7点
        case 180*10/12 :   //10点
        case 180*11/12 :   //11点
          LED01_TMP = 0 ;
         break;
       }
      }
      if ( i < (9*4) ) PORTB_TMP &= ~LED_TAB_12369 ; //查表显示12,3,6,9
                    
      
      //显示指针"时"
      i = H_LINE ;
      j = H_LINE ;
      if ( ++i > 179 ) i="0" ;    //i+1,结果>179,则清零
      if ( --j > 179 ) i="179" ;   //j-1,结果为负,则重新赋值179
                    
      if ( ( DISP_LINE == H_LINE ) || ( DISP_LINE == i ) || ( DISP_LINE == j ))
      {
       LED09_TMP = 0 ; 
       LED10_TMP = 0 ; 
       LED11_TMP = 0 ; 
       LED12_TMP = 0 ; 
       LED13_TMP = 0 ;
      }
                    
      //显示指针"分"
      if ( DISP_LINE == M_LINE )    
      {
       LED08_TMP = 0 ; 
       LED09_TMP = 0 ; 
       LED10_TMP = 0 ; 
       LED11_TMP = 0 ; 
       LED12_TMP = 0 ; 
       LED13_TMP = 0 ;
      }
                    
      //显示指针"秒"
      if ( DISP_LINE == S_LINE )    
      {
       LED06_TMP = 0 ; 
       LED07_TMP = 0 ; 
       LED08_TMP = 0 ; 
       LED09_TMP = 0 ; 
       LED10_TMP = 0 ; 
       LED11_TMP = 0 ; 
       LED12_TMP = 0 ; 
       LED13_TMP = 0 ;
      }
 
      break;  
 
     case  1:     //显示状态1:数字钟  
      //显示钟摆
      i = ZB_LINE - 4 ;      //计算钟摆小球的起始行
      j = ZB_LINE + 4 ;     //计算钟摆小球的终止行
      if ( (DISP_LINE >= i ) && (DISP_LINE <= j ) )
      {
       i = DISP_LINE - i + 9*12;
       PORTB_TMP &= ~LED_TAB_A ;   //查表显示钟摆小球的当前列
       
       if ( DISP_LINE == ZB_LINE )   //钟摆线位置判断
       {
        LED06_TMP = 0 ; 
        LED07_TMP = 0 ; 
        LED08_TMP = 0 ; 
        LED09_TMP = 0 ; 
        LED10_TMP = 0 ; 
        LED11_TMP = 0 ; 
        LED12_TMP = 0 ; 
        LED13_TMP = 0 ;
       }
      }
    
      break;  
 
     case  2:     //显示状态2:温度计  
      //显示温度曲线
      i = 44 ;     //定位第0个X轴坐标点
      for ( j="0"; j      {
       if ( DISP_LINE == i )   //匹配X轴坐标点
       {
        LED07_TMP = 0 ;   //画X轴线
        i=TEMP_LS_QUEUE[j];  //载入当前坐标点对应的的温度值
        if ( i >= TEMP_LSPJ )   //当前历史纪录>=平均温度
        {
         i = i-TEMP_LSPJ;  //求差值
         //根据差值,显示不同的坐标
         switch( i )     
         {
          case  0:
           LED07_TMP = 0 ;
           break;
          case  1:
           LED08_TMP = 0 ;
           break;
          case  2:
           LED09_TMP = 0 ;
           break;
          case  3:
           LED10_TMP = 0 ;
           break;
          case  4:
           LED11_TMP = 0 ;
           break;
          default:
           LED12_TMP = 0 ;
           break;
         }
        }
        else     //当前历史纪录<平均温度
        {
         i = TEMP_LSPJ-i;  //求差值
         //根据差值,显示不同的坐标
         switch( i )     
         {
          case  0:
           LED07_TMP = 0 ;
           break;
          case  1:
           LED06_TMP = 0 ;
           break;
          case  2:
           LED05_TMP = 0 ;
           break;
          case  3:
           LED04_TMP = 0 ;
           break;
          case  4:
           LED03_TMP = 0 ;
           break;
          default:
           LED02_TMP = 0 ;
           break;
         }
        }
        break;  
       }
       i = i + 4 ;    //定位下一个X轴坐标点   
      }       
      break;  
 
     case  3:     //显示状态3:闹钟 
      //显示进度条
      if ( ( DISP_LINE > 65 ) && ( DISP_LINE <= ZB_LINE ) )
      {
       LED04_TMP = 0 ; 
      }


      if ( ( DISP_LINE > 65 ) && ( DISP_LINE < 115 ) )
      {
       LED03_TMP = 0 ; 
       LED05_TMP = 0 ; 
      }
      else if ( ( DISP_LINE == 65 ) || ( DISP_LINE == 115 ) )
      {
       LED03_TMP = 0 ; 
       LED04_TMP = 0 ; 
       LED05_TMP = 0 ; 
      }
      
      break;  
 
       default:
       
       break; 
     } 
   }
   
/*
   //设置状态
   else
   {
    //根据设置状态判断
    switch( SET_MODE )     
    {
     case  0:     //设置状态0:时钟"时"  
      break;  
     case  1:     //设置状态1:时钟"分"  
      break;  
     case  2:     //设置状态2:闹钟"时"  
      break;  
     case  3:     //设置状态3:闹钟"分"
      break;  
       case  4:     //设置状态4:闹铃时间
      break;  
        case  5:     //设置状态5:报时功能
      break;  
       default:
       break; 
    }
   }
*/
   
   //显缓区(字符串队列) 送显示
   if ( DISP_QUEUE_FLAG )      //显缓区(字符串队列)开启标志(0=未开启,1=开启)
   {
    i = 137 ;     //定位字符0起始位置
    for ( j="0"; j    {
     if ( (DISP_LINE >= i) && (DISP_LINE < (i+9) ))  //匹配字符位置
     {
      j = DISP_QUEUE[j] ;    //载入待显示字符
      i = DISP_LINE - i ;
      i = i + j * 8 ;
      i = i + j ;
      PORTB_TMP &= ~LED_TAB_A ;   //查表显示当前字符的当前列 PORTB_TMP &= ~LED_TAB_A[ DISP_LINE- i + 9*DISP_QUEUE[j]] ;
      break; 
     }
     i = i + 11 ;      //定位下一个字符位置
     if ( i>=180 ) i = i-180 ;
    }
   }


   //画外框
   LED00_TMP = 0 ;     
   //画内框
   LED13_TMP = 0 ;     


  }


  //========
  //送显
  //========
  PORTA = PORTA_TMP ; 
  PORTB = PORTB_TMP ;
  PORTC = PORTC_TMP ;


 }
   
 //================
 //INT中断
 //================
 if ( INTF && INTE )
 {
  INTF = 0 ;     //清除中断标志
  
  MOTOR_STOP_JSQ = 0 ;              //电机停转计时器=0


  if ( TIMR1_JSQ < 20 )
  {
   MOTOR_ST_FLAG = 0 ;   //电机状态标志=0(0=关闭,1=开启)
   SET_EN_FLAG = 0 ;   //设置使能标志=0(0=禁止,1=使能)
  }
  else
  {
   MOTOR_ST_FLAG = 1 ;   //电机状态标志=1(0=关闭,1=开启)


   //调整单列显示时间设置值(模糊控制)
   if ( TIMR1_JSQ > 180 )
   {
    if ( TIMR1_JSQ > 220 ) DISP_TIME_SET = DISP_TIME_SET - 8 ;
    else if ( TIMR1_JSQ > 200 ) DISP_TIME_SET = DISP_TIME_SET - 4 ;
    else if ( TIMR1_JSQ > 185 ) DISP_TIME_SET = DISP_TIME_SET - 2 ;
    else DISP_TIME_SET = DISP_TIME_SET - 1 ;


    if ( DISP_TIME_SET < 400 ) DISP_TIME_SET = 400 ;  //钳位
   }
   else if ( TIMR1_JSQ < 180 )
   {
    if ( TIMR1_JSQ < 140 ) DISP_TIME_SET = DISP_TIME_SET + 8 ;
    else if ( TIMR1_JSQ < 160 ) DISP_TIME_SET = DISP_TIME_SET + 4 ;
    else if ( TIMR1_JSQ < 175 ) DISP_TIME_SET = DISP_TIME_SET + 2 ;
    else DISP_TIME_SET = DISP_TIME_SET + 1 ;
 
    if ( DISP_TIME_SET > 65100 ) DISP_TIME_SET = 65100 ;  //钳位
   }
  }


  //计数器处理
  TIMR1_JSQ = 0 ;     //TIMR1溢出计数器 = 0
  DISP_LINE = DISP_LINE_ADJ ;   //显示列计数器(0~179)=校正值
 
 } 


 //================
 //TMR0中断
 //中断频率=Fosc/(指令周期*TMR0赋初值)=18M/(4*250)=18KHZ
 //中断周期=1/中断频率=55.556us
 //================
 if ( T0IF && T0IE )
 {
  T0IF = 0 ;     //清除中断标志
  TMR0 = TMR0 + (256-(250-2)) ;   //TMR0赋初值
  
  if ( ++TIME_US > 179 )     //"微秒"+1,结果>最大值?
  {
   TIME_US = 0 ;    //"微秒"=0
   T_10MS_FLAG = 1 ;   //10毫秒定时溢出标志=1
  }
 } 


 //================
 //串口接收中断
 //================
 if ( RCIF && RCIE )
 {
  //说明:RCIF由硬件决定是否清零,不必软件清除
  
  do      //循环处理,把硬件缓冲队列中接收到的数据都存入软件缓冲队列
  {
   if ( FERR )     //帧错误?
   {
    
    i = RCREG ;    //读取当前发生错误的接收结果,并丢弃
   }
   else
   {
    COMM_BUF[COMM_PUT_PTR] = RCREG ;   //读取当前接收结果,并存入接收缓冲队列
    if ( ++COMM_PUT_PTR >= COMM_BUF_NUM ) COMM_PUT_PTR=0 ; //接收数据存放指针+1,结果>=通讯缓冲区大小,则清零
    
    if ( OERR )     //溢出错误?
    {
     CREN = 0 ;
     CREN = 1 ;    //重新复位接收模块,令OERR标志清零
    }
   }
  }
  while ( RCIF ) ;    //RCIF=1时,说明把硬件缓冲队列中还有待处理的数据
 }
  



}
//--------------------------------------------------------
//
// THE END
//
// 版权所有:程序匠人(引用者请保留原作者姓名)
//
//--------------------------------------------------------


 

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
8
关闭 站长推荐上一条 /3 下一条