#include #include #include #include #include "PCF8574.h" #define LCD_DEFAULT #include #pragma config OSC = 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, data; //unsigned char PCF8574_000 = 0b00000000; unsigned char button1 = 0b11111111; unsigned char button2 = 0b11111111; unsigned char button, button_ctrl; unsigned char input_data_H = 0b00000000; unsigned char input_data_L = 0b00000000; unsigned char light1 = 0b00000000; unsigned char light2 = 0b00000000; unsigned char light1_bak, light2_bak; unsigned char mask1 = 0b00000000; unsigned char mask2 = 0b00000000; unsigned int mask; unsigned char datafree = 0b00000000; 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 got_switch = 0; char Command_code, Address_code, Control_bit, Control_bit_bak; unsigned int switch_data = 0; //************************************************************ // 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) { 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.INTEDG2 = 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; input_data_L = input_data; input_data = input_data >> 8; input_data_H = input_data & 0b00001111; Control_bit = input_data_H & 0b00001000; Control_bit = Control_bit >> 3; data = input_data_H & 0b00000111; data = data << 8; data = data + input_data_L; 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 } } //************************************************************ //************************************************************ // 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 //************************************************************ // Inizio gestione interrupt a bassa prioritą //************************************************************ void Low_Int_Event (void) { //************************************************************ // Inizio gestione interrupt da PCF8574 0x40 e 0x42 (RB1) //************************************************************ // RB1 interrupt dei PCF8574 if(INTCON3bits.INT1IF){ INTCON3bits.INT1IE = 0; //disable RB1 interrupt. //pausa filtraggio spike 50ms Delay1KTCYx(250); //lettura dello stato dei pulsanti PCF8574_read_data (0x40, &button1); PCF8574_read_data (0x42, &button2); //caso pressione di almeno un pulsante if (button1 < 255 || button2 < 255) { got_switch = 1; switch_data = button2; switch_data = switch_data << 8; switch_data = switch_data + button1; button_ctrl = switch_data & 0x01; button = 1; //determino il numero del pulsante premuto //(il minore in caso di pressione di pił pulsanti) while (button_ctrl){ button = button + 1; switch_data = switch_data >> 1; button_ctrl = switch_data & 0x01; } } PCF8574_read_data (0x40, &datafree);//con la lettura rilascio l'interruzione PCF8574_read_data (0x42, &datafree);//con la lettura rilascio l'interruzione INTCON3bits.INT1IE = 1; //enable RB1 interrupt. // Resetto il flag d'interrupt per permettere nuove interruzioni INTCON3bits.INT1IF = 0; } //************************************************************ // Inizio gestione interrupt da PORTB //************************************************************ // Controllo che l'interrupt sia stato generato da PORTB if (INTCONbits.RBIF == 1 ) { //pausa filtraggio spike 50ms Delay1KTCYx(250); //************************************************************ // Inizio gestione interrupt da RB4 //************************************************************ // 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; } //************************************************************ // Inizio gestione interrupt da Timer0 //************************************************************ // 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; } } void main (void){ // Variabile usata per creare un conteggio fittizio di pausa unsigned int i; //Imposto PORTA tutti ingressi LATA = 0x00; TRISA = 0b11111111; //Imposto PORTB tutti ingressi LATB = 0x00; TRISB = 0b11111111; //Imposto PORTC tutti ingressie RC1 come uscita per retroilluminazione LCD LATC = 0b00000000; TRISC = 0b11111101; //Imposto PORTD tutte uscite LATD = 0b00000000; TRISD= 0b00000000; CMCONbits.CM2 = 1; CMCONbits.CM1 = 1; CMCONbits.CM0 = 1; //Imposto PORTE 7 tutte uscite LATE = 0x00; TRISE = 0b00000000; //Inizializza il modulo I2C 1a 100KHz @20MHz OpenI2C(MASTER, SLEW_OFF); SSPADD = 49; //Inizializzo il display LCD con quarzo a 20MHz OpenLCD (20); BacklightLCD (TURN_OFF); WriteStringLCD ("Ciao"); ShiftLCD (RIGHT,6); Line2LCD (); //****************************************************************************** // RB0 interrupt set up //****************************************************************************** INTCONbits.INT0IE = 1; //enable RB0 interrupt. //INTCON3bits.INT2IP = 1; //High priority RB2 interrupt INTCON2bits.INTEDG0 = 0; //interrupt on falling edge. // ADCON1 = 0x0F; //all digital I/O //****************************************************************************** //****************************************************************************** // RB1 interrupt set up //****************************************************************************** INTCON3bits.INT1IE = 1; //enable RB1 interrupt. INTCON3bits.INT1IP = 0; //Low priority RB1 interrupt INTCON2bits.INTEDG1 = 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 bassa priorita' INTCON2bits.RBIP = 0; //************************************************************ // 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 ; // Setto il flag d'interrupt per inibire le interruzioni su RB1 //INTCONbits.RBIF = 1; //PCF8574_write_data (0x42, 0b11111111); // Resetto il flag d'interrupt per permettere nuove interruzioni //INTCONbits.RBIF = 0; PCF8574_write_data (0x44,light1); PCF8574_write_data (0x46,light2); // Ciclo infinito while (1){ //************************************************************ // Gestione della ricezione codici RC5 //************************************************************ if(got_data){ got_data = 0; if (Control_bit != Control_bit_bak){ Control_bit_bak=Control_bit; ClearLCD(); WriteStringLCD("Data="); WriteIntLCD(data,0); Line2LCD (); WriteStringLCD("Ctrl="); WriteIntLCD(Control_bit,0); //ClearLCD(); //WriteStringLCD("Ctrl="); //WriteIntLCD(Control_bit,0); //Line2LCD (); //WriteStringLCD("Add="); //WriteIntLCD(Address_code,0); //WriteStringLCD(";Com="); //WriteIntLCD(Command_code,0); switch (data){ case 321: //PCF8574_read_data (0x44, &light1);non funziona!!! mask1= 0b00000001; light1_bak = light1; light1=light1_bak & mask1; if (light1==0){ light1=light1_bak + mask1; } else { light1=light1_bak & (255 - mask1); } PCF8574_write_data (0x44,light1); break; case 322: mask1= 0b00000010; light1_bak = light1; light1=light1_bak & mask1; if (light1==0){ light1=light1_bak + mask1; } else { light1=light1_bak & (255 - mask1); } PCF8574_write_data (0x44,light1); break; case 323: mask1= 0b00000100; light1_bak = light1; light1=light1_bak & mask1; if (light1==0){ light1=light1_bak + mask1; } else { light1=light1_bak & (255 - mask1); } PCF8574_write_data (0x44,light1); break; case 324: mask1= 0b00001000; light1_bak = light1; light1=light1_bak & mask1; if (light1==0){ light1=light1_bak + mask1; } else { light1=light1_bak & (255 - mask1); } PCF8574_write_data (0x44,light1); break; case 325: mask1= 0b00010000; light1_bak = light1; light1=light1_bak & mask1; if (light1==0){ light1=light1_bak + mask1; } else { light1=light1_bak & (255 - mask1); } PCF8574_write_data (0x44,light1); break; case 326: mask1= 0b00100000; light1_bak = light1; light1=light1_bak & mask1; if (light1==0){ light1=light1_bak + mask1; } else { light1=light1_bak & (255 - mask1); } PCF8574_write_data (0x44,light1); break; case 327: mask1= 0b01000000; light1_bak = light1; light1=light1_bak & mask1; if (light1==0){ light1=light1_bak + mask1; } else { light1=light1_bak & (255 - mask1); } PCF8574_write_data (0x44,light1); break; case 328: mask1= 0b10000000; light1_bak = light1; light1=light1_bak & mask1; if (light1==0){ light1=light1_bak + mask1; } else { light1=light1_bak & (255 - mask1); } PCF8574_write_data (0x44,light1); break; case 329: mask2= 0b00000001; light2_bak = light2; light2=light2_bak & mask2; if (light2==0){ light2=light2_bak + mask2; } else { light2=light2_bak & (255 - mask2); } PCF8574_write_data (0x46,light2); break; case 320: mask2= 0b00000010; light2_bak = light2; light2=light2_bak & mask2; if (light2==0){ light2=light2_bak + mask2; } else { light2=light2_bak & (255 - mask2); } PCF8574_write_data (0x46,light2); break; case 370: mask2= 0b00000100; light2_bak = light2; light2=light2_bak & mask2; if (light2==0){ light2=light2_bak + mask2; } else { light2=light2_bak & (255 - mask2); } PCF8574_write_data (0x46,light2); break; case 373: mask2= 0b00001000; light2_bak = light2; light2=light2_bak & mask2; if (light2==0){ light2=light2_bak + mask2; } else { light2=light2_bak & (255 - mask2); } PCF8574_write_data (0x46,light2); break; case 372: mask2= 0b00010000; light2_bak = light2; light2=light2_bak & mask2; if (light2==0){ light2=light2_bak + mask2; } else { light2=light2_bak & (255 - mask2); } PCF8574_write_data (0x46,light2); break; case 374: mask2= 0b00100000; light2_bak = light2; light2=light2_bak & mask2; if (light2==0){ light2=light2_bak + mask2; } else { light2=light2_bak & (255 - mask2); } PCF8574_write_data (0x46,light2); break; case 375: mask2= 0b01000000; light2_bak = light2; light2=light2_bak & mask2; if (light2==0){ light2=light2_bak + mask2; } else { light2=light2_bak & (255 - mask2); } PCF8574_write_data (0x46,light2); break; case 368: mask2= 0b10000000; light2_bak = light2; light2=light2_bak & mask2; if (light2==0){ light2=light2_bak + mask2; } else { light2=light2_bak & (255 - mask2); } PCF8574_write_data (0x46,light2); break; default:; } } } //************************************************************ // Gestione della pressione dei tasti //************************************************************ if(got_switch){ got_switch = 0; ClearLCD(); WriteStringLCD("button="); WriteIntLCD(button,0); mask = 1; mask = mask << button-1; //mask = 65535 - mask; mask1 = mask; mask = mask >> 8; mask2 = mask; Line2LCD (); WriteStringLCD("m1="); WriteIntLCD(mask1,0); WriteStringLCD("m2="); WriteIntLCD(mask2,0); if (mask1>0){ //PCF8574_read_data (0x44, &light1_bak); light1_bak = light1; light1=light1_bak & mask1; if (light1==0){ light1=light1_bak + mask1; } else { light1=light1_bak & (255 - mask1); } PCF8574_write_data (0x44,light1); } if (mask2>0){ //PCF8574_read_data (0x46, &light2_bak); light2_bak=light2; light2=light2_bak & mask2; if (light2==0){ light2=light2_bak + mask2; } else { light2=light2_bak & (255 - mask2); } PCF8574_write_data (0x46,light2); } } /* PCF8574_read_data (0x40, &light1); PCF8574_read_data (0x42, &light2); PCF8574_write_data (0x44,light1); PCF8574_write_data (0x46,light2); // Delay10KTCYx(255); */ } }