00001 /**************************************************************************** 00002 Title: Access serial EEPROM 24C02 using I2C interace 00003 Author: Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury 00004 File: $Id: test_i2cmaster.c,v 1.2 2003/12/06 17:07:18 peter Exp $ 00005 Software: AVR-GCC 3.3 00006 Hardware: AT90S8515 at 4 Mhz, any AVR device can be used 00007 00008 Description: 00009 This example shows how the I2C library i2cmaster.S can be used to 00010 access a serial eeprom. 00011 Based on Atmel Application Note AVR300, adapted to AVR-GCC C interface 00012 00013 *****************************************************************************/ 00014 #include <avr/io.h> 00015 #include <avr/interrupt.h> // dient zur behandlung der Interrupts 00016 #include <util/twi.h> // enthält z.B. die Bezeichnungen für die Statuscodes in TWSR 00017 #include <stdint.h> // definiert den Datentyp uint8_t 00018 00019 /******************** 00020 * DEFINES * 00021 ********************/ 00022 #define SLAVE_ADD 0x50 // device address 00023 #define REGISTER_ANZ 7 // anzahl der Slaveregister 00024 00025 00026 //Je nach Statuscode in TWSR müssen verschiedene Bitmuster in TWCR geschreiben werden(siehe Tabellen im Datenblatt!). 00027 //Makros für die verwendeten Bitmuster: 00028 //ACK nach empfangenen Daten senden/ ACK nach gesendeten Daten erwarten 00029 #define TWCR_ACK TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(0<<TWWC); 00030 //NACK nach empfangenen Daten senden/ NACK nach gesendeten Daten erwarten 00031 #define TWCR_NACK TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(0<<TWWC); 00032 //switched to the non adressed slave mode... 00033 #define TWCR_RESET TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(0<<TWWC); 00034 //Die Bitmuster für TWCR_ACK und TWCR_RESET sind gleich. Dies ist kein Fehler und dient nur der Übersicht! 00035 00036 /**************************** 00037 * private globale Variablen * 00038 ****************************/ 00039 volatile uint8_t register_adr; //"Adressregister" mit adresse des gewählten registers 00040 00041 // statusregister für TWI 00042 volatile struct { 00043 unsigned bFirstAccess:1; // erster Zugriff, Registerposition setzen 00044 } twi_status; 00045 00046 // Adressen der Register 00047 enum enRegisterAdr { INBuffer=1, OUTBuffer, INCounter, OUTCounter, PaketReqID, Status, GPIO }; 00048 00049 typedef struct 00050 { 00051 uint8_t id; // ID des Tabelleneintrages (muss eindeutig sein) 00052 char titel[TITELLANG+1]; // Titel des Menüs 00053 }tstMenue; 00054 00055 typedef struct 00056 { 00057 uint8_t id; // ID des Elementes 00058 uint8_t pos; // Position innerhalb des Menüs 00059 void* element; // Pointer auf das Element 00060 enum enElemtenTypen elementType; // Typ des Elementes 00061 uint8_t parent; // übergeortnetes Elemente 00062 }tstZeile; 00063 00064 /******************************* 00065 * private Funktions prototypen * 00066 ********************************/ 00067 void init_twi_slave (uint8_t adr); 00068 00069 /**************** 00070 * main * 00071 ****************/ 00072 int main(void) 00073 { 00074 init_twi_slave(SLAVE_ADD); 00075 sei(); 00076 while(1); 00077 } 00078 00079 00080 /****************************************************************************/ 00088 void init_twi_slave (uint8_t adr) 00089 { 00090 TWAR= adr; // Adresse setzen 00091 TWCR &= ~(1<<TWSTA)|(1<<TWSTO); // START und STOP deaktivieren 00092 TWCR|= (1<<TWEA) | (1<<TWEN) | (1<<TWIE); // aktivieren von: Acknowledge, Interrupt und TWI 00093 register_adr=0x00; // registeradresse zurücksetzen 00094 twi_status.bFirstAccess = 1; // erster zugriff nach stop 00095 00096 DDRB = 0xff; 00097 PORTB = 0x00; 00098 DDRA = 0xff; 00099 PORTA = 0x00; 00100 } 00101 00102 00103 /****************************************************************************/ 00110 ISR(TWI_vect) 00111 { 00112 uint8_t data = 0; 00113 switch (TW_STATUS) // TWI-Statusregister prüfen und nötige Aktion bestimmen 00114 { 00115 case TW_SR_SLA_ACK: // 0x60 Slave Receiver, wurde adressiert 00116 TWCR_ACK; // nächstes Datenbyte empfangen, ACK danach 00117 PORTA = 0xFC; 00118 break; 00119 00120 /*** Daten Empfangen ****/ 00121 case TW_SR_DATA_ACK: // 0x80 Slave Receiver,Daten empfangen 00122 data=TWDR; // Empfangene Daten auslesen 00123 if(twi_status.bFirstAccess) // erte Adressierung nach STOP 00124 { 00125 register_adr = data;// Empfangene Register Adresse speciern 00126 PORTA = register_adr; 00127 twi_status.bFirstAccess = 0; 00128 } 00129 else 00130 { 00131 switch( register_adr) 00132 { 00133 case INBuffer: 00134 case OUTBuffer: 00135 case INCounter: 00136 case OUTCounter: 00137 case PaketReqID: 00138 case Status: 00139 case GPIO: 00140 PORTB = data; 00141 break; 00142 default: 00143 PORTB = 0xff; 00144 } 00145 register_adr++; 00146 } 00147 TWCR_ACK; 00148 break; 00149 00150 /*** Daten versenden ***/ 00151 case TW_ST_SLA_ACK: // 0xA8 Slave Transmitter wurde adressiert 00152 case TW_ST_DATA_ACK: // 0xB8 Slave Transmitter, weitere Daten wurden angefordert 00153 TWCR_ACK; 00154 break; 00155 00156 case TW_ST_DATA_NACK: // 0xC0 Keine Daten mehr gefordert 00157 case TW_SR_DATA_NACK: // 0x88 Keine Daten weiteren empfangen 00158 case TW_ST_LAST_DATA: // 0xC8 Last data byte in TWDR has been transmitted (TWEA = “0”); ACK has been received 00159 case TW_SR_STOP: // 0xA0 STOP empfangen 00160 default: // alle anderen codes 00161 twi_status.bFirstAccess = 1; 00162 TWCR_RESET; // Übertragung beenden, warten bis zur nächsten Adressierung 00163 } // end switch 00164 }// end ISR 00165 00166