Code:
/* *************************************
TWI Lib Version 5 oder so
bhm 2006
************************************** */
// bislang keinmultimaster support
// keine Garanie für irgendwas
// Bemerkungen, Fehlerreports usw willkommen
#ifndef _TWILIB_
#define _TWILIB_ 1
#include <avr/io.h> //Zugriff auf IO's des Controllers
#include <stdint.h>
#include <compat/twi.h>
void init_Master (void) {
TWSR &= ~(_BV(TWPS0) | _BV(TWPS1)); //0b11111100: Prescaler auf 1 setzen, Bit 1 und 0 auf 0
TWBR = 0x0A; //Bitrate auf 10 setzen, gibt 220kHz Bustakt bei 8MHz
}
void init_Slave (uint8_t SlvAdd) {
TWAR = SlvAdd; // eigene Address, hier ohne general call
TWCR = _BV(TWEA) | _BV(TWEN) | _BV(TWINT); //slave receive, TWEA > ACK,
}
void waitTWINT (void) {
uint32_t m=0,mmax=F_CPU; //zZt einfach eine große Zahl
while (bit_is_clear(TWCR, TWINT)) {
if (m++ > mmax) return; // bricht waitTWINT ab, TW_Status enthält dann TW_NO_INFO
}
}
// *********** MasterTransmitter *************
// Daten in *Data, lenmax #Daten senden, MT #gesendete Daten
uint8_t MT (uint8_t SlvAdd, uint8_t *Data, uint8_t lenmax) {
uint8_t len=1;
TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN); //sende start
waitTWINT();
if ((TW_STATUS != TW_START) && (TW_STATUS != TW_REP_START)){ // chk Start | repeated start
goto ENDE;
}
TWDR = SlvAdd + TW_WRITE; //Addresse des Slaves angeben, SLA+W
TWCR = _BV(TWINT) | _BV(TWEN); // sende sla_w
waitTWINT();
if (TW_STATUS != TW_MT_SLA_ACK) { // chk sla_ack
goto STOP;
}
do {
TWDR = *Data++; // Datum laden
TWCR = _BV(TWINT) | _BV(TWEN); // sende Datum
waitTWINT();
if (TW_STATUS != TW_MT_DATA_ACK) { // chk data_ack
goto STOP;
}
} while (len++<lenmax);
STOP:
TWCR = _BV(TWINT) | _BV(TWEN) | _BV(TWSTO); // sende stop, kein warten auf TWINT
ENDE:
return len-1;
}
// *********** MasterReceiver *************
// empfangene Daten nach *Data, Speicher muss bereitgestellt sein,
// lenmax #Daten empfangen, MR #empfangene Daten
uint8_t MR (uint8_t SlvAdd, uint8_t *Data, uint8_t lenmax) {
uint8_t len=1;
TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN); //sende start
waitTWINT();
if ((TW_STATUS != TW_START) && (TW_STATUS != TW_REP_START)){ // chk Start | repeated start
goto ENDE;
}
TWDR = SlvAdd + TW_READ; //Addresse des Slaves angeben, SLA+r
TWCR = _BV(TWINT) | _BV(TWEN); // sende sla_r
waitTWINT();
if (TW_STATUS != TW_MR_SLA_ACK) { // chk sla_ack
goto STOP;
}
while (1) { // endlos, verlassen via break in if TW_Status
if (len<lenmax) {
TWCR = _BV(TWEA) | _BV(TWEN) | _BV(TWINT); //receive, ACK,
} else {
TWCR = _BV(TWEN) | _BV(TWINT); //receive, NACK,
}
waitTWINT();
if (TW_STATUS != TW_MR_DATA_ACK) break; // LOOP VERLASSEN
*Data++ = TWDR; len++; // Daten verarbeitet
}
if (TW_STATUS == TW_MR_DATA_NACK) {
*Data++ = TWDR; len++; // Daten verarbeitet
goto STOP;
}
STOP:
TWCR = _BV(TWINT) | _BV(TWEN) | _BV(TWSTO); // sende stop, kein warten auf TWINT
ENDE:
return len-1;
}
// *********** SlaveReceiver *************
// empfangene Daten nach *Data, Speicher muss bereitgestellt sein,
// lenmax #Daten empfangen, SR #empfangene Daten
uint8_t SR (uint8_t *Data, uint8_t lenmax) {
uint8_t len=1; // lenmax >= 1, min ein Byte empfangen!
// auf SLA warten
while (bit_is_clear(TWCR, TWINT)); // beliebig lange warten oder pollen
// jetzt geht's los
if (TW_STATUS != TW_SR_SLA_ACK) { // chk SLA+W
goto STOP;
}
while (1) { // endlos, verlassen via break in if TW_Status
if (len<lenmax) {
TWCR = _BV(TWEA) | _BV(TWEN) | _BV(TWINT); //slave receive, TWEA > ACK,
} else {
TWCR = _BV(TWEN) | _BV(TWINT); //slave receive, TWEA > NACK,
}
waitTWINT();
if (TW_STATUS != TW_SR_DATA_ACK) break; // LOOP VERLASSEN
*Data++ = TWDR; len++; // Daten verarbeitet
}
if (TW_STATUS == TW_SR_DATA_NACK) { // Datum mit NACK beantwortet
*Data = TWDR; len++; // im Prinzip noch ein Datum verfügbar
}
STOP: // (TW_STATUS == TW_SR_STOP) einzig anderer möglicher Status, von ARBs abgesehen
TWCR = _BV(TWEA) | _BV(TWEN) | _BV(TWINT); //slave receive, TWEA > ACK,
return len-1;
}
// *********** SlaveTransmitter *************
// Daten in *Data, lenmax #Daten senden, ST #gesendete Daten
uint8_t ST (uint8_t *Data, uint8_t lenmax) {
uint8_t len=0; // lenmax >= 1, min ein Byte senden!
// auf SLA warten
while (bit_is_clear(TWCR, TWINT)); // beliebig lange warten oder pollen
// jetzt geht's los
if (TW_STATUS != TW_ST_SLA_ACK) { // chk SLA+R
goto STOP;
}
do {
TWDR = *Data++; len++;
if (len<lenmax) {
TWCR = _BV(TWEA) | _BV(TWEN) | _BV(TWINT);
} else {
TWCR = _BV(TWEN) | _BV(TWINT);
}
waitTWINT();
} while (TW_STATUS == TW_ST_DATA_ACK);
STOP:
TWCR = _BV(TWEA) | _BV(TWEN) | _BV(TWINT); //slave receive, TWEA > ACK,
return len;
}
#endif
Bei den versprochenen Links habe ich immernoch nicht die Zeit gefunden ...
Lesezeichen