#include #include #include #define LCD_DEFAULT #include #pragma config FOSC = HS #pragma config WDT = OFF #pragma config LVP = OFF #pragma config PBADEN = OFF //OSC = HS Impostato per lavorare ad alta frequenza //WDT = OFF Disabilito il watchdog timer //LVP = OFF Disabilito programmazione LVP //PBADEN = OFF Disabilito gli ingressi analogici unsigned int input_data; char logic_interval, logic_change, bit_count; char old_invert = 0; char invert_bit = 0; enum { Idle, Start_bit, Capture_bit }; char Current_state = Idle; char got_data = 0; char Command_code, Address_code, Control_bit; //************************************************************ // Dichiarazione Prototipi di funzione //************************************************************ // Prototipo di funzione per bassa priorita' void Low_Int_Event (void); // Prototipo di funzione per alta priorita' void High_Int_Event (void); //************************************************************ // Impostazione e Gestione priorita' alta //************************************************************ #pragma code high_vector = 0x08 void high_interrupt (void) { // Salto per la gestione dell'interrupt ad alta priorita' _asm GOTO High_Int_Event _endasm } #pragma code #pragma interrupt High_Int_Event // Funzione per la gestione dell'interruzione ad alta priorita' void High_Int_Event (void) { // Indice per il ciclo di pausa int i=0; if(INTCONbits.INT0IF){ //****************************************************************************** // RB0 changed, toggle interrupt edge bit and increase logic_change for detect // fault signal purpose // If it's a first edge detected, initialize data and turn on timer2 //****************************************************************************** INTCON2bits.INTEDG0 = ~INTCON2bits.INTEDG0; //toggle edge logic_change++ ; if (Current_state == Idle){ logic_interval = 0; logic_change = 0; Delay1KTCYx(1); TMR2 = 0; PIR1bits.TMR2IF = 0; //clear interrupt flag T2CONbits.TMR2ON = 1; //timer2 is on Current_state = Start_bit; } INTCONbits.INT0IF = 0; //clear interrupt flag. } //********* End RB0 interrupt routine ***************************************** if(PIR1bits.TMR2IF){ // LATDbits.LATD6=~LATDbits.LATD6; logic_interval++; switch (Current_state){ //****************************************************************************** // Check for (second) start bit, Logic on RB0 must change in 890us or considers // as a fault signal. //****************************************************************************** case Start_bit: if((logic_interval == 1)&& (logic_change == 1)){ logic_interval = 0; logic_change = 0; bit_count = 0; input_data = 0; Current_state = Capture_bit; //move on to capturing state }else { Current_state = Idle; T2CONbits.TMR2ON = 0; //timer2 is off INTCON2bits.INTEDG0 = 0; //interrupt on falling edge. } break; case Capture_bit: //****************************************************************************** // Capturing state. Sampling RB0 logic every 1780 us (logic_interval = 2). // Data is valid if logic on RB0 was change. // Data is store in Command_code and Address_code //****************************************************************************** if(logic_interval == 2){ if(logic_change <= 2){ logic_interval = 0; logic_change = 0; if(bit_count < 12){ bit_count++; input_data = input_data << 1; if(PORTBbits.RB0 == 1) { input_data = input_data | 1; } } else { Command_code = input_data & 0x3F; input_data = input_data >> 6; Address_code = input_data & 0x1F; input_data = input_data >> 5; Control_bit = input_data & 0x01; if(old_invert != input_data) { invert_bit = 1; old_invert = input_data; }else invert_bit = 0; got_data = 1; Current_state = Idle; T2CONbits.TMR2ON = 0; //timer2 is off INTCON2bits.INTEDG0 = 0; //interrupt on falling edge. } }else { Current_state = Idle; T2CONbits.TMR2ON = 0; //timer2 is off INTCON2bits.INTEDG0 = 0; //interrupt on falling edge. } } break; default: Current_state = Idle; INTCON2bits.INTEDG0 = 0; //interrupt on falling edge. } PIR1bits.TMR2IF = 0; //clear interrupt flag } // Controllo che l'interrupt sia stato generato da PORTB if (INTCONbits.RBIF == 1 ) { //pausa filtraggio spike for (i=0; i<10000; i++){ } // Controllo la pressione di RB4 if (PORTBbits.RB4 == 0) { // Accendo il LED 1 LATDbits.LATD1 = ~LATDbits.LATD1; } // Resetto il flag d'interrupt per permettere nuove interruzioni INTCONbits.RBIF = 0; } } //************************************************************ // Impostazione e Gestione priorita' bassa //************************************************************ #pragma code low_vector = 0x18 void low_interrupt (void) { // Salto per la gestione dell'interrupt a bassa priorita' _asm GOTO Low_Int_Event _endasm } #pragma code #pragma interruptlow Low_Int_Event // Funzione per la gestione dell'interruzione ad alta priorita' void Low_Int_Event (void) { // Controllo che l'interrupt sia stato generato da Timer0 if (INTCONbits.TMR0IF == 1 ) { // Inverto lo stato del LED 0 LATDbits.LATD0 = ~LATDbits.LATD0; // Resetto il flag d'interrupt per permettere nuove interruzioni INTCONbits.TMR0IF = 0; } } //************************************************************ // Inizio programma principale //************************************************************ void main (void){ // Variabile usata per creare un conteggio fittizio di pausa unsigned int i; // Imposto PORTA tutti ingressi LATA = 0x00; TRISA = 0xFF; // Imposto PORTB tutti ingressi LATB = 0x00; TRISB = 0xFF; // Imposto PORTC tutti ingressi LATC = 0x00; TRISC = 0xFF; // Imposto PORTD tutte uscite LATD = 0x00; TRISD = 0x00; // Imposto PORTE tutti ingressi LATE = 0x00; TRISE = 0xFF; //Inizializzo il display LCD con quarzo a 20MHz OpenLCD (20); BacklightLCD (TURN_ON); WriteStringLCD ("Ciao"); ShiftLCD (RIGHT,6); Line2LCD (); // RB0 interrupt set up //****************************************************************************** INTCONbits.INT0IE = 1; //enable RB0 interrupt. INTCON2bits.INTEDG0 = 0; //interrupt on falling edge. // ADCON1 = 0x0F; //all digital I/O //****************************************************************************** // Timer2 interrupt set up, interrupt every 890us //****************************************************************************** T2CON = 0b00111001; //postscal 1:5, timer off, prescaler 1:4 PR2 = 139; //preload timer2 comparator value TMR2 = 0; //reset value timer2 PIR1bits.TMR2IF = 0; //clear interrupt flag. PIE1bits.TMR2IE = 1; //enable timer2 interrupt. IPR1bits.TMR2IP = 1; //timer2 interrupt high priority //****************************************************************************** //************************************************************ // Abilito i pulsanti per le interruzioni ad alta priorita' //************************************************************ // Abilita i resistori di pull-up sulla PORTB EnablePullups(); // Abilito le interruzioni su PORTB INTCONbits.RBIE = 1; // Abilito le interruzioni su PORTB come alta priorita' INTCON2bits.RBIP = 1; //************************************************************ // Abilito il Timer0 per funzionare a bassa priorita' //************************************************************ // Modalita' a 16 bit T0CONbits.T08BIT = 0; // Clock interno T0CONbits.T0CS = 0; // Abilito Prescaler T0CONbits.PSA = 0; // Prescaler 32 T0CONbits.T0PS0 = 0; T0CONbits.T0PS1 = 0; T0CONbits.T0PS2 = 1; // Abilito le interruzioni del Timer0 INTCONbits.TMR0IE = 1; // Abilito le interruzioni del Timer0 come bassa priorita' INTCON2bits.TMR0IP = 0; // Abilito il Timer0 T0CONbits.TMR0ON = 1; //************************************************************ // Abilito le interruzioni //************************************************************ // Abilito modalita' interruzione a due livelli alta e bassa RCONbits.IPEN = 1; // Abilito gli interrupt ad alta priorita' INTCONbits.GIEH = 1; // Abilito gli interrupt a bassa priorita' INTCONbits.GIEL = 1 ; // Ciclo infinito while (1){ if(got_data){ got_data = 0; ClearLCD(); WriteStringLCD("Ctrl="); WriteIntLCD(Control_bit,0); Line2LCD (); WriteStringLCD("Add="); WriteIntLCD(Address_code,0); WriteStringLCD(";Com="); WriteIntLCD(Command_code,0); } } }