⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ir.c

📁 This is IR (Infra-Red) learn module for home automation system. It can learn IR codes from different
💻 C
字号:
/*
 *  FILE:
 *     ir.c (rev. 1.0 - 21.04.2006)
 *
 *  PROJECT:
 *     IR Learn System 
 *  
 *  DESCRIPTION:
 *     See "ir.h" for description
 *     
*/


#include "AT89C51ED2.h"
#include "types.h"
#include "ir.h"
#include "eeprom.h"

#define TMR2_Restart    TR2=0; TF2=0; TL2=IR_TMR_Lo; TH2=IR_TMR_Hi; TR2=1;

volatile BOOL IR_StartCatch;     // Start IR catch flag
volatile U8   IR_CodeLen;        // Length of captured sequence (bits)
volatile U8   IR_KeyLen;         // Length of key sequence
volatile U8   IR_KeyPtr;         // Pointer to current key
xdata U8 IR_CodeSeq[8];          // Captured code
xdata U8 IR_tmpSeq[8];           // Captured code (temporary version)
xdata U8 IR_MaskSeq[8];          // Captured code mask
xdata U8 IR_KeySeq[16];          // Keyboard sequence

U16 IR_len0;                     // Length of last 0 pulse of IR receiver
U16 IR_len1;                     // Length of last 1 pulse of IR receiver
U16 IR_tmp;                      // Length of current 0 pulse of IR receiver

// Initialize IR data and EXT0 interrupt
void IR_Init(void) {
    IR_StartCatch=0;
    IR_CodeLen=0; IR_KeyLen=0; IR_KeyPtr=0;
    IR_len0=0; IR_len1=0;
    EA=0;                   // Disable system interrupts
    IT0=1;                  // Edge-triggered interrupt
    IPH0|=1; IPL0|=1;       // Set highest priority for INT0 interrupt
    T2CON=0; T2MOD=0;       // Initialize Timer 2
    EA=1; EX0=1;            // Enable INT0 interrupt
}

// TMR2 Interrupt Routine
void TMR2_Interrupt(void) interrupt 5 using 3 {
    TR2=0; TF2=0; ET2=0;
    IR_StartCatch=0;
    // Accept only codes with at least 10 transitions
    if (IR_CodeLen<10) {IR_CodeLen=0; return;}
}

// External INT0 Interrupt Routine
void IR_Interrupt(void) interrupt 0 using 3 {
    if (IR_StartCatch==0) return;   
    TR2=0;
    IR_tmp=TH2; IR_tmp<<=8; IR_tmp+=TL2;
    TMR2_Restart
    EA=0; 
    if (TF2) {TF2=0; IR_StartCatch=0; IR_CodeLen=0; EA=1; return;}
    IR_tmp-=IR_TMR_Val;
    if (IR_CodeLen==0) {
        IR_len0=0; IR_len1=0;
        for (IR_tmp=0;IR_tmp<8;IR_tmp++) IR_CodeSeq[IR_tmp]=0;
    }
    else {
        if (IR_tmp<IR_len1) IR_len1-=IR_tmp;
        else IR_len1=IR_tmp-IR_len1;
        // Check difference (accuracy: 25%)
        if ((IR_tmp>>2)>IR_len1) IR_CodeSeq[IR_CodeLen>>3]|=(0x80>>(IR_CodeLen&7));
        IR_len1=IR_tmp; IR_CodeLen++;
    }
    while (TF2==0) {
        P3_2=1;
        if (P3_2==1) break;
    }
    TR2=0; 
    // if low pulse is too long (>20 msec)
    if (TF2) {TF2=0; IR_StartCatch=0; IR_CodeLen=0; EA=1; return;}
    // if 64 pulses were catched
    if (IR_CodeLen>=64) {IR_StartCatch=0; EA=1; return;}
    IR_tmp=TH2; IR_tmp<<=8; IR_tmp+=TL2;
    IR_tmp-=IR_TMR_Val;
    if (IR_tmp<IR_len0) IR_len0-=IR_tmp;
    else IR_len0=IR_tmp-IR_len0;
    // Check difference (accuracy: 25%)
    if ((IR_tmp>>2)>IR_len0) IR_CodeSeq[IR_CodeLen>>3]|=(0x80>>(IR_CodeLen&7));
    IR_len0=IR_tmp; IR_CodeLen++;
    TMR2_Restart
    EA=1; ET2=1;
}

