Projekte
workwind
BGX1 firmware
i2c.c
Projekte
Forum
Doku
Öffentliche Projekte
Startseite
Beispielprogramme
Projekte von anderen
Welcome
Username
Passwort
Eingeloggt bleiben
Zugangsdaten vergessen?
Registrieren
Projektverwaltung
⇨ Please choose! ⇦
——————————————————
✎ Create new project...
★ Browse existing projects...
——————————————————
⚬ MotorTest#1
⚬ C Tutorial 8#1
⚬ NIBO2 C Project#1
⚙ C Tutorial 15#1
⚬ 2010_11_18_el_test001#1
BGX1 firmware
adc.c
adc.h
battery.xbm
bgx1_protocol.h
Biene.xbm
display.c
display.h
exclamation.xbm
gfx.c
gfx.h
i2c.c
i2c.h
i2cconf.h
images.c
images.h
iodefs.h
iodefs_bgx1.h
main.c
MarsRover.xbm
Nase.xbm
nicai_logo.xbm
pwm.c
pwm.h
question.xbm
smily1.xbm
smily2.xbm
Project details
Compiler settings
Nachrichten
Sie sind nicht eingeloggt.
Neuigkeiten
★
NiboRoboLib 3.6
2017-01-17: Neue Version 3.6
★
NiboRoboLib 3.4.1
2016-04-16: Neue Version 3.4.1
★
Coding Tutorial
2015-11-22: Jetzt auch für den NIBO burger!
Site-Statistic
7433 private projects
378 public projects
16180353 lines compiled
58212 builds
NIBO
@
bgx1_firmware/i2c.c [read only]
/*! \file i2c.c \brief I2C interface using AVR Two-Wire Interface (TWI) hardware. */ //***************************************************************************** // // File Name: 'i2c.c' // Title: I2C interface using AVR Two-Wire Interface (TWI) hardware // Author: Pascal Stang - Copyright (C) 2002-2003 // Modified: Nils Springob 2010 // // This code is distributed under the GNU Public License // which can be found at http://www.gnu.org/licenses/gpl.txt // //***************************************************************************** #include <avr/io.h> #include <avr/interrupt.h> #include "i2c.h" // TWSR values (not bits) // (taken from avr-libc twi.h - thank you Marek Michalkiewicz) // Master #define TW_START 0x08 #define TW_REP_START 0x10 // Master Transmitter #define TW_MT_SLA_ACK 0x18 #define TW_MT_SLA_NACK 0x20 #define TW_MT_DATA_ACK 0x28 #define TW_MT_DATA_NACK 0x30 #define TW_MT_ARB_LOST 0x38 // Master Receiver #define TW_MR_ARB_LOST 0x38 #define TW_MR_SLA_ACK 0x40 #define TW_MR_SLA_NACK 0x48 #define TW_MR_DATA_ACK 0x50 #define TW_MR_DATA_NACK 0x58 // Slave Transmitter #define TW_ST_SLA_ACK 0xA8 #define TW_ST_ARB_LOST_SLA_ACK 0xB0 #define TW_ST_DATA_ACK 0xB8 #define TW_ST_DATA_NACK 0xC0 #define TW_ST_LAST_DATA 0xC8 // Slave Receiver #define TW_SR_SLA_ACK 0x60 #define TW_SR_ARB_LOST_SLA_ACK 0x68 #define TW_SR_GCALL_ACK 0x70 #define TW_SR_ARB_LOST_GCALL_ACK 0x78 #define TW_SR_DATA_ACK 0x80 #define TW_SR_DATA_NACK 0x88 #define TW_SR_GCALL_DATA_ACK 0x90 #define TW_SR_GCALL_DATA_NACK 0x98 #define TW_SR_STOP 0xA0 // Misc #define TW_NO_INFO 0xF8 #define TW_BUS_ERROR 0x00 // defines and constants #define TWCR_CMD_MASK 0x0F #define TWSR_STATUS_MASK 0xF8 // return values #define I2C_OK 0x00 #define I2C_ERROR_NODEV 0x01 // Standard I2C bit rates are: // 100KHz for slow speed // 400KHz for high speed // I2C state and address variables static volatile eI2cStateType I2cState; static uint8_t I2cDeviceAddrRW; // send/transmit buffer (outgoing data) static uint8_t I2cSendData[I2C_SEND_DATA_BUFFER_SIZE]; static uint8_t I2cSendDataIndex; static uint8_t I2cSendDataLength; // receive buffer (incoming data) static uint8_t I2cReceiveData[I2C_RECEIVE_DATA_BUFFER_SIZE]; static uint8_t I2cReceiveDataIndex; static uint8_t I2cReceiveDataLength; // function pointer to i2c receive routine //! I2cSlaveReceive is called when this processor // is addressed as a slave for writing static void (*i2c_slaveReceive)(uint8_t receiveDataLength, uint8_t* recieveData); //! I2cSlaveTransmit is called when this processor // is addressed as a slave for reading static uint8_t (*i2c_slaveTransmit)(uint8_t transmitDataLengthMax, uint8_t* transmitData); // functions void i2c_init() { // clear SlaveReceive and SlaveTransmit handler to null i2c_slaveReceive = 0; i2c_slaveTransmit = 0; // set i2c bit rate to 100KHz i2c_setBitrate(100); // enable TWI (two-wire interface) TWCR |= _BV(TWEN); // set state I2cState = I2C_IDLE; // enable TWI interrupt and slave address ACK TWCR |= _BV(TWIE); TWCR |= _BV(TWEA); } void i2c_setBitrate(uint16_t bitrateKHz) { uint8_t bitrate_div; // set i2c bitrate // SCL freq = F_CPU/(16+2*TWBR)) #ifdef TWPS0 // for processors with additional bitrate division (mega128) // SCL freq = F_CPU/(16+2*TWBR*4^TWPS) // set TWPS to zero TWSR &= ~_BV(TWPS0); TWSR &= ~_BV(TWPS1); #endif // calculate bitrate division bitrate_div = ((F_CPU/1000l)/bitrateKHz); if (bitrate_div >= 16) { bitrate_div = (bitrate_div-16)/2; } TWBR = bitrate_div; } void i2c_setLocalDeviceAddr(uint8_t deviceAddr, uint8_t genCallEn) { // set local device address (used in slave mode only) TWAR = ((deviceAddr&0xFE) | (genCallEn?1:0)); } void i2c_setSlaveReceiveHandler(void (*i2cSlaveRx_func)(uint8_t receiveDataLength, uint8_t* recieveData)) { i2c_slaveReceive = i2cSlaveRx_func; } void i2c_setSlaveTransmitHandler(uint8_t (*i2cSlaveTx_func)(uint8_t transmitDataLengthMax, uint8_t* transmitData)) { i2c_slaveTransmit = i2cSlaveTx_func; } inline void i2c_sendStart() { // send start condition TWCR = (TWCR&TWCR_CMD_MASK)|_BV(TWINT)|_BV(TWSTA); } inline void i2c_sendStop() { // transmit stop condition // leave with TWEA on for slave receiving TWCR = (TWCR&TWCR_CMD_MASK)|_BV(TWINT)|_BV(TWEA)|_BV(TWSTO); } inline void i2c_waitForComplete() { // wait for i2c interface to complete operation while( !(TWCR & _BV(TWINT)) ); } inline void i2c_sendByte(uint8_t data) { // save data to the TWDR TWDR = data; // begin send TWCR = (TWCR&TWCR_CMD_MASK)|_BV(TWINT); } inline void i2c_receiveByte(uint8_t ackFlag) { // begin receive over i2c if (ackFlag) { // ackFlag = TRUE: ACK the recevied data TWCR = (TWCR&TWCR_CMD_MASK)|_BV(TWINT)|_BV(TWEA); } else { // ackFlag = FALSE: NACK the recevied data TWCR = (TWCR&TWCR_CMD_MASK)|_BV(TWINT); } } inline uint8_t i2c_getReceivedByte() { // retieve received data byte from i2c TWDR return TWDR; } inline uint8_t i2c_getStatus() { // retieve current i2c status from i2c TWSR return TWSR; } void i2c_masterSend(uint8_t deviceAddr, uint8_t length, uint8_t* data) { uint8_t i; // wait for interface to be ready while(I2cState); // set state I2cState = I2C_MASTER_TX; // save data I2cDeviceAddrRW = (deviceAddr & 0xFE); // RW cleared: write operation for (i=0; i<length; i++) { I2cSendData[i] = *data++; } I2cSendDataIndex = 0; I2cSendDataLength = length; // send start condition i2c_sendStart(); } void i2c_masterReceive(uint8_t deviceAddr, uint8_t length, uint8_t* data) { uint8_t i; // wait for interface to be ready while(I2cState); // set state I2cState = I2C_MASTER_RX; // save data I2cDeviceAddrRW = (deviceAddr|0x01); // RW set: read operation I2cReceiveDataIndex = 0; I2cReceiveDataLength = length; // send start condition i2c_sendStart(); // wait for data while(I2cState); // return data for (i=0; i<length; i++) { *data++ = I2cReceiveData[i]; } } uint8_t i2c_masterSendNI(uint8_t deviceAddr, uint8_t length, uint8_t* data) { uint8_t retval = I2C_OK; // disable TWI interrupt TWCR &= ~_BV(TWIE); // send start condition i2c_sendStart(); i2c_waitForComplete(); // send device address with write i2c_sendByte( deviceAddr & 0xFE ); i2c_waitForComplete(); // check if device is present and live if (TWSR == TW_MT_SLA_ACK) { // send data while(length) { i2c_sendByte( *data++ ); i2c_waitForComplete(); length--; } } else { // device did not ACK it's address, // data will not be transferred // return error retval = I2C_ERROR_NODEV; } // transmit stop condition // leave with TWEA on for slave receiving i2c_sendStop(); while( !(TWCR & _BV(TWSTO)) ); // enable TWI interrupt TWCR |= _BV(TWIE); return retval; } uint8_t i2c_masterReceiveNI(uint8_t deviceAddr, uint8_t length, uint8_t *data) { uint8_t retval = I2C_OK; // disable TWI interrupt TWCR &= ~_BV(TWIE); // send start condition i2c_sendStart(); i2c_waitForComplete(); // send device address with read i2c_sendByte( deviceAddr | 0x01 ); i2c_waitForComplete(); // check if device is present and live if (TWSR == TW_MR_SLA_ACK) { // accept receive data and ack it while (length > 1) { i2c_receiveByte(1); i2c_waitForComplete(); *data++ = i2c_getReceivedByte(); // decrement length length--; } // accept receive data and nack it (last-byte signal) i2c_receiveByte(0); i2c_waitForComplete(); *data++ = i2c_getReceivedByte(); } else { // device did not ACK it's address, // data will not be transferred // return error retval = I2C_ERROR_NODEV; } // transmit stop condition // leave with TWEA on for slave receiving i2c_sendStop(); // enable TWI interrupt TWCR |= _BV(TWIE); return retval; } /* void i2cMasterTransferNI(uint8_t deviceAddr, uint8_t sendlength, uint8_t* senddata, uint8_t receivelength, uint8_t* receivedata) { // disable TWI interrupt cbi(TWCR, TWIE); // send start condition i2cSendStart(); i2cWaitForComplete(); // if there's data to be sent, do it if(sendlength) { // send device address with write i2cSendByte( deviceAddr & 0xFE ); i2cWaitForComplete(); // send data while(sendlength) { i2cSendByte( *senddata++ ); i2cWaitForComplete(); sendlength--; } } // if there's data to be received, do it if(receivelength) { // send repeated start condition i2cSendStart(); i2cWaitForComplete(); // send device address with read i2cSendByte( deviceAddr | 0x01 ); i2cWaitForComplete(); // accept receive data and ack it while(receivelength > 1) { i2cReceiveByte(TRUE); i2cWaitForComplete(); *receivedata++ = i2cGetReceivedByte(); // decrement length receivelength--; } // accept receive data and nack it (last-byte signal) i2cReceiveByte(TRUE); i2cWaitForComplete(); *receivedata++ = i2cGetReceivedByte(); } // transmit stop condition // leave with TWEA on for slave receiving i2cSendStop(); while( !(inb(TWCR) & BV(TWSTO)) ); // enable TWI interrupt sbi(TWCR, TWIE); } */ //! I2C (TWI) interrupt service routine SIGNAL(TWI_vect) { // read status bits uint8_t status = TWSR & TWSR_STATUS_MASK; switch (status) { // Master General case TW_START: // 0x08: Sent start condition case TW_REP_START: // 0x10: Sent repeated start condition // send device address i2c_sendByte(I2cDeviceAddrRW); break; // Master Transmitter & Receiver status codes case TW_MT_SLA_ACK: // 0x18: Slave address acknowledged case TW_MT_DATA_ACK: // 0x28: Data acknowledged if (I2cSendDataIndex < I2cSendDataLength) { // send data i2c_sendByte( I2cSendData[I2cSendDataIndex++] ); } else { // transmit stop condition, enable SLA ACK i2c_sendStop(); // set state I2cState = I2C_IDLE; } break; case TW_MR_DATA_NACK: // 0x58: Data received, NACK reply issued // store final received data byte I2cReceiveData[I2cReceiveDataIndex++] = TWDR; // continue to transmit STOP condition case TW_MR_SLA_NACK: // 0x48: Slave address not acknowledged case TW_MT_SLA_NACK: // 0x20: Slave address not acknowledged case TW_MT_DATA_NACK: // 0x30: Data not acknowledged // transmit stop condition, enable SLA ACK i2c_sendStop(); // set state I2cState = I2C_IDLE; break; case TW_MT_ARB_LOST: // 0x38: Bus arbitration lost //case TW_MR_ARB_LOST: // 0x38: Bus arbitration lost // release bus TWCR = (TWCR&TWCR_CMD_MASK)|_BV(TWINT); // set state I2cState = I2C_IDLE; // release bus and transmit start when bus is free //outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWSTA)); break; case TW_MR_DATA_ACK: // 0x50: Data acknowledged // store received data byte I2cReceiveData[I2cReceiveDataIndex++] = TWDR; // fall-through to see if more bytes will be received case TW_MR_SLA_ACK: // 0x40: Slave address acknowledged if (I2cReceiveDataIndex < (I2cReceiveDataLength-1)) { // data byte will be received, reply with ACK (more bytes in transfer) i2c_receiveByte(1); } else { // data byte will be received, reply with NACK (final byte in transfer) i2c_receiveByte(0); } break; // Slave Receiver status codes case TW_SR_SLA_ACK: // 0x60: own SLA+W has been received, ACK has been returned case TW_SR_ARB_LOST_SLA_ACK: // 0x68: own SLA+W has been received, ACK has been returned case TW_SR_GCALL_ACK: // 0x70: GCA+W has been received, ACK has been returned case TW_SR_ARB_LOST_GCALL_ACK: // 0x78: GCA+W has been received, ACK has been returned // we are being addressed as slave for writing (data will be received from master) // set state I2cState = I2C_SLAVE_RX; // prepare buffer I2cReceiveDataIndex = 0; // receive data byte and return ACK TWCR = (TWCR&TWCR_CMD_MASK)|_BV(TWINT)|_BV(TWEA); break; case TW_SR_DATA_ACK: // 0x80: data byte has been received, ACK has been returned case TW_SR_GCALL_DATA_ACK: // 0x90: data byte has been received, ACK has been returned // get previously received data byte I2cReceiveData[I2cReceiveDataIndex++] = TWDR; // check receive buffer status if (I2cReceiveDataIndex < I2C_RECEIVE_DATA_BUFFER_SIZE) { // receive data byte and return ACK i2c_receiveByte(1); //outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA)); } else { // receive data byte and return NACK i2c_receiveByte(0); //outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)); } break; case TW_SR_DATA_NACK: // 0x88: data byte has been received, NACK has been returned case TW_SR_GCALL_DATA_NACK: // 0x98: data byte has been received, NACK has been returned // receive data byte and return NACK i2c_receiveByte(0); //outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)); break; case TW_SR_STOP: // 0xA0: STOP or REPEATED START has been received while addressed as slave // i2c receive is complete, call i2cSlaveReceive if(i2c_slaveReceive) i2c_slaveReceive(I2cReceiveDataIndex, I2cReceiveData); // switch to SR mode with SLA ACK TWCR = (TWCR&TWCR_CMD_MASK)|_BV(TWINT)|_BV(TWEA); // set state I2cState = I2C_IDLE; break; // Slave Transmitter case TW_ST_SLA_ACK: // 0xA8: own SLA+R has been received, ACK has been returned case TW_ST_ARB_LOST_SLA_ACK: // 0xB0: GCA+R has been received, ACK has been returned // we are being addressed as slave for reading (data must be transmitted back to master) // set state I2cState = I2C_SLAVE_TX; // request data from application if(i2c_slaveTransmit) I2cSendDataLength = i2c_slaveTransmit(I2C_SEND_DATA_BUFFER_SIZE, I2cSendData); // reset data index I2cSendDataIndex = 0; // fall-through to transmit first data byte case TW_ST_DATA_ACK: // 0xB8: data byte has been transmitted, ACK has been received // transmit data byte TWDR = I2cSendData[I2cSendDataIndex++]; if(I2cSendDataIndex < I2cSendDataLength) { // expect ACK to data byte TWCR = (TWCR&TWCR_CMD_MASK)|_BV(TWINT)|_BV(TWEA); } else { // expect NACK to data byte TWCR = (TWCR&TWCR_CMD_MASK)|_BV(TWINT); } break; case TW_ST_DATA_NACK: // 0xC0: data byte has been transmitted, NACK has been received case TW_ST_LAST_DATA: // 0xC8: // all done // switch to open slave TWCR = (TWCR&TWCR_CMD_MASK)|_BV(TWINT)|_BV(TWEA); // set state I2cState = I2C_IDLE; break; // Misc case TW_NO_INFO: // 0xF8: No relevant state information // do nothing break; case TW_BUS_ERROR: // 0x00: Bus error due to illegal start or stop condition // reset internal hardware and release bus TWCR = (TWCR&TWCR_CMD_MASK)|_BV(TWINT)|_BV(TWSTO)|_BV(TWEA); // set state I2cState = I2C_IDLE; break; } } eI2cStateType i2c_getState() { return I2cState; }
Compiler results:
Werbung
Online
palmaagosto630589
warrenhinder6456