PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Peter Fleury's I2C Master Library für RP6



Dirk
01.11.2014, 11:52
Hi RP6(v2) Fans,

die RP6I2CmasterTWI Library, die für die RP6 Plattformen (Base, M32, M256 WiFi) mit geliefert wurde (im Ordner /.../RP6Lib/common/), ist für die allermeisten Anwendungsfälle gut geeignet.
Zudem ist sie durch die Interrupt-basierte Umsetzung wenig blockierend.

Es gab aber immer wieder einzelne Fälle, in denen man mit der Lib bestimmte I2C-Slave-Chips nicht ansteuern konnte: Beispiel (https://www.roboternetz.de/community/threads/56861-Frage-zu-RP6-I2C-Library-Funktionen-der-Lib-von-Peter-Fleury)
In dem genannten Thread geht es z.B. um den MLX90614, der bei der Abfrage einen "Repeated Start" auf dem I2C Bus benötigt und nicht einen (Neu-)Start, wie ihn die Original Lib umsetzt.
Mit dem nötigen Know-how kann man die Original Lib von SlyD sicher auch dazu bringen, einen Repeated Start zu machen, aber in dem o.g. Thread ist das nicht gelungen. Durch die Interrupt-basierte Struktur der Lib ist das auch nicht einfach und ich habe das auch nicht fehlerfrei hingekriegt.

Eine Lösung wäre, die bewährte I2C Master Library von Peter Fleury (http://homepage.hispeed.ch/peterfleury/avr-software.html#libs) zu benutzen, um einen "Low-Level" Zugang zu den TWI-Funktionen zu bekommen.
Damit könnte man dann natürlich wahlweise in TWI-Lesefunktionen einen Repeated Start oder einen (Re-)Start machen.

Damit stelle ich euch heute mal eine "Mantel-Library" vor, die anstelle der RP6I2CmasterTWI Library benutzt werden kann. "Mantel" deshalb, weil sie die Kern-Funktionen der Fleury Lib nutzt, aber darüber (als Mantel) die "alten" Befehle der Original-Lib zur Verfügung stellt. Man kann natürlich zusätzlich auch alle Funktionen der Fleury Lib benutzen.

Header RP6I2CmasterTWI_FLEURY.h:

/* ************************************************** **************************
* _______________________
* \| RP6 ROBOT SYSTEM |/
* \_-_-_-_-_-_-_-_-_-_/ >>> COMMON
* ----------------------------------------------------------------------------
* ------------------- [c]2006 / 2007 - AREXX ENGINEERING ---------------------
* ------------------- modified [c]2012 - JM3 Engineering ---------------------
* -------------------------- http://www.arexx.com/ ---------------------------
* ************************************************** **************************
* File: RP6I2CmasterTWI_FLEURY.h
* Version: 1.1
* Target: RP6 Base & Processor Expansion - ATMEGA32 @8.00 or 16.00MHz
* Author(s): Dominik S. Herwald, JM3 Engineering, Peter Fleury
* ************************************************** **************************
* Description:
* For functional description of the TWI Master lib
* s. RP6I2CmasterTWI_FLEURY.c!
*
* ************************************************** **************************
* CHANGELOG AND LICENSING INFORMATION CAN BE FOUND AT THE END OF THIS FILE!
* ************************************************** **************************
*/

#ifdef RP6I2C_SLAVE_TWI_H
#error YOU CAN NOT INCLUDE TWI I2C MASTER AND SLAVE ROUTINES AT THE SAME TIME!
#else
#ifndef RP6I2C_MASTER_TWI_H
#define RP6I2C_MASTER_TWI_H

/************************************************** ***************************/
// Includes:

#include <stdint.h>
#include <avr/interrupt.h>
#include <avr/io.h>
#include "i2cmaster.h" // I2C Master Library, v 1.10 (c) 2005 Peter Fleury

/************************************************** ***************************/

union TWI_statusReg {
uint8_t all;
struct {
unsigned lastTransOK:1;
unsigned dataReady:1;
unsigned repStart:1;
unsigned unusedBits:5;
};
};

extern union TWI_statusReg TWI_statusReg;

//extern uint8_t i2c_req_adr;
extern uint8_t TWI_operation;

#define I2CTWI_isBusy() ((TWCR & (1<<TWIE)))

// Read functions will use the (RE-)START condition (default):
#define I2CTWI_start() {TWI_statusReg.repStart = 0;}
// Read functions will use the REPEATED START condition:
#define I2CTWI_repStart() {TWI_statusReg.repStart = 1;}

#define I2CTWI_isRepStart() (TWI_statusReg.all & 4)
#define I2CTWI_isDataReady() (TWI_statusReg.all & 2)


// Sample TWI transmission states, used in the main application.
#define I2CTWI_NO_OPERATION 0
#define I2CTWI_SEND_REGISTER 1
#define I2CTWI_REQUEST_BYTES 2
#define I2CTWI_READ_BYTES_FROM_BUFFER 3

#define I2CTWI_BUFFER_SIZE 16 // Set this to the largest message size that will be sent including address byte.
#define I2CTWI_BUFFER_REC_SIZE 48 // Set this to the largest message size that will be received including address byte.

#define I2CTWI_initMaster(__FREQ__) __I2CTWI_initMaster((uint8_t)((F_CPU/(2000UL*__FREQ__))-8))
void __I2CTWI_initMaster(uint8_t twi_bitrate);

void I2CTWI_setRequestedDataReadyHandler(void (*requestedDataReadyHandler)(uint8_t));
void I2CTWI_setTransmissionErrorHandler(void (*transmissionErrorHandler)(uint8_t));

void task_I2CTWI(void);
uint8_t I2CTWI_getState(void);

void I2CTWI_requestDataFromDevice(uint8_t requestAdr, uint8_t requestID, uint8_t numberOfBytes);
void I2CTWI_requestRegisterFromDevice(uint8_t targetAdr, uint8_t requestID, uint8_t reg, uint8_t numberOfBytes);
void I2CTWI_getReceivedData(uint8_t *msg, uint8_t msgSize);

void I2CTWI_readBytes(uint8_t targetAdr, uint8_t * messageBuffer, uint8_t numberOfBytes);
uint8_t I2CTWI_readByte(uint8_t targetAdr);
void I2CTWI_readRegisters(uint8_t targetAdr, uint8_t reg, uint8_t * messageBuffer, uint8_t numberOfBytes);
void I2CTWI_readWordRegisters(uint8_t targetAdr, uint8_t reg, uint8_t * messageBuffer, uint8_t numberOfRegs);

void I2CTWI_transmitByte(uint8_t adr, uint8_t data);
void I2CTWI_transmit2Bytes(uint8_t adr, uint8_t data1, uint8_t data2);
void I2CTWI_transmit3Bytes(uint8_t targetAdr, uint8_t data1, uint8_t data2, uint8_t data3);
void I2CTWI_transmit4Bytes(uint8_t targetAdr, uint8_t data1, uint8_t data2, uint8_t data3, uint8_t data4);
void I2CTWI_transmitBytes(uint8_t targetAdr, uint8_t *msg, uint8_t numberOfBytes);

#define TWI_READ 1
#define TWI_GEN_CALL 0

/************************************************** ***************************/
// TWI Status Codes:
// The TWI status codes were taken from ATMEL AN315!

// General TWI Master staus codes
#define TWI_START 0x08 // START has been transmitted
#define TWI_REP_START 0x10 // Repeated START has been transmitted
#define TWI_ARB_LOST 0x38 // Arbitration lost

// TWI Master Transmitter staus codes
#define TWI_MTX_ADR_ACK 0x18 // SLA+W has been transmitted and ACK received
#define TWI_MTX_ADR_NACK 0x20 // SLA+W has been transmitted and NACK received
#define TWI_MTX_DATA_ACK 0x28 // Data byte has been transmitted and ACK received
#define TWI_MTX_DATA_NACK 0x30 // Data byte has been transmitted and NACK received

// TWI Master Receiver staus codes
#define TWI_MRX_ADR_ACK 0x40 // SLA+R has been transmitted and ACK received
#define TWI_MRX_ADR_NACK 0x48 // SLA+R has been transmitted and NACK received
#define TWI_MRX_DATA_ACK 0x50 // Data byte has been received and ACK transmitted
#define TWI_MRX_DATA_NACK 0x58 // Data byte has been received and NACK transmitted

// TWI Slave Transmitter staus codes
#define TWI_STX_ADR_ACK 0xA8 // Own SLA+R has been received; ACK has been returned
#define TWI_STX_ADR_ACK_M_ARB_LOST 0xB0 // Arbitration lost in SLA+R/W as Master; own SLA+R has been received; ACK has been returned
#define TWI_STX_DATA_ACK 0xB8 // Data byte in TWDR has been transmitted; ACK has been received
#define TWI_STX_DATA_NACK 0xC0 // Data byte in TWDR has been transmitted; NOT ACK has been received
#define TWI_STX_DATA_ACK_LAST_BYTE 0xC8 // Last data byte in TWDR has been transmitted (TWEA = “0”); ACK has been received

// TWI Slave Receiver staus codes
#define TWI_SRX_ADR_ACK 0x60 // Own SLA+W has been received ACK has been returned
#define TWI_SRX_ADR_ACK_M_ARB_LOST 0x68 // Arbitration lost in SLA+R/W as Master; own SLA+W has been received; ACK has been returned
#define TWI_SRX_GEN_ACK 0x70 // General call address has been received; ACK has been returned
#define TWI_SRX_GEN_ACK_M_ARB_LOST 0x78 // Arbitration lost in SLA+R/W as Master; General call address has been received; ACK has been returned
#define TWI_SRX_ADR_DATA_ACK 0x80 // Previously addressed with own SLA+W; data has been received; ACK has been returned
#define TWI_SRX_ADR_DATA_NACK 0x88 // Previously addressed with own SLA+W; data has been received; NOT ACK has been returned
#define TWI_SRX_GEN_DATA_ACK 0x90 // Previously addressed with general call; data has been received; ACK has been returned
#define TWI_SRX_GEN_DATA_NACK 0x98 // Previously addressed with general call; data has been received; NOT ACK has been returned
#define TWI_SRX_STOP_RESTART 0xA0 // A STOP condition or repeated START condition has been received while still addressed as Slave

// TWI Miscellaneous status codes
#define TWI_NO_STATE 0xF8 // No relevant state information available; TWINT = “0”
#define TWI_BUS_ERROR 0x00 // Bus error due to an illegal START or STOP condition


#endif
#endif

/************************************************** ****************************
* Additional info
* ************************************************** **************************
* Changelog:
* - v. 1.1 4.09.2012 by JM3 Engineering
* - NEW: added support for reading 16Bit registers
* - v. 1.0 (initial release) 16.05.2007 by Dominik S. Herwald
*
* ************************************************** **************************
* Bugs, feedback, questions and modifications can be posted on the AREXX Forum
* on http://www.arexx.com/forum/ !
* Of course you can also write us an e-mail to: info@arexx.nl
* AREXX Engineering may publish updates from time to time on AREXX.com!
* ************************************************** **************************
* - LICENSE -
* GNU GPL v2 (http://www.gnu.org/licenses/gpl.txt, a local copy can be found
* on the RP6 CD in the RP6 sorce code folders!)
* This program is free software. You can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
* ************************************************** **************************
*/

/************************************************** ***************************/
// EOF

Source RP6I2CmasterTWI_FLEURY.c:

/* ************************************************** **************************
* _______________________
* \| RP6 ROBOT SYSTEM |/
* \_-_-_-_-_-_-_-_-_-_/ >>> COMMON
* ----------------------------------------------------------------------------
* ------------------- [c]2006 / 2007 - AREXX ENGINEERING ---------------------
* ------------------- modified [c]2012 - JM3 Engineering ---------------------
* -------------------------- http://www.arexx.com/ ---------------------------
* ************************************************** **************************
* File: RP6I2CmasterTWI_FLEURY.c
* Version: 1.1
* Target: RP6 Base & Processor Expansion - ATMEGA32 @8.00 or 16.00MHz
* Author(s): Dominik S. Herwald, JM3 Engineering, Peter Fleury
* ************************************************** **************************
* Description:
* This is the I2C Bus Master Library based on the Fleury I2C Master Library.
* Download the file "i2cmaster.zip" here:
* http://homepage.hispeed.ch/peterfleury/avr-software.html#libs
* Extract the files "i2cmaster.h" and "twimaster.c" and copy them to the
* folder /.../RP6Lib/RP6common.
* Please include twimaster.c in makefile of your project:
* SRC += $(RP6_LIB_PATH)/RP6common/twimaster.c
* You will find documentation for this library here:
* http://homepage.hispeed.ch/peterfleury/group__pfleury__ic2master.html
* This I2C Bus Master Library can be used instead of the original
* RP6I2CmasterTWI Library.
* Differences between the two libraries:
* RP6I2CmasterTWI RP6I2CmasterTWI_FLEURY
* ----------------------------------------------------------
* Dominik S. Herwald Kernel: Peter Fleury
* Interrupt-based NOT interrupt-based
* No repeated start (read functions) Repeated OR (re-)start
* Only high-level TWI functions High- AND low-level
*
* ************************************************** **************************
* CHANGELOG AND LICENSING INFORMATION CAN BE FOUND AT THE END OF THIS FILE!
* ************************************************** **************************
*/

/************************************************** ***************************/
// Includes:

#include "RP6I2CmasterTWI_FLEURY.h"

/*
* This function initializes the TWI interface! You need
* to call this first before you use the TWI interface!
* You should better use the macro I2CTWI_initMaster without __ at the
* beginning. There you can specify the SCL frequency in kHz!
* Example:
* I2CTWI_initMaster(100); // I2C Master mode with 100kHz SCL frequency
* // This calculates TWBR value automatically.
*
* __I2CTWI_initMaster(32); // I2C Master mode also with 100kHz SCL frequency
* // but directly calculated with the formula in the
* // MEGA32 datasheet.
*/
void __I2CTWI_initMaster(uint8_t twi_bitrate)
{
cli();
TWBR = twi_bitrate;
TWSR = 0x00; // DO NOT USE PRESCALER! Otherwise you need to mask the
TWDR = 0xFF; // TWSR Prescaler bits everywhere TWSR is read!
TWCR = (1<<TWEN);
TWI_statusReg.lastTransOK = 1;
sei();
TWI_statusReg.dataReady = 0; // No data
TWI_statusReg.repStart = 0; // No repeated starts
TWI_operation = I2CTWI_NO_OPERATION; // Lib not interrupt-based!
}

/************************************************** ***************************/
// TWI Event handlers
// These functions are used to receive Data or react on errors.

void I2CTWI_requestedDataReady_DUMMY(uint8_t requestID){}
static void (*I2CTWI_requestedDataReadyHandler)(uint8_t) = I2CTWI_requestedDataReady_DUMMY;
void I2CTWI_setRequestedDataReadyHandler(void (*requestedDataReadyHandler)(uint8_t))
{
I2CTWI_requestedDataReadyHandler = requestedDataReadyHandler;
}

void I2CTWI_transmissionError_DUMMY(uint8_t requestID){}
static void (*I2CTWI_transmissionErrorHandler)(uint8_t) = I2CTWI_transmissionError_DUMMY;
void I2CTWI_setTransmissionErrorHandler(void (*transmissionErrorHandler)(uint8_t))
{
I2CTWI_transmissionErrorHandler = transmissionErrorHandler;
}

/************************************************** ***************************/
// Control task

static uint8_t I2CTWI_recbuf[I2CTWI_BUFFER_REC_SIZE];
union TWI_statusReg TWI_statusReg = {0};
uint8_t TWI_TWSR_state = 0;

uint8_t I2CTWI_request_adr = 0;
uint8_t I2CTWI_request_reg = 0;
uint8_t I2CTWI_request_size = 0;
int16_t I2CTWI_requestID = 0;
uint8_t TWI_operation = I2CTWI_NO_OPERATION;


/**
* You have to call this functions frequently out of the main loop.
* It calls the event handlers above automatically if data has been received.
*/
void task_I2CTWI(void)
{
if(TWI_statusReg.dataReady) {
if(I2CTWI_requestID!=-1)
I2CTWI_requestedDataReadyHandler(I2CTWI_requestID) ;
}
uint8_t errState = I2CTWI_getState();
if(errState != 0) {
TWI_statusReg.lastTransOK = 1;
TWI_statusReg.dataReady = 0;
I2CTWI_request_adr = 0;
I2CTWI_requestID = 0;
I2CTWI_request_size = 0;
I2CTWI_transmissionErrorHandler(errState);
TWI_TWSR_state = 0;
}
}


/************************************************** ***************************/
// Request functions - you need to use requestedDataReadyHandler to receive
// the requested data...

/**
* Requests a number of Bytes from the target device. You need to set a requestID
* to be able to identify the request after the data has been received and the
* "requestedDataReady" event handler is called.
*/
void I2CTWI_requestDataFromDevice(uint8_t targetAdr, uint8_t requestID, uint8_t numberOfBytes)
{
uint8_t i;
i = i2c_start(targetAdr+I2C_WRITE);
if (i) {TWI_TWSR_state = TWSR & 0xF8; i2c_stop(); return;}
if (TWI_statusReg.repStart)
i2c_rep_start(targetAdr+I2C_READ);
else {
i2c_stop();
i2c_start(targetAdr+I2C_READ);
}
i = 1;
while (i < numberOfBytes) {
I2CTWI_recbuf[i] = i2c_readAck();
i++;
}
I2CTWI_recbuf[i] = i2c_readNak();
i2c_stop();
I2CTWI_request_adr = targetAdr;
I2CTWI_request_reg = 0;
I2CTWI_requestID = (int16_t)requestID;
I2CTWI_request_size = numberOfBytes;
TWI_statusReg.lastTransOK = 1; // Set status bits to completed successfully.
TWI_statusReg.dataReady = 1; // Requested data ready
}

/**
* Same as requestDataFromDevice, but this function first sets the register
* that has to be read and transmits the register number before!
*/
void I2CTWI_requestRegisterFromDevice(uint8_t targetAdr, uint8_t requestID, uint8_t reg, uint8_t numberOfBytes)
{
uint8_t i;
i = i2c_start(targetAdr+I2C_WRITE);
if (i) {TWI_TWSR_state = TWSR & 0xF8; i2c_stop(); return;}
i2c_write(reg);
if (TWI_statusReg.repStart)
i2c_rep_start(targetAdr+I2C_READ);
else {
i2c_stop();
i2c_start(targetAdr+I2C_READ);
}
i = 1;
while (i < numberOfBytes) {
I2CTWI_recbuf[i] = i2c_readAck();
i++;
}
I2CTWI_recbuf[i] = i2c_readNak();
i2c_stop();
I2CTWI_requestID = (int16_t)requestID;
I2CTWI_request_adr = targetAdr;
I2CTWI_request_reg = reg;
I2CTWI_request_size = numberOfBytes;
TWI_statusReg.lastTransOK = 1;
TWI_statusReg.dataReady = 1;
}

/**
* This function can be used in the requestedDataReady Handler to get the
* received data from the TWI Buffer. You need to provide a pointer to a
* buffer which is large enough to hold all received data.
* You can specify the number of bytes you want to read out of the buffer
* with the msgSize parameter.
* It does not make sense to use this function anywhere else as you
* can not guarantee what is in the reception buffer...
*/
void I2CTWI_getReceivedData(uint8_t *msg, uint8_t msgSize)
{
uint8_t i = 0;
if(TWI_statusReg.dataReady) { // Requested data ready?
for(; i < msgSize; i++)
msg[i] = I2CTWI_recbuf[i+1];
TWI_statusReg.dataReady = 0;
}
}

/**
* This function returns the last TWI State / Error State.
*/
uint8_t I2CTWI_getState(void)
{
return (TWI_TWSR_state); // Return error state.
}

/************************************************** ***************************/
// Read functions:

/**
* Reads "numberOfBytes" from "targetAdr" Register "reg" into "messageBuffer".
* If the slave device supports auto increment, then it reads all subsequent registers of course!
*/
void I2CTWI_readRegisters(uint8_t targetAdr, uint8_t reg, uint8_t * messageBuffer, uint8_t numberOfBytes)
{
uint8_t i;
i = i2c_start(targetAdr+I2C_WRITE);
if (i) {TWI_TWSR_state = TWSR & 0xF8; i2c_stop(); return;}
i2c_write(reg);
if (TWI_statusReg.repStart)
i2c_rep_start(targetAdr+I2C_READ);
else {
i2c_stop();
i2c_start(targetAdr+I2C_READ);
}
i = 1;
while (i < numberOfBytes) {
I2CTWI_recbuf[i] = i2c_readAck();
i++;
}
I2CTWI_recbuf[i] = i2c_readNak();
i2c_stop();
TWI_statusReg.lastTransOK = 1;
TWI_statusReg.dataReady = 1;
I2CTWI_requestID = -1;
I2CTWI_getReceivedData(&messageBuffer[0], numberOfBytes+1);
}

/**
* Reads "numberOfRegs" from "targetAdr" Register "reg" into "messageBuffer".
* If the slave device supports auto increment, then it reads all subsequent registers of course!
*/
void I2CTWI_readWordRegisters(uint8_t targetAdr, uint8_t reg, uint8_t * messageBuffer, uint8_t numberOfRegs)
{
uint8_t i;
i = i2c_start(targetAdr+I2C_WRITE);
if (i) {TWI_TWSR_state = TWSR & 0xF8; i2c_stop(); return;}
i2c_write(reg);
if (TWI_statusReg.repStart)
i2c_rep_start(targetAdr+I2C_READ);
else {
i2c_stop();
i2c_start(targetAdr+I2C_READ);
}
i = 1;
while (i < (numberOfRegs<<1)) {
I2CTWI_recbuf[i] = i2c_readAck();
i++;
}
I2CTWI_recbuf[i] = i2c_readNak();
i2c_stop();
TWI_statusReg.lastTransOK = 1;
TWI_statusReg.dataReady = 1;
I2CTWI_requestID = -1;
I2CTWI_getReceivedData(&messageBuffer[0], (numberOfRegs<<1)+1);
}

/**
* Same as readRegisters, but you need to make sure which register to read yourself - if there
* are any registers at all in your slave device.
*
*/
void I2CTWI_readBytes(uint8_t targetAdr, uint8_t * messageBuffer, uint8_t numberOfBytes)
{
uint8_t i;
i = i2c_start(targetAdr+I2C_WRITE);
if (i) {TWI_TWSR_state = TWSR & 0xF8; i2c_stop(); return;}
if (TWI_statusReg.repStart)
i2c_rep_start(targetAdr+I2C_READ);
else {
i2c_stop();
i2c_start(targetAdr+I2C_READ);
}
i = 1;
while (i < numberOfBytes) {
I2CTWI_recbuf[i] = i2c_readAck();
i++;
}
I2CTWI_recbuf[i] = i2c_readNak();
i2c_stop();
TWI_statusReg.lastTransOK = 1;
TWI_statusReg.dataReady = 1;
I2CTWI_requestID = -1;
I2CTWI_getReceivedData(&messageBuffer[0], numberOfBytes+1);
}

/**
* Reads a single byte from the slave device.
*/
uint8_t I2CTWI_readByte(uint8_t targetAdr)
{
uint8_t i;
i = i2c_start(targetAdr+I2C_WRITE);
if (i) {TWI_TWSR_state = TWSR & 0xF8; i2c_stop(); return 0;}
if (TWI_statusReg.repStart)
i2c_rep_start(targetAdr+I2C_READ);
else {
i2c_stop();
i2c_start(targetAdr+I2C_READ);
}
I2CTWI_recbuf[1] = i2c_readNak();
i2c_stop();
TWI_statusReg.lastTransOK = 1;
TWI_statusReg.dataReady = 0;
I2CTWI_requestID = -1;
return I2CTWI_recbuf[1];
}

/************************************************** ***************************/
// Transmission functions

/**
* Transmits a single byte to a slave device. It waits until the
* transmission is finished (it blocks the normal program flow!)!
*/
void I2CTWI_transmitByte(uint8_t targetAdr, uint8_t data)
{
uint8_t i;
i = i2c_start(targetAdr+I2C_WRITE);
if (i) {TWI_TWSR_state = TWSR & 0xF8; i2c_stop(); return;}
i2c_write(data);
i2c_stop();
TWI_statusReg.lastTransOK = 0;
TWI_statusReg.dataReady = 0;
}

/**
* This is just the same as transmitByte, but you can pass 2 Bytes to
* this function which are then transferred.
*/
void I2CTWI_transmit2Bytes(uint8_t targetAdr, uint8_t data1, uint8_t data2)
{
uint8_t i;
i = i2c_start(targetAdr+I2C_WRITE);
if (i) {TWI_TWSR_state = TWSR & 0xF8; i2c_stop(); return;}
i2c_write(data1);
i2c_write(data2);
i2c_stop();
TWI_statusReg.lastTransOK = 0;
TWI_statusReg.dataReady = 0;
}

/**
* Transmits 3 Bytes to the slave.
*/
void I2CTWI_transmit3Bytes(uint8_t targetAdr, uint8_t data1, uint8_t data2, uint8_t data3)
{
uint8_t i;
i = i2c_start(targetAdr+I2C_WRITE);
if (i) {TWI_TWSR_state = TWSR & 0xF8; i2c_stop(); return;}
i2c_write(data1);
i2c_write(data2);
i2c_write(data3);
i2c_stop();
TWI_statusReg.lastTransOK = 0;
TWI_statusReg.dataReady = 0;
}

/**
* Transmits 4 Bytes to the slave.
*/
void I2CTWI_transmit4Bytes(uint8_t targetAdr, uint8_t data1, uint8_t data2, uint8_t data3, uint8_t data4)
{
uint8_t i;
i = i2c_start(targetAdr+I2C_WRITE);
if (i) {TWI_TWSR_state = TWSR & 0xF8; i2c_stop(); return;}
i2c_write(data1);
i2c_write(data2);
i2c_write(data3);
i2c_write(data4);
i2c_stop();
TWI_statusReg.lastTransOK = 0;
TWI_statusReg.dataReady = 0;
}


/**
* Transmits "numberOfBytes" Bytes to the Slave device. The Bytes need to be
* in the Buffer "msg". Otherwise it is just the same as the other transmit functions.
*/
void I2CTWI_transmitBytes(uint8_t targetAdr, uint8_t *msg, uint8_t numberOfBytes)
{
uint8_t i;
i = i2c_start(targetAdr+I2C_WRITE);
if (i) {TWI_TWSR_state = TWSR & 0xF8; i2c_stop(); return;}
numberOfBytes++;
i = 0;
for(; i < numberOfBytes; i++)
i2c_write(msg[i]);
i2c_stop();
TWI_statusReg.lastTransOK = 0;
TWI_statusReg.dataReady = 0;
}

/************************************************** ****************************
* Additional info
* ************************************************** **************************
* Changelog:
* - v. 1.1 4.09.2012 by JM3 Engineering
* - NEW: added support for reading 16Bit registers
* - v. 1.0 (initial release) 16.05.2007 by Dominik S. Herwald
*
* ************************************************** **************************
* Bugs, feedback, questions and modifications can be posted on the AREXX Forum
* on http://www.arexx.com/forum/ !
* Of course you can also write us an e-mail to: info@arexx.nl
* AREXX Engineering may publish updates from time to time on AREXX.com!
* ************************************************** **************************
* - LICENSE -
* GNU GPL v2 (http://www.gnu.org/licenses/gpl.txt, a local copy can be found
* on the RP6 CD in the RP6 sorce code folders!)
* This program is free software. You can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
* ************************************************** **************************
*/

/************************************************** ***************************/
// EOF


- - - Aktualisiert - - -

Was ist in der neuen I2C Master Library für das RP6 System neu/anders:

1. Die neue Mantel Lib ist nicht mehr Interrupt-basiert und hat daher ein anderes Timing.
2. Darüber hinaus ist sie weitgehend kompatibel zur Original Lib von SlyD und wurde mit allen Original Demos getestet.
3. Lese-Funktionen können wahlweise mit I2C Start oder Repeated Start ausgeführt werden.
4. Neben den vertrauten I2C-Schreib-Lese-Funktionen, die in der RP6 Anleitung beschrieben werden, kann man alle Funktionen der Fleury Lib nutzen.
Eine Anleitung dazu gibt's hier (http://homepage.hispeed.ch/peterfleury/group__pfleury__ic2master.html).

Was muss man zusätzlich noch wissen:

Die Peter Fleury I2C Master Library muss man von dem oben angegebenen Link herunterladen und die Dateien "twimaster.c" und "i2cmaster.h" ins Verzeichnis /../RP6Lib/RP6common kopieren. Da hinein kommen natürlich auch die Dateien der Mantel Lib.

Die neue Lib muss mit:
SRC += $(RP6_LIB_PATH)/RP6common/twimaster.c
SRC += $(RP6_LIB_PATH)/RP6common/RP6I2CmasterTWI_FLEURY.c
... im makefile eingebunden werden und mit:
#include "RP6I2CmasterTWI_FLEURY.h"
... ins Hauptprogramm eingebunden werden.

Das ist alles. (Fast) alle Programme des RP6 Systems müßten mit der neuen Lib laufen.

Die TWI Lesefunktionen erfolgen (wie beim Original) mit (Neu-)Start.
Braucht man im Einzelfall den Repeated Start, setzt man einfach vor die jeweilige Lesefunktion:
I2CTWI_repStart();
Diese Einstellung bleibt dann dauerhaft erhalten bis man mit:
I2CTWI_start();
... wieder auf die Standardeinstellung (Start) umstellt.

Viel Erfolg!