char I2C_read(char writeDataLength, char readDataLength, char* writeData) { char j = readDataLength; I2C_START; // do start transition // send the data writeDataLength--; //decrement this to begin with, as the last byte (second addr) will be sent after the repeated start while (writeDataLength--) i2cPutbyte(*writeData++); //repeated start HDEL; I2C_SDL_HI; //prepare for the repeated start HDEL; I2C_SCL_HI; // do a repeated START I2C_START; i2cPutbyte(*writeData); // Send the last byte in the write data array // receive data bytes while (j--) buffer_REPLY[IN_REPORT_HEADER_LENGTH + readDataLength - 1 - j] = i2cGetbyte(j == 0); I2C_SDL_LO; // clear data line and I2C_STOP; // send STOP transition return ERROR_I2C_NOERROR; }
//! Send a byte sequence on the I2C bus void i2c_Send(uint8_t device, uint8_t subAddr, uint16_t length, uint8_t *dataxx) { I2C_START; // do start transition i2cPutbyte(device); // send DEVICE address i2cPutbyte(subAddr); // and the subaddress // send the data while (length--) i2cPutbyte(*dataxx++); I2C_SDA_LO; // clear data line and I2C_STOP; // send STOP transition }
// odczyt danych z pamiêci EEPROM void EI2C_read_buf(u08 device, u16 subAddr, u16 len, u08 *buf) { while (len--) { I2C_START(); i2cPutbyte(device | ((subAddr>>8)<<1) ); i2cPutbyte(subAddr); I2C_REP_START(); i2cPutbyte(device + 1); *buf++ = i2cGetbyte( NACK ); I2C_STOP(); subAddr++; } }
// zapis danych do pamiêci EEPROM void EI2C_write_buf(u08 device, u16 subAddr, u16 len, u08 *buf) { while (len--) { I2C_START(); // ustawienie 9 bitu adresu pamiêci EEPROM w ramach // sprzêtowego adresu urz¹dzenia na pozycji bitu 1 (nr.2) i2cPutbyte( device | ((subAddr>>8)<<1) ); i2cPutbyte(subAddr); i2cPutbyte(*buf++); I2C_STOP(); _delay_ms(5); // oczekiwanie na zapis subAddr++; } }
uint8_t i2c_Receive_Status(uint8_t device) { I2C_START; // do start transition i2cPutbyte(device | READ); // send DEVICE address and read return(i2cGetbyte(1)); // read status byte }
//! Retrieve a byte sequence on the I2C bus void i2c_Receive(uint8_t device, uint8_t subAddr, uint8_t length, uint8_t *dataxx) { int j = length; uint8_t *p = dataxx; I2C_START; // do start transition i2cPutbyte(device); // send DEVICE address i2cPutbyte(subAddr); // and the subaddress HDEL; I2C_SCL_HI; // do a repeated START I2C_START; // transition i2cPutbyte(device | READ); // resend DEVICE, with READ bit set // receive data bytes while (j--) *p++ = i2cGetbyte(j == 0); I2C_SDA_LO; // clear data line and I2C_STOP; // send STOP transition }
//Ensure that the number of addresses does not exceed the reply report length //NOT YET WORKING RIGHT void I2C_busScan(char startAddr, char endAddr, char increment) { char index = 0; for(int i = startAddr; i <= endAddr; i += increment) //loops through available addresses { I2C_START; // do start transition buffer_REPLY[IN_REPORT_HEADER_LENGTH + index++] = i2cPutbyte(i); // write address to bus, check for ACK I2C_SDL_LO; // clear data line and I2C_STOP; // send STOP transition HDEL; HDEL; } setReplyInherentData(S_I2C, I2C_BUS_SCAN, index, 0x00); }
//Data input is //[0] writeDatalength //[1-n] write data (includes address) char I2C_write(char writeDataLength, char* writeData) { char ack = 0; //this stores the values of the ACKs, if any byte is not acked, the error code will be set I2C_START; // do start transition // send the data while (writeDataLength--) ack |= i2cPutbyte(*writeData++); I2C_SDL_LO; // clear data line and I2C_STOP; // send STOP transition if (ack == 0) //all bytes acked return ERROR_I2C_NOERROR; else return ERROR_I2C_NOACK; }
/*! \file i2rtm.c \brief Software I2C interface using port pins. */ //***************************************************************************** // // File Name : 'i2rtm.c' // Title : Software I2C interface to RTM module // Author : Vahan Petrosyan // Created : 10/19/2010 // Target MCU : Atmel AVR series // // Modified by : Markus Joos ([email protected]) // // This code is distributed under the GNU Public License // which can be found at http://www.gnu.org/licenses/gpl.txt // //***************************************************************************** //Note: User code still to be extracted #include <avr/io.h> #include "i2crtm.h" #include "avrlibtypes.h" #include "project.h" #include "timer.h" #include "rtm_mng.h" #include "user_code_select.h" // Standard I2C bit rates are: // 100KHz for slow speed // 400KHz for high speed //************************ //* I2C public functions * //************************ //! Initialise I2C communication //******************/ void i2crtmInit(void) //Called from rtm_mng.c //******************/ { #ifdef USE_RTM sbi(RTMENBUFPORT, RTMENBUF); // In our case activating the RTM I2C only consist into enabling the I2C buffer. Then the same I2C pins are used as for the rest. #endif } //************************************************************************************/ void write_rtm_eeprom_page(u08 base_addr, u08 length, u08 *data, u16 after_write_delay) //called from load_rtm_eeprom in this file //************************************************************************************/ { u08 ack_ok = 0; CRITICAL_SECTION_START; i2cswSend(RTM_EEPROM_ADDR, base_addr, 2, length, data); //Poll for the EEPROM to be ready for the next write while (!ack_ok) { I2C_START ack_ok = i2cPutbyte(RTM_EEPROM_ADDR << 1); I2C_SDL_LO; I2C_STOP } CRITICAL_SECTION_END; }
void instrCall_I2C(char instruction, char* datain, char datainLength) { switch (instruction) { case I2C_WRITE: { I2C_error = I2C_write(datain[0], &datain[1]); break; } case I2C_READ: { I2C_read(datain[0], datain[1], &datain[2]); setReplyInherentData(S_I2C, I2C_READ, datain[1], 0x00); break; } case I2C_SETUP: { I2C_error = I2C_setup(); break; } case I2C_SEND_START: { I2C_error = ERROR_I2C_NOERROR; I2C_SCL_LO; QDEL; I2C_SDL_HI; QDEL; I2C_SCL_HI; QDEL; //ensure the lines are in the correct state before issuing the start I2C_START; break; } case I2C_SEND_STOP: { I2C_STOP; break; } case I2C_SEND_BYTES: { char ack = 0; // send the data char writeDataLength = datain[0]; char* writeData = &datain[1]; while (writeDataLength--) ack |= i2cPutbyte(*writeData++); I2C_SDL_LO; // clear data line if (ack == 0) //all bytes acked I2C_error = ERROR_I2C_NOERROR; else I2C_error = ERROR_I2C_NOACK; break; } case I2C_READ_BYTES: { char readDataLength = datain[0]; char j = readDataLength; while (j--) buffer_REPLY[IN_REPORT_HEADER_LENGTH + readDataLength - 1 - j] = i2cGetbyte(j == 0); I2C_SDL_HI; // clear data line and setReplyInherentData(S_I2C, I2C_READ_BYTES, readDataLength, 0x00); break; } case I2C_CHECK_ERROR: { setReply(S_I2C, I2C_CHECK_ERROR, 1, 0x00, &I2C_error); I2C_error = ERROR_I2C_NOERROR; //reset the error code break; } case I2C_BUS_SCAN: { I2C_busScan(datain[0], datain[1], datain[2]); break; } } }