zoukankan      html  css  js  c++  java
  • OTP cpu Remote Controller

    /*-------------------------------------------
    Function name: main.c
    Designed By: Milo Lu
    Version:     2020-11-21 
                1. adapted,first functional draft.
    Description:
    1.  K1 project
    2.  SC8P1153A
    //                    SC8P1153A
    //                 ---------------
    // LEARN_S3-PA0-|               |-PA1
    //        LED,PB7-|               |-PA2
    //      ON_S1,PB6-|RST            |-PA3
    //            VCC-|               |-GND
    //            PB5-|               |-PB0-OFF_S2
    //            PB4-|               |-PB1-SDA
    //       DATA,PB3-|               |-PB2-SCL
    //                 ---------------
    -------------------------------------------*/
    
    
    #include <sc.h>                    //sc library,system search h file automatically.
    
    //----------- My Define -----------------
    #define     Button1_S1        PORTB6            // input
    #define        Button2_S2        PORTB0            // input
    #define     Button3_S3        PORTA0            // input
    
    #define        DIR_OUTPUT        0                //Output direction
    #define        DIR_INPUT        1                //Input direction
    #define        SDA_DIR            TRISB1            //DIR
    #define        SDA                PORTB1
    #define        SCL                PORTB2            // output
    
    #define        LED_4            PORTB7            // output
    #define        DATA_IN            PORTB3            // input
    #define        RELAY_CTL        PORTA2            // output
    
    
    //----------- My variable parameters -------
    unsigned int     Learn_Time_ms;
    unsigned char     SysTick;
    unsigned char     START_RX;
    unsigned char     RemoteID_Index;
    unsigned int     DATA_RECEIVED;
    unsigned char     CMD_VALUE;
    unsigned char     My_Led_Blink;
    unsigned char     My_Led_Delay;
    unsigned char     My_Mode;
    unsigned int     My_Remot0ID;
    unsigned int    My_Remot1ID;
    unsigned int    My_Remot2ID;
    //-------------- 24C02 --------------------
    void delay5us()
    {
        asm("nop");
        asm("nop");
        asm("nop");
        asm("nop");
        asm("nop");
        asm("nop");
    }
    
    void iic_start()//SDA falling when SCL is high
    {
        SDA_DIR = DIR_OUTPUT;
        SDA = 1;
        asm("nop");asm("nop");
        SCL = 1;
        delay5us();
        SDA = 0;
        delay5us();
        SCL = 0;
    }
    void iic_stop()//SDA rise when SCL is high
    {
        SDA_DIR = DIR_OUTPUT;
        SDA = 0;
        asm("nop");
        SCL = 1;
        delay5us();
        SDA = 1;
        delay5us();
        SCL = 0;
    }
    void iic_ack()
    {
        SCL = 0;
        asm("nop");asm("nop");asm("nop");
        SCL = 1;
        delay5us();
        SCL = 0;
        asm("nop");asm("nop");
    }
    void iic_NoAck()
    {
        SDA_DIR = DIR_OUTPUT;
        SDA = 1;
        asm("nop");asm("nop");asm("nop");
        SCL = 1;
        delay5us();
        SCL = 0;
        asm("nop");asm("nop");
    }
    void iic_write_byte(unsigned char u8_value)
    {
        unsigned char i;
        SDA_DIR = DIR_OUTPUT;
        for(i=0;i<8;i++)
        {
            SCL = 0;
            delay5us();
            if(u8_value&0x80) SDA = 1;
            else SDA = 0;
            delay5us();
            SCL = 1;
            delay5us();
            u8_value<<=1;
        }
        SCL = 0;
        delay5us();
        SDA = 1;
    }
    unsigned char iic_read_byte()
    {
        unsigned char i,ret_val=0;
        SDA_DIR = DIR_INPUT;
        SDA = 1;
        for(i=0;i<8;i++)
        {
            SCL = 0;
            delay5us();
            SCL = 1;
            delay5us();
            ret_val<<=1;
            if(SDA)
                ret_val |= 1;
        }
        return ret_val;
    }
    void iic_write_byte_to_addr(unsigned char addr,unsigned char val)
    {
        iic_start();
        iic_write_byte(0xa0);
        iic_ack();
        iic_write_byte(addr);
        iic_ack();
        iic_write_byte(val);
        iic_ack();
        iic_stop();
    }
    unsigned char iic_read_byte_from_addr(unsigned char addr)
    {
        unsigned char ret_val;
        iic_start();
        iic_write_byte(0xa0);
        iic_ack();
        iic_write_byte(addr);
        iic_ack();
        iic_start();
        iic_write_byte(0xa1);
        iic_ack();
        ret_val = iic_read_byte();
        SCL = 0;
        iic_NoAck();
        iic_stop();
        return ret_val;
    }
    
    /*******************************************
    ** Main Function
    ********************************************/
    void main(void)
    {
        //------------ My static variable ---------
        static unsigned char Btn1_Debouncing,Btn2_Debouncing;//,Btn3_Debouncing;
        //------------- variable -----------
        unsigned char tmp,j;
        unsigned int i;
        
        //---------- System Start ----------
        asm("nop");
        asm("clrwdt");
        
        //-------- System Init -------------
        OPTION_REG =0;                    //Fdev for TMR0  
        OSCCON = 0XF1;                    //8M
        
        //---------- PORTA PORTB Init -------------
        // pull-up and pull-down resistor
        // Bit7~Bit4--pull up resistor;Bit3~Bit0--pull down resistor;0=disable;1=enable
        UPDOWNA = 0B00010100;    //PA0 pull-up,PA2 pull-down registor enable
        // Bit7~Bit0--pull-up registor. enable;1=enable;0=disable.
        WPUB    = 0B01001001;    //PB6,PB3,PB0 pull-up registor enable
        // Bit7~Bit0--pull-down registor enable;1=enable;0=disable.
        PDCONB    = 0b00000000;    //PB disable all pull-down registor
        // Bit7~Bit0--output open enable;1=enable;0=disable
        ODCONB     = 0B10000000;    //PB7 enable
        //IO input output direction option--0=Output;1=Input
        TRISA     = 0B00000001;    //PA0=Input;Others=Output
        TRISB    = 0B01111001;    //PB1=Output,Others=Input
        SDA = 0;                //PB1 = 0
        RELAY_CTL = 0;
        My_Mode = 0;            //Normal mode
        
        //------------- Read 24C02 ----------
        //iic_write_byte_to_addr(j,tmp++);        //test
        RemoteID_Index = iic_read_byte_from_addr(0xFB);
        if(RemoteID_Index > 14)RemoteID_Index = 0;
        DATA_RECEIVED = 0;
        My_Remot0ID = iic_read_byte_from_addr(0);
        My_Remot0ID<<=8;
        My_Remot0ID |=iic_read_byte_from_addr(1);
        
        My_Remot1ID = iic_read_byte_from_addr(2);
        My_Remot1ID<<=8;
        My_Remot1ID |=iic_read_byte_from_addr(3);
        
        My_Remot2ID = iic_read_byte_from_addr(4);
        My_Remot2ID<<=8;
        My_Remot2ID |=iic_read_byte_from_addr(5);
        
        //------------- TIMER0 --------------
        TMR0 = 0;                // CNT++ = 1us
        OPTION_REG = 0x00;        // Focs/4
        TMR0PRD = 50;            // Load default value interrupt trigger per 50us
        
        //----------- Interrupt ------------------
        INTCON     = 0x00;            //Disable Gobal interrupt
        IOCB    = 0B00001000;    // Enable level PB3 change interrupt
        OSCCON |= 0X01;            //TIMER0 Start...
        INTCON  = 0xA8;            //TIMER0 Interrupt enable,PORTB Level changed interrupt enable
        while(1)
        {
            asm("clrwdt");
            
            //--------- Button1--Connect Key Press down -----------
            if(!Button1_S1)
            {
                if(Btn1_Debouncing < 200) Btn1_Debouncing++;
                else if(Btn1_Debouncing == 200)
                {
                    if(!Button1_S1)
                    {
                        RELAY_CTL = 1;
                        Btn1_Debouncing++;
                    }
                }
            }
            else if(Btn1_Debouncing != 0) Btn1_Debouncing =0;
            
            //------------ Button2--Disconnect Key Press down ------------
            if(!Button2_S2)
            {
                if(Btn2_Debouncing < 200) Btn2_Debouncing++;
                else if(Btn2_Debouncing == 200)
                {
                    if(!Button2_S2)
                    {
                        RELAY_CTL = 0;
                        Btn2_Debouncing++;
                    }
                }
            }
            else if(Btn2_Debouncing != 0) Btn2_Debouncing =0;
            
            //------------ Button3--Learn Key Press down -------------
            switch(My_Mode)
            {
                case 0:
                {
                    if(!Button3_S3)
                    {
                        Learn_Time_ms = 20;
                        My_Mode =1;                    //key down event trigger
                    }
                    break;
                }
                case 1:
                {
                    if(!Button3_S3)
                    {
                        if(Learn_Time_ms==0)        //debouncing time out
                        {
                            Learn_Time_ms=9000;        //9 second to confirn a long key press down
                            My_Mode =2;                //key down evnet confirn
                        }
                    }
                    else 
                    {
                        My_Mode = 0;                //invaid key
                    }
                    break;
                }
                case 2:                                //wait for key release
                {
                    if(!Button3_S3)                    //key continue press down
                    {
                        if(Learn_Time_ms==0)        //key press down for more than 9 seconds,reset remote ID
                        {
                            GIE = 0;                //disable interrupt
                            Learn_Time_ms = 0;
                            RemoteID_Index = 0;
                            
                            My_Remot0ID = 0;
                            My_Remot1ID = 0;
                            My_Remot2ID = 0;
                            iic_write_byte_to_addr(0xFB,RemoteID_Index);
                            for(i=0;i<200;i++)delay5us();
                            asm("clrwdt");
                            for(tmp=0;tmp<16;tmp++)
                            {
                                iic_write_byte_to_addr(tmp,0x00);
                                for(i=0;i<200;i++)delay5us();        //a delay should be add.
                                asm("clrwdt");
                            }
                            My_Led_Blink = 6;        //led blinks
                            My_Mode = 3;            //wait for key release
                            GIE = 1;                //interrupt enable
                        }
                    }
                    else if(Learn_Time_ms > 7000)    //key release within 3 second
                    {
                        My_Mode = 4;                //Learn Mode
                        My_Led_Blink = 6;            //Led blinks
                        Learn_Time_ms = 20000;        //Learn time:20 seconds.
                    }
                    break;
                }
                case 3:
                {
                    if(Button3_S3)                    //key release event trigger
                    {
                        for(i=0;i<200;i++)delay5us();    //delay block CPU.
                        if(Button3_S3)                //key release event confirn
                        {
                            My_Mode = 0;            //normal mode
                        }
                    }
                    break;
                }
                case 4:
                {
                    if(Learn_Time_ms==0)            //time out, exit learn mode
                    {
                        My_Mode = 0;                //normal mode
                    }
                    break;
                }
                default:
                {
                    My_Mode = 0;
                    break;
                }
            }
            /*if(!Button3_S3)
            {
                if(Btn3_Debouncing < 200) Btn3_Debouncing++;
                else if(My_Mode==0)
                {
                    if(!Button3_S3)
                    {
                        Learn_Time_ms = 9000;
                        My_Mode = 1;
                    }
                }
                else if(My_Mode==1)                    //continue press down for more than 9 seconds
                {
                    if(Learn_Time_ms==0)
                    {
                        GIE = 0;
                        Learn_Time_ms = 0;
                        RemoteID_Index = 0;
                        
                        My_Remot0ID = 0;
                        My_Remot1ID = 0;
                        My_Remot2ID = 0;
                        iic_write_byte_to_addr(0xFB,RemoteID_Index);
                        for(i=0;i<200;i++)delay5us();
                        asm("clrwdt");
                        for(tmp=0;tmp<16;tmp++)
                        {
                            iic_write_byte_to_addr(tmp,0x00);
                            for(i=0;i<200;i++)delay5us();
                            asm("clrwdt");
                        }
                        My_Led_Blink = 6;
                        My_Mode = 2;                //avoid to reset again
                        GIE = 1;
                    }
                }
            }
            else if(Btn3_Debouncing != 0) 
            {
                if((My_Mode == 1)&&(Learn_Time_ms >= 7000))
                {
                    My_Led_Blink = 3;
                    Learn_Time_ms = 20000;
                    My_Mode = 3;
                }
                else if(My_Mode!=0)
                {
                    My_Mode=0;
                }
                Btn3_Debouncing =0;
            }
            */
            
            //---------------- Paraser ------------------
            if(DATA_RECEIVED!=0)
            {
                GIE = 0;
                if(My_Mode==4)                        //learn mode
                {
                    switch(RemoteID_Index)
                    {
                        case 0:
                            {
                                My_Remot0ID = DATA_RECEIVED;
                                break;
                            }
                        case 2:
                            {
                                My_Remot1ID = DATA_RECEIVED;
                                break;
                            }
                        case 4:
                            {
                                My_Remot2ID = DATA_RECEIVED;
                                break;
                            }
                        default:
                            {
                                break;
                            }
                    }
                    tmp = (DATA_RECEIVED>>8);                //High byte first
                    iic_write_byte_to_addr(RemoteID_Index,tmp);
                    for(i=0;i<200;i++)delay5us();
                    asm("clrwdt");
                    tmp = DATA_RECEIVED&0x00FF;                //Low byte second
                    RemoteID_Index ++;
                    iic_write_byte_to_addr(RemoteID_Index,tmp);
                    for(i=0;i<200;i++)delay5us();
                    asm("clrwdt");
                    RemoteID_Index ++;
                    if(RemoteID_Index >= 16)                //Remote Number Max 8,save
                        RemoteID_Index = 0;
                    iic_write_byte_to_addr(0xFB,RemoteID_Index);
                    for(i=0;i<200;i++)delay5us();
                    asm("clrwdt");
                    My_Led_Blink = 6;
                    Learn_Time_ms = 0;                        //Exit learn mode
                }
                else                                        //CMD from Remote
                {
                    //it is faster to get id from RAM than ROM.
                    if(DATA_RECEIVED == My_Remot0ID || DATA_RECEIVED == My_Remot1ID || DATA_RECEIVED == My_Remot2ID )
                    {
                        tmp = 0;
                    }
                    else 
                    {
                        for(tmp=0,j=0;tmp<16;tmp++)
                        {
                            i=iic_read_byte_from_addr(j);
                            i<<=8;
                            j++;
                            i|=iic_read_byte_from_addr(j);
                            asm("clrwdt");
                            j++;
                            if(DATA_RECEIVED == i)
                            {
                                tmp = 0;
                                break;
                            }
                        }
                    }
                    if(!tmp )    //id active
                    {
                        My_Led_Blink = 1;
                        switch (CMD_VALUE)
                        {
                            case 1:
                            {
                                break;
                            }
                            case 2:                                //For PGST Remote, this cmd is arm
                            {
                                RELAY_CTL = 0;
                                break;
                            }
                            case 4:                                //For PGST Remote, this cmd is Disarm
                            {
                                break;
                            }
                            case 8:                                //For PGST Remote,this cmd is Home Arm
                            {
                                RELAY_CTL = 1;
                                break;
                            }
                            default:
                            {
                                break;
                            }
                        }
                    }
                }
                GIE = 1;
                DATA_RECEIVED = 0;
            }
        }
    }
    
    /*******************************************
    **     Timer0 interrupt
    **    Timer=200us
    **     PB0 interrupt
    **    RF data received
    ********************************************/
    void interrupt Isr_Routine()
    {
        static unsigned int id,tmp;
        static unsigned char bits_of_byte,TAR_50us;
        static unsigned long one_byte;
        unsigned char IO_State;
        if(T0IF)                        //TIMER0 Interrupt
        {
            T0IF = 0;
            if(SysTick++ >= 20)        // 20*50us = 1ms
            {
                if(Learn_Time_ms != 0)
                {
                    Learn_Time_ms--;
                }
                if(My_Led_Blink != 0)
                {
                    if(My_Led_Delay++ < 100) 
                        LED_4 = 1;
                    else if(My_Led_Delay < 200) 
                        LED_4 = 0;
                    else 
                    {
                        My_Led_Delay = 0;
                        My_Led_Blink--;
                    }
                }
                SysTick = 0;
            }
            TAR_50us++;
        }
        if(PBIF)                        //PORTB Interrupt
        {
            PBIF = 0;
            
            //----------------------------------------------------------------------------
            //            RF Data Format:NRZ Encoder
            //            1B = 400usH+1000usL; 0B = 1000usH+400usL; T = 1500us
            //            Bootstrap: 1ms H + 400us L
            //            5bytes = 2bytesID + 1ByteData + 2bytesReserver(FFFFH)
            //            Data:F7H, F5H, FFH, FDH
            //            Down Midle  Up  Learn
            //            ASM Modulation
            //----------------------------------------------------------------------------
            IO_State = (unsigned char)DATA_IN;
            if(IO_State)                // Low to high transition
            {
                // Low state time is upper than 1.5ms,OR Paraser busy, data crash, retry again
                if((TAR_50us >= 30)||(DATA_RECEIVED!=0))            
                {
                    START_RX = 0;
                }
                TAR_50us = 0;
            }
            else                        // High to low transition
            {
                if(!START_RX)                                         // The first header doesn't receive
                {
                    if((TAR_50us > 14)&&(TAR_50us < 30))             // 1.5ms > T > 0.7ms
                    {
                        one_byte = 1;
                        bits_of_byte = 1;
                        START_RX = 1;
                    }
                }
                else                                                  // The second header received,
                {                                                   // start to get RF data
                    if((TAR_50us >4)&&(TAR_50us< 12))                //0 600us > T > 200us
                    {
                        one_byte <<=1;
                        bits_of_byte++;
                    }
                    else if((TAR_50us > 14)&&(TAR_50us < 30))         // 1.5ms > T > 0.7ms
                    {
                        one_byte<<=1;
                        one_byte+=1;
                        bits_of_byte++;
                    }
                    else
                    {
                        START_RX = 0x00;                            // data crash, retry again
                    }
                    if(bits_of_byte >= 24)                             // got one byte, got id
                    {
                        CMD_VALUE = (one_byte&0x0F);                //lowest 4 bits are command
                        one_byte>>=4;
                        tmp = one_byte;
                        if(id != tmp)
                        {
                            id = tmp;                                //got new id 
                        }
                        else                                        //at least 2 times get the same id
                        {
                            DATA_RECEIVED = id;                        //load RF data
                        }
                        START_RX = 0x00;                            // Receiving repeat
                        one_byte = 0;
                        bits_of_byte = 0;
                    }
                }
                TAR_50us = 0;
            }
        }
    }

    IIC bus using by OTP cpu example.

    Enjoy.

  • 相关阅读:
    二、静、动态代理(9~10)~~~~
    luogu P3572 [POI2014]PTA-Little Bird 单调队列优化dp
    luogu P6113 【模板】一般图最大匹配 带花树
    Codeforces Round #646 (Div. 2) C——Game On Leaves 思维
    Codeforces Round #646 (Div. 2) E——Tree Shuffling 思维
    luogu P2979 [USACO10JAN]Cheese Towers S 变形dp背包
    luogu P6577 【模板】二分图最大权完美匹配
    Educational Codeforces Round 88 (Rated for Div. 2) D
    Codeforces Round #645 (Div. 2) E
    Codeforces Round #645 (Div. 2) D
  • 原文地址:https://www.cnblogs.com/lumao1122-Milolu/p/14031908.html
Copyright © 2011-2022 走看看