Hello
Sorry for my late answer…
Look @ “Modif CC” into the code.
/*** BeginHeader */ #ifndef __I2C_LIB #define __I2C_LIB /*** EndHeader */ /* START LIBRARY DESCRIPTION ********************************************* I2C.LIB Rabbit Semiconductor, 2001 Library implementing I2C master on port d pins, default SCL=PD6, SDA=PD7 Define I2CSCLBit and I2CSDABit to set pins on D port OR define these functions for other pin options i2c_SCL_H() - set the clock bit high i2c_SCL_L() - set the clock bit low i2c_SDA_H() - set the data bit high i2c_SDA_L() - set the data bit low i2c_SDA() - read data bit (return 1=high=5V or 0) i2c_SCL() - read clock bit (return 1=high=5V or 0) API Functions: i2c_init i2c_start_tx i2c_startw_tx i2c_send_ack i2c_send_nak i2c_read_char i2c_check_ack i2c_write_char i2c_stop_tx i2c_wr_wait Protocol: while clock high START - data high to low STOP - data low to high while clock low Data can change ack : data low while clock pulse nak : data high while clock pulse This library was programmed for Rabbit Semiconductor by: KENT JOHANSEN ANAKRON / ANAKRON CANADA INC www.anakron.com kent@anakron.com END DESCRIPTION *********************************************************/ /*** BeginHeader */ // Define the bits in the D port and the delay to use for I2C #ifndef i2cClockStretchDelay // Counts of I2CDelay to allow for clock stretching #define i2cClockStretchDelay 2000 #endif #ifndef i2cRetries // Number of retries to get an answer from slave in i2c_write_wait #define i2cRetries 1000 #endif #ifndef I2CSCLBit // The clock bit, if on port D. //#define I2CSCLBit 6 // Modif CC -> The clock bit, if on port E #define I2CSCLBit 0 #endif #ifndef I2CSDABit // The data bit, if on port D. //#define I2CSDABit 7 // Modif CC -> The data bit, if on port E #define I2CSDABit 1 #endif /*** EndHeader */ /*** BeginHeader i2c_init,i2c_SCL_H,i2c_SCL_L,i2c_SDA_H,i2c_SDA_L,i2c_SDA,i2c_SCL */ void i2c_init(); int i2c_clocks_per_us; //need declaration to prevent error in asm definition //below #define WAIT_5_us asm ld a,(i2c_clocks_per_us) $\ sub 2 $\ ld b,a $\ db 0x10, -2 //*** define C macro *** // a machine code version of above #define cWAIT_5_us asm ld a,(i2c_clocks_per_us) $\ sub 3 $\ ld b,a $\ db 0x10,-2 // db 3ah,i2c_clocks_per_us&0ffh,(i2c_clocks_per_us>>8)&0ffh,0d6h,3,47h,10h,-2 // Define these to change basic bit handling #ifndef i2c_SCL_H() #define i2c_SCL_H() BitWrPortI(PEDDR,&PEDDRShadow,0,I2CSCLBit) #define i2c_SCL_L() BitWrPortI(PEDDR,&PEDDRShadow,1,I2CSCLBit) #define i2c_SDA_H() BitWrPortI(PEDDR,&PEDDRShadow,0,I2CSDABit) #define i2c_SDA_L() BitWrPortI(PEDDR,&PEDDRShadow,1,I2CSDABit) #define i2c_SCL() BitRdPortI(PEDR,I2CSCLBit) #define i2c_SDA() BitRdPortI(PEDR,I2CSDABit) #endif /*#ifndef i2c_SCL_H() #define i2c_SCL_H() BitWrPortI(PDDDR,&PDDDRShadow,0,I2CSCLBit) #define i2c_SCL_L() BitWrPortI(PDDDR,&PDDDRShadow,1,I2CSCLBit) #define i2c_SDA_H() BitWrPortI(PDDDR,&PDDDRShadow,0,I2CSDABit) #define i2c_SDA_L() BitWrPortI(PDDDR,&PDDDRShadow,1,I2CSDABit) #define i2c_SCL() BitRdPortI(PDDR,I2CSCLBit) #define i2c_SDA() BitRdPortI(PDDR,I2CSDABit) #endif */ /*** EndHeader */ /* START FUNCTION DESCRIPTION ******************************************** i2c_init SYNTAX: int i2c_init(); DESCRIPTION: Sets up the SCL and SDA port pins for open-drain output Also initializes delay constant Acknowledgement: This library is programmed for Rabbit Semiconductor by KENT JOHANSEN ANAKRON / ANAKRON CANADA INC www.anakron.com kent@anakron.com END DESCRIPTION **********************************************************/ nodebug void i2c_init() { //Modif CC le 23/01/2010 //SCL et SDA sur Port E (PD6 et PD7 non dispo sur RCM5700/5600W) // Set the bits to tristate and the output to 0. Toggle using //tristate reg. // This function affects the port D transfer transfer clock // Transfer clock on port D is PCLK/2 WrPortI(PECR,&PECRShadow,0); BitWrPortI(PEFR ,&PEFRShadow ,0,I2CSCLBit); // Set the bits to normal function BitWrPortI(PEFR ,&PEFRShadow ,0,I2CSDABit); BitWrPortI(PEDDR,&PEDDRShadow,0,I2CSCLBit); // Set the bits to input (=0) BitWrPortI(PEDDR,&PEDDRShadow,0,I2CSDABit); BitWrPortI(PEDCR,&PEDCRShadow,1,I2CSCLBit); // Set the bits to Open Drain BitWrPortI(PEDCR,&PEDCRShadow,1,I2CSDABit); BitWrPortI(PEDR ,&PEDRShadow ,0,I2CSCLBit); // Set the outputs to 0, when outputs BitWrPortI(PEDR ,&PEDRShadow ,0,I2CSDABit); // Set the bits to tristate and the output to 0. Toggle using //tristate reg. // This function affects the port D transfer transfer clock // Transfer clock on port D is PCLK/2 //WrPortI(PDCR,&PDCRShadow,0); //BitWrPortI(PDFR ,&PDFRShadow ,0,I2CSCLBit); // Set the bits to normal function //BitWrPortI(PDFR ,&PDFRShadow ,0,I2CSDABit); //BitWrPortI(PDDDR,&PDDDRShadow,0,I2CSCLBit); // Set the bits to input (=0) //BitWrPortI(PDDDR,&PDDDRShadow,0,I2CSDABit); //BitWrPortI(PDDCR,&PDDCRShadow,1,I2CSCLBit); // Set the bits to Open Drain //BitWrPortI(PDDCR,&PDDCRShadow,1,I2CSDABit); //BitWrPortI(PDDR ,&PDDRShadow ,0,I2CSCLBit); // Set the outputs to 0, when outputs //BitWrPortI(PDDR ,&PDDRShadow ,0,I2CSDABit); i2c_clocks_per_us = (int)(19200L*32*freq_divider/1000000L); if(i2c_clocks_per_us < 3) { i2c_clocks_per_us = 3; } } /*** BeginHeader i2c_wSCL_H */ int i2c_wSCL_H(); /*** EndHeader */ /* START FUNCTION DESCRIPTION ******************************************** i2c_wSCL_H SYNTAX: int i2c_wSCL_H(); DESCRIPTION: sets clock high, if slave stretches it, the function waits for max i2cClockStretchDelay i2c_Delay's for the clock to go low slaves use this feature to delay data transfer to master. RETURN VALUE: 0 success, -1 clock stretching timeout END DESCRIPTION **********************************************************/ nodebug int i2c_wSCL_H() { // Sets SCL high and waits for clock stretching. Returns -1 if stretch //too long auto int delcnt; i2c_SCL_H(); cWAIT_5_us; delcnt=0; while(i2c_SCL()==0 && delcnt SYNTAX: int i2c_start_tx(); DESCRIPTION: initiates i2c transmission by sending S first waits for possible clock stretching. data goes low while clock is high. RETURN VALUE: 0 success, -1 clock stretching timeout END DESCRIPTION **********************************************************/ nodebug int i2c_start_tx() { // Try to send start pulse. If clock stretching happening, return 1 else 0 if (i2c_wSCL_H()) return -1; // Check if clock stretching too long i2c_SDA_H(); cWAIT_5_us; i2c_SDA_L(); cWAIT_5_us; i2c_SCL_L(); return 0; } /*** BeginHeader i2c_startw_tx */ int i2c_startw_tx(); /*** EndHeader */ /* START FUNCTION DESCRIPTION ******************************************** i2c_startw_tx SYNTAX: int i2c_startw_tx(); DESCRIPTION: initiates i2c transmission by sending S First waits for possible clock stretching. data goes low while clock is high. Inserts delay after S pulse. RETURN VALUE: 0 success, -1 clock stretching timeout END DESCRIPTION **********************************************************/ nodebug int i2c_startw_tx() { auto unsigned int delcnt; if (i2c_wSCL_H()) return -1; // Check if clock stretching too long i2c_SDA_H(); cWAIT_5_us; i2c_SDA_L(); cWAIT_5_us; i2c_SCL_L(); cWAIT_5_us; return 0; } /*** BeginHeader i2c_send_ack */ int i2c_send_ack(); /*** EndHeader */ /* START FUNCTION DESCRIPTION ******************************************** i2c_send_ack SYNTAX: int i2c_send_ack(); DESCRIPTION: Sends ACK sequence to slave. ACK is usually sent after succesful transfer, where more bytes are to be read. RETURN VALUE: 0 success, -1 clock stretching timeout END DESCRIPTION **********************************************************/ nodebug int i2c_send_ack() { i2c_SDA_L(); cWAIT_5_us; if (i2c_wSCL_H()) return -1; // Check if clock stretching too long cWAIT_5_us; i2c_SCL_L(); cWAIT_5_us; i2c_SDA_H(); return 0; } /*** BeginHeader i2c_send_nak */ int i2c_send_nak(); /*** EndHeader */ /* START FUNCTION DESCRIPTION ******************************************** i2c_send_nak SYNTAX: int i2c_send_nak(); DESCRIPTION: Sends NAK sequence to slave. NAK is often sent when transfer is finished. RETURN VALUE: 0 success, -1 clock stretching timeout END DESCRIPTION **********************************************************/ nodebug int i2c_send_nak() { i2c_SDA_H(); cWAIT_5_us; if (i2c_wSCL_H()) return -1; // Check if clock stretching too long cWAIT_5_us; i2c_SCL_L(); cWAIT_5_us; i2c_SDA_H(); return 0; } /*** BeginHeader i2c_read_char */ int i2c_read_char(char *ch); /*** EndHeader */ /* START FUNCTION DESCRIPTION ******************************************** i2c_read_char SYNTAX: int i2c_read_char(char *ch); DESCRIPTION: Reads 8 bits from slave. Allows for clocks stretching on all SCL going high. This is NOT in the protocol for I2C, but allows I2C slaves to be implemented on slower devices. PARAMETER1: char * ch - 1 character return buffer. RETURN VALUE: 0 success, -1 clock stretching timeout END DESCRIPTION **********************************************************/ nodebug int i2c_read_char(char *ch) { auto char res,cnt; for ( cnt=0,res=0;cnt<8;cnt++ ) { i2c_SDA_H(); cWAIT_5_us; if (i2c_wSCL_H()) return -1; // too long clock stretching res<<=1; if (i2c_SDA()) res|=0x01; i2c_SCL_L(); cWAIT_5_us; } *ch=res; return 0; } /*** BeginHeader i2c_check_ack */ int i2c_check_ack(); /*** EndHeader */ /* START FUNCTION DESCRIPTION ******************************************** i2c_check_ack SYNTAX: int i2c_check_ack(); DESCRIPTION: Checks if slave pulls data low for ACK on clock pulse. Allows for clocks stretching on SCL going high. RETURN VALUE: 0 : Ack sent from slave, 1: NAK sent from slave, -1 : if timeout END DESCRIPTION **********************************************************/ nodebug int i2c_check_ack() { auto int delcnt; i2c_SDA_H(); cWAIT_5_us; if (i2c_wSCL_H()) return -1; // Check if clock stretching too long if (i2c_SDA()) { i2c_SCL_L(); return 1; } i2c_SCL_L(); return 0; } /*** BeginHeader i2c_write_char */ int i2c_write_char(char d); /*** EndHeader */ /* START FUNCTION DESCRIPTION ******************************************** i2c_write_char SYNTAX: int i2c_write_char(char d); DESCRIPTION: Sends 8 bits to slave. Checks if slave pulls data low for ACK on clock pulse. Allows for clocks stretching on SCL going high. PARAMETER1: char ch - character to send RETURN VALUE: 0 success, -1 clock stretching timeout, 1 if NAK sent from slave END DESCRIPTION **********************************************************/ nodebug int i2c_write_char(char d) { // Writes char and returns -1 if no ACK was sent from remote auto char i; for (i=0;i<8;i++) { if (d & 0x80) { i2c_SDA_H(); } else { i2c_SDA_L(); } cWAIT_5_us; if (i2c_wSCL_H()) return -1; i2c_SCL_L(); cWAIT_5_us; d = d << 1; } return i2c_check_ack(); } /*** BeginHeader i2c_stop_tx */ void i2c_stop_tx(); /*** EndHeader */ /* START FUNCTION DESCRIPTION ******************************************** i2c_stop_tx SYNTAX: void i2c_stop_tx(); DESCRIPTION: Sends P (STOP) to slave. Clock goes high, then data goes high. RETURN VALUE: none END DESCRIPTION **********************************************************/ nodebug void i2c_stop_tx() { i2c_SDA_L(); cWAIT_5_us; i2c_SCL_H(); cWAIT_5_us; i2c_SDA_H(); } /*** BeginHeader i2c_wr_wait */ int i2c_wr_wait(char d); /*** EndHeader */ /* START FUNCTION DESCRIPTION ******************************************** i2c_wr_wait SYNTAX: int i2c_wr_wait(char d); DESCRIPTION: Retries char write until slave responds. Max i2cRetries attempts. PARAMETER1: char ch - character to send RETURN VALUE: 0 success, -1 too many retries END DESCRIPTION **********************************************************/ nodebug int i2c_wr_wait(char d) { auto unsigned int cnt; cnt=0; while (i2c_write_char(d) && cnt=i2cRetries) { return -1; // number of retries exceeded } else { return 0; } } /*** BeginHeader */ #endif /*** EndHeader */