// Right-click Menu->IR Assign
void IR_Assign() {
    U8 i,j;
    MENU_pFunc=NULL;
    MENU_pMenuBack=NULL;
    i=GetDigit(1);  // Get IR sequence number
    if (i==0xFF) return;
    if (GetIRseq()==0xFF) return;
    for (j=0;j<16;j++) {
        EEPROM_Write(MAP_IR_Seq+i*16+j,buf[j]);
        if (buf[j]==0) break;
    }
}

// Right-click Menu->IR Learn
void IR_Learn() {
    U8 i,j,k;
    MENU_pFunc=NULL;
    MENU_pMenuBack=NULL;
    i=GetDigit(1);  // Get IR sequence number
    if (i==0xFF) return;
    for (j=0;j<8;j++) {
        IR_CodeSeq[j]=0; 
        IR_MaskSeq[j]=0;
    }
    IR_CodeLen=0;
    for (j=0;j<5;) {
        if (GetIRcode(j)==0xFF) return;
        if (IR_CodeLen!=0) {
            LED_Msg_Blink();
            if (j!=0)
                for (k=0;k<8;k++) IR_MaskSeq[k]|=(IR_CodeSeq[k]^IR_tmpSeq[k]);
            for (k=0;k<8;k++) IR_tmpSeq[k]=IR_CodeSeq[k];            
            j++;
        }
        TMR_Delay(10000);
    }
    // Calculate number of mask bit
    k=0;
    for (j=0;j<IR_CodeLen;j++) {
        if (IR_MaskSeq[j>>3]&(0x80>>(j&7))) k++;
    }
    // if less than 25%
    if (k<(IR_CodeLen>>2)) {
        EEPROM_Write(MAP_IR_Cmd+i*18,IR_CodeLen);        
        for (j=1;j<9;j++) {
            EEPROM_Write(MAP_IR_Cmd+i*18+j,IR_CodeSeq[j-1]);
            EEPROM_Write(MAP_IR_Cmd+i*18+9+j,~IR_MaskSeq[j-1]);
        }
        print(MSG_IRLearned[MENU_Lang]);
    }
    else print(MSG_IRProblem[MENU_Lang]);
    IR_CodeLen=0;
    TMP_Timer=20000;   
    i=0;
    while(i==0 && TMP_Timer) i=getkey();
}

// Check current captured IR code with learned codes
void IR_Check() {
    U8 i,j,k;
    if (IR_CodeLen<10) {
        IR_CodeLen=0;
        IR_StartCatch=1;
        return;
    }
    for (i=0;i<10;i++) {
        j=EEPROM_Read(MAP_IR_Cmd+i*18);
        if (j!=IR_CodeLen) continue;
        for (j=0;j<8;j++) {
            k=EEPROM_Read(MAP_IR_Cmd+i*18+10+j);
            if ((IR_CodeSeq[j]&k)!=(EEPROM_Read(MAP_IR_Cmd+i*18+j+1)&k)) break;
        }
        if (j==8) break;
    }
    if (i==10) {
        IR_CodeLen=0;
        LED_Arm_Blink();
        IR_StartCatch=1;
        return;
    }
    IR_CodeLen=0;
    LED_Msg_Blink();
    // load key sequence 
    for (j=0;j<16;j++) {
        k=EEPROM_Read(MAP_IR_Seq+i*16+j);
        IR_KeySeq[j]=k;
        if (k==0) break;
        if (k==0xFF) {
            IR_KeySeq[j]=0;
            break;
        }
    }
    IR_KeyLen=j; IR_KeyPtr=0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -