#include #include #include #include #pragma config PLLDIV = 5 // 20 MHz Oscillator #pragma config CPUDIV = OSC1_PLL2 // OSC1_PLL2 #pragma config USBDIV = 2 // 48 MHz CPU-CLK #pragma config FOSC = HSPLL_HS // Highspeed with phase locked loop //#pragma config FOSC = HS // Highspeed, no phase locked loop #pragma config FCMEN = OFF #pragma config IESO = OFF #pragma config DEBUG = OFF //#ifdef __DEBUG #pragma config PWRT = OFF #pragma config WDT = OFF, WDTPS = 1024 //#else // #pragma config PWRT = ON // #pragma config WDT = ON, WDTPS = 32768 //#endif #pragma config BOR = OFF, BORV = 0 #pragma config VREGEN = OFF //3.3V regulator #pragma config MCLRE = OFF #pragma config LPT1OSC = OFF #pragma config PBADEN = OFF #pragma config CCP2MX = OFF #pragma config STVREN = ON #pragma config LVP = OFF #pragma config ICPRT = ON//OFF #pragma config XINST = OFF #pragma config CP0 = OFF, CP1 = OFF, CP2 = OFF #pragma config CPB = OFF, CPD = OFF #pragma config WRT0 = OFF, WRT1 = OFF, WRT2 = OFF #pragma config WRTB = OFF, WRTC = OFF, WRTD = OFF #pragma config EBTR0 = OFF, EBTR1 = OFF, EBTR2 = OFF, EBTRB = OFF #define _XTAL_FREQ 20000000 //void low_isr (void); void high_isr(void); unsigned char databyte; unsigned char status = 0; unsigned char readIndex = 0; unsigned char writeIndex = 0; unsigned char R_CNT = 0; void delay_sec(unsigned char sec); void delay_msec(unsigned char msec); void leds_test(void); void writeByte(void); unsigned char I2C_Send[7]; unsigned char I2C_Recv[21]; #pragma code low_vector=0x08 //High interrupt priority starts at 0x08 void high_interrupt(void) { _asm GOTO high_isr _endasm } #pragma code #pragma interrupt high_isr void high_isr(void) { unsigned int checksum = 0; unsigned char data = 0; if (PIR1bits.SSPIF) { if (SSPSTATbits.S) // start bit has been detected last { status = 0; if (SSPSTATbits.R_W == 0) // master write operation { if (SSPSTATbits.BF) { data = SSPBUF; if (SSPSTATbits.D_A == 0) //last byte was an address byte { //PORTD = data; status = 1; readIndex = 0; writeIndex = 0; } else { if (data == 0xF6) { checksum = 0; writeIndex = 0; //I2C_Send[0] = 0b11000011; // test data, can be replaced by PORTA; I2C_Send[0] = PORTA; I2C_Send[1] = PORTB; // test data, can be replaced by PORTB; I2C_Send[2] = PORTC; // test data, can be replaced by PORTB; I2C_Send[3] = PORTD; // test data, can be replaced by PORTD; I2C_Send[4] = PORTE; // test data, can be replaced by PORTE; checksum += I2C_Send[0]; checksum += I2C_Send[1]; checksum += I2C_Send[2]; checksum += I2C_Send[3]; checksum += I2C_Send[4]; I2C_Send[5] = checksum >> 8; // high byte I2C_Send[6] = (checksum << 8) >> 8; // low byte writeIndex = 0; R_CNT++; } status = 2; //PORTD = 2; if (readIndex < 20) { I2C_Recv[readIndex] = data; //PORTD = I2C_Recv[readIndex]; readIndex++; } } SSPCON1bits.CKP = 1; } } else // master read operation { if (SSPSTATbits.D_A == 0)//last byte was an address byte { if (SSPSTATbits.BF) { data = SSPBUF; } SSPBUF = I2C_Send[writeIndex++]; if(writeIndex >= 7) { writeIndex =0; } //PORTD = 0b11000011; status = 3; SSPCON1bits.CKP = 1; } else if (SSPSTATbits.BF) { data = SSPBUF; status = 4; writeByte(); writeIndex++; SSPCON1bits.CKP = 1; } else if(!SSPCON1bits.CKP){ writeByte(); writeIndex++; SSPCON1bits.CKP = 1; } } } //PORTD = R_CNT; PIR1bits.SSPIF = 0; } } void writeByte(void) { //PORTD = 0b11110000; SSPCON1bits.WCOL = 0; SSPBUF = 0b11000011; while (SSPCON1bits.WCOL) { SSPCON1bits.WCOL = 0; SSPBUF = 0b10000011; //PORTD = 0b11001101; } //PORTD = 0b11110011; } /* #pragma code low_vector=0x18 //Low interrupt priority starts at 0x18 void low_interrupt(void) { _asm GOTO low_isr _endasm } #pragma code #pragma interrupt low_isr void low_isr (void) { PORTD = 3; if(PIR1bits.SSPIF) //Timer0 interrupt { PIR1bits.SSPIF = 0; PORTD = 4; } } */ void main(void) { unsigned char sync_mode = 0, slew = 0, add1, status, temp, w, length = 0; unsigned char slaveEvenAddress = 0x42; unsigned char slaveOddAddress = 0x42 | 0x01; unsigned char command = 0x00; unsigned char counter = 0x00; unsigned char counter2 = 0x00; unsigned char slaveData = 0x00; unsigned char mask = 0x00; PORTA = 0; TRISA = 0b00111111; // PORTA7...A6 outputs, A5-A0 inputs PORTA = 0b00000000; /* Two pins are used for data transfer: ? Serial clock (I2C_SCL) ? RB1/AN10/INT1/SCK/I2C_SCL ? Serial data (I2C_SDA) ? RB0/AN12/INT0/FLT0/SDI/I2C_SDA The user must configure these pins as inputs by setting the associated TRIS bits. */ ADCON1 = 0b00001111; //AN0...AN12 as digital I/O PORTB = 0; TRISB = 0b11111111; //RB0...RB7 as digital inputs PORTB = 0b11111111; PORTC = 0; TRISC = 0b11111111; // PORTC as digital inputs PORTC = 0b11111111; PORTD = 0; TRISD = 0b11111111; // PORTD as digital inputs PORTD = 0b11111111; PORTE = 0; TRISE = 0b11111111; // PORTE as digital inputs PORTE = 0b11111111; UCONbits.USBEN = 0; //RC5 and RC4 are only available as port pins when the USB module is disabled (UCON<3> = 0). UCFGbits.FSEN = 0; UCFG = 0b00001100; // disable onchip tranceiver //leds_test(); for (w = 0; w < 20; w++) { I2C_Recv[w] = 0; I2C_Send[w] = 0b11000011; } CloseI2C(); //close i2c if was operating earlier //------------------------INITIALISE THE I2C MODULE FOR MASTER MODE WITH 100KHz --------------------------- SSPCON1 = 0; SSPCON2 = 0; SSPSTAT = 0; SSPCON2bits.GCEN = 1; //General Call Enable bit (Slave mode only) SSPSTATbits.SMP = 1; // slew rate is disabled SSPSTATbits.CKE = 1; // enable SM SSPCON1bits.CKP = 1; // Release clock SSPCON2bits.SEN = 1; // 0 =Clock stretching is disabled //SSPCON2 = 0b10111110;// mask enabled SSPCON2 = 0b10000000;// no mask //SSPCON1 = 0b00101110;// I2C Slave mode, 7-bit address with Start and Stop bit interrupts enabled(2) SSPCON1 = 0b00100110; // I2C Slave mode, 7-bit address SSPSTATbits.SMP = 1; // 1 = slew rate is disabled SSPADD = slaveEvenAddress; //initialze slave address //PORTD = 1; PIE1bits.SSPIE = 1; //SSPIE: Master Synchronous Serial Port Interrupt Enable bit INTCONbits.PEIE = 1; //Enable all peripheral interrupts INTCONbits.GIE = 1; //Enable global interrupts //PORTD = 2; while (1) { } while (1) { //PORTD = 2; while (DataRdyI2C() == 0); //WAIT UNTILL THE DATA IS TRANSMITTED FROM master temp = ReadI2C(); if (temp == slaveEvenAddress) { //PORTD = 3; //********************* Data reception from master by slave ********************* do { while (DataRdyI2C() == 0); //WAIT UNTILL THE DATA IS TRANSMITTED FROM master I2C_Recv[length++] = getcI2C(); // save byte received //PORTD = PORTD + 1; } while (length != 20); //PORTD = 4; //******************** write sequence from slave ******************************* while (SSPSTATbits.S != 1); //wait untill STOP CONDITION //PORTD = 5; //********************* Read the address sent by master from buffer ************** while (DataRdyI2C() == 0); //WAIT UNTILL THE DATA IS TRANSMITTED FROM master temp = ReadI2C(); if (temp == slaveEvenAddress) { //PORTD = 6; command = ReadI2C(); //PORTD = command; slaveData++; } while (DataRdyI2C() == 0); //WAIT UNTILL THE DATA IS TRANSMITTED FROM master //PORTD = 7; temp = ReadI2C(); if (temp == slaveOddAddress) { //PORTD = 8; } else { //PORTD = temp; while (1) { } } //PORTD = 10; temp = SSPBUF; slaveData = 0b11000011; /* bit 7 SMP: Slew Rate Control bit In Master or Slave mode: 1 = Slew rate control disabled for Standard Speed mode (100 kHz and 1 MHz) 0 = Slew rate control enabled for High-Speed mode (400 kHz) bit 6 CKE: SMBus Select bit In Master or Slave mode: 1 = Enable SMBus specific inputs 0 = Disable SMBus specific inputs bit 5 D/A: Data/Address bit In Master mode: Reserved. In Slave mode: 1 = Indicates that the last byte received or transmitted was data 0 = Indicates that the last byte received or transmitted was address bit 4 P: Stop bit(1) 1 = Indicates that a Stop bit has been detected last 0 = Stop bit was not detected last bit 3 S: Start bit(1) 1 = Indicates that a Start bit has been detected last 0 = Start bit was not detected last bit 2 R/W: Read/Write Information bit(2,3) In Slave mode: 1 = Read 0 = Write In Master mode: 1 = Transmit is in progress 0 = Transmit is not in progress bit 1 UA: Update Address bit (10-Bit Slave mode only) 1 = Indicates that the user needs to update the address in the SSPADD register 0 = Address does not need to be updated bit 0 BF: Buffer Full Status bit In Transmit mode: 1 = SSPBUF is full 0 = SSPBUF is empty In Receive mode: 1 = SSPBUF is full (does not include the ACK and Stop bits) 0 = SSPBUF is empty (does not include the ACK and Stop bits) */ //movf Temp,W ; //andlw b'00101100' ; Mask BF bit in SSPSTAT //xorlw b'00001100' mask = 0b00001100; status = SSPSTAT; while (status) { //PORTD = status; status = SSPSTAT & 0b00101100; // Mask BF bit in SSPSTAT status = status ^ mask; // mask sspstat } SSPBUF = 0b11000011; while (SSPCON1bits.WCOL) { SSPCON1bits.WCOL = 0; //PORTD = 0b11010011; SSPBUF = 0b11000011; } for (counter = 1; counter < 20; counter++) { mask = 0b00101100; status = SSPSTAT; //S = 1, D_A = 1, R_W = 1, BF = 0 while (status) { //PORTD = status; status = SSPSTAT & 0b00101100; // Mask BF bit in SSPSTAT status = status ^ mask; // mask sspstat } SSPBUF = 0b11000011; while (SSPCON1bits.WCOL) { SSPCON1bits.WCOL = 0; //PORTD = 0b11010011; SSPBUF = 0b11000011; } } //if (SSPSTAT & 0x04) //check if master is ready for reception // while (putsI2C(I2C_Send)); // send the data to master //PORTD = 0b01010101; while (1) { } } else { //PORTD = temp; } } //-------------TERMINATE COMMUNICATION FROM MASTER SIDE--------------- CloseI2C(); //close I2C module } void delay_sec(unsigned char sec) { unsigned char counter1 = 0; unsigned char counter2 = 0; unsigned char counter3 = 0; unsigned char counter4 = 0; for (counter1 = 0; counter1 < sec; counter1++) { for (counter2 = 0; counter2 < 50; counter2++) { for (counter3 = 0; counter3 < 100; counter3++) { for (counter4 = 0; counter4 < 100; counter4++) { Nop(); // (5 * 2) * 100 * 100 * 100 } } } } } void delay_msec(unsigned char msec) { unsigned char counter1 = 0; unsigned char counter2 = 0; unsigned char counter3 = 0; for (counter1 = 0; counter1 < msec; counter1++) { for (counter2 = 0; counter2 < 50; counter2++) { for (counter3 = 0; counter3 < 10; counter3++) { Nop(); // (5 * 2) * 100 * 100 * 100 } } } } void leds_test(void) { PORTD = 0b11111111; delay_msec(100); PORTD = 0b00000001; delay_msec(100); PORTD = PORTD << 1; delay_msec(100); PORTD = PORTD << 1; delay_msec(100); PORTD = PORTD << 1; delay_msec(100); PORTD = PORTD << 1; delay_msec(100); PORTD = PORTD << 1; delay_msec(100); PORTD = PORTD << 1; delay_msec(100); PORTD = PORTD << 1; delay_sec(1); }