// Usare il PIC16 come periferica I2C - Versione 0.1 - Gennaio 2010 // Copyright © 2009, VincenzoV.net (https://www.vincenzov.net) // Creative Commons | Attribuzione-Condividi allo stesso modo 3.0 Unported. // Creative Commons | Attribution-Share Alike 3.0 Unported // https://www.vincenzov.net/tutorial/elettronica-di-base/PIC16F690 #include #define _XTAL_FREQ 8000000 #define I2C_ADDR 0x51 int i2c_counter; __CONFIG(INTIO & // Use internal clock WDTDIS & // Disable watchdog PWRTEN & // Delay after power on enabled MCLRDIS & // Internal External Switch Over Mode Disable UNPROTECT & // Disable memory protection BORDIS & // Disable reset on low volage IESODIS & // Internal External Switch Over Mode Disable FCMDIS); // Disable Fail clock monitoring void main(void) {OSCCON=0x70; // x111 0000 - 8 Mhz internal clock TRISC = 0x00; // Set PORTC as Output ANSEL = 0; // Set as Digital I/O ANSELH = 0; // Set as Digital I/O PORTC = 0x00; // All LEDs off TRISB = 0xFF; // Set PORTB as Inputs // SSPCON = 0; // work around for PIC16F690 for revision A5 and previous //Configure as I2C slave //xxxx 0110 = I2C Slave mode, 7 bit address, no interrupts on start and stop //xxx1 xxxx = CKP = 1, Enable clock //xx1x xxxx = SSPEN, Enable SSP SSPCON = 0b00110110; SSPADD = I2C_ADDR << 1; // Set I2C address SSPSTAT = 0x00; // All bits must be cleared SSPIE = 1; // Enable the SSP module and the SSP interrupt SSPIF = 0; PEIE = 1; GIE = 1; for(;;); // Do nothing... } void interrupt isr(void) // Interrupt Service Routine {if (SSPIF) // I2C interrupt {if(!DA && !RW && BF && START) // An address from master: write to slave {SSPBUF = SSPBUF; // Empty buffer and clear BF bit if(SSPOV) // Check overflow {//... // Overflow handling, if required SSPOV = 0; } } else if(DA && !RW && BF) // Data from master to slave {PORTC = SSPBUF; // Output data to PORTC LEDs and clear BF bit if(SSPOV) // Check overflow {//... // Overflow handling, if required SSPOV = 0; } } else if(!DA && RW && !BF) // An address from master: read from slave {SSPBUF = ++i2c_counter; // Data will be write to master CKP = 1; // Release clock (data ready to be send to master) } else if(DA && RW && !BF && START) // Read a byte from slave (next byte) {SSPBUF = 255-i2c_counter; // Data will be write to master CKP = 1; // Release clock (data ready to be send to master) } else if(DA && !RW && !BF) // NAK from master (complete transmission has occurred) { } } SSPIF = 0; // Re-enable interrupt }