PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : I2C Fehlerteufel



Fro
05.08.2006, 17:32
Servus alle miteinander!

Ich setze mich gerade mit 2Atmega8 auseinander und zwar möchte ich das die beiden miteinander kommunizieren, der ein als Slave und der andere als Master. (Logisch ich weiß ;-))

So mein Problem ist aber, das das nicht funktioniert. Ich hab jetzt zur Problemlösung folgendes gemacht. Hab LEDs an Ports angeschloßen um zu sehen, ob der uC irgendwo "hängt" oder nicht weiterkommt. Also LED an -> Programm läuft etc.

Mit Hilfe dieser neandertaler Lösung bin ich jetzt soweit dass auf meinem Master die Software zu funktionieren scheint. Tue ich das gleiche beim Slave stellt sich heraus, dass die Interruptroutine für den TWI Bus nie aufgerufen wird. Hab aber interrupts schon über sei(); enabled. :-k

Hab ich irgendwas im Konzept eventuell bisher falsh verstanden? Wenn der Master das Start Signal sendet müsste das doch den Interrupt beim Slave auslösen, oder?

Nächstes. Reichen 3,7V an Spannung an den 2 Busleitungen?

Hilfe wäre nett...

Florian
05.08.2006, 19:10
Hallo Fro!
Leider kennen wir Deinen Code nicht!
In welcher Sprache programmierst Du?
Bitte hilf uns weiter, damit wir Dir helfen können!

Viele Grüße
Florian

Fro
05.08.2006, 19:27
Oh entschuldigug O:)

Code für den Master wird bald nach gereicht, da ich an einem anderen PC programmiere. Ich programmiere in C mit WinAVR. Hier aber schonmal der Code für den I2C Bus für den Slave Atmega, welchen ich glaube ich hier aus dem Forum gesaugt habe...


#include "i2cbus.h"

unsigned char i2c_read_byte (void)
{
/*send content of TWDR; TWEA = enable ACK*/
TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
/*wait, until byte has been received --> ACK*/
while (!(TWCR & (1<<TWINT)));
return TWDR;
}

unsigned char i2c_receive (void)
{
unsigned char value = 0;
value = i2c_read_byte ();
return value;
}



Aufrufen tue ich dass dann folgendermaßen:


SIGNAL(SIG_2WIRE_SERIAL){
variablexyz = i2receive();
PORTB = 0xFF //LED am Slave anschalten;}

Die "variablexyz" habe ich vorher als volatile deklariert und initialisiert.

Fro
05.08.2006, 19:50
Kleiner Nachtrag noch, ich hab vorher noch im Code für den Slave TWI über das nötige Bit natürlich enablet und eine Slave Adresse zugewiesen...

uwegw
05.08.2006, 20:54
Merkwürdiges Programm deinerseits. Normalerweise fragt man im Interrupt erst mal das Statusregister TWSR ab und entscheidet nach dessen Inhalt, was gemacht werden muss [steht in ner großen Tabelle im Datenblatt]

Mein Slave-Code:
EDIT: Programm ins Wiki verschoben!
https://www.roboternetz.de/wissen/index.php/TWI_Slave_mit_avr-gcc


Ich arbeite mit nem Buffer, der so wie ein gewöhnliches I2C-Eeprom vom Master beschrieben wird.

Fro
06.08.2006, 00:35
Okay, also ich sehe ich habe das Konzept wie der I2C abläuft noch nicht wirklich ganz verstanden. Aber deswegen bastel ich auch :-)

Ich wollte einfach ein ganz rudimentäres Programm um schreiben um einfach zu verstehen wie das abläuft. Es soll einfach nur ein Byte übertragen werden und damit hat sich das...

Ich werde es mal mit deinem Code probieren und sehen wie ich vorankomme.

Danke für die Hilfe erstmal!

uwegw
06.08.2006, 11:26
Les dir mal die Artikel TWI und I2C im Wiki durch, dann dürfte das Prinzip von I2V schon klar werden.

Fro
06.08.2006, 12:34
Hab ich schon mehrmals getan, aber zwischen der grauen Theorie und dem eigentlich programmieren liegen für mich dann doch schon Welten....aber ich versuch mich durchzubeißen.

Hier jetzt der I2Ccode für den Master:

#include "i2cbus.h"


void i2c_send_init (void)
{
/*setting for 10Mhz and SCL 100kHz -> TWBR factor = 42
SCL = CPU/(16+2*TWBR*4)*/
TWBR = 0x2A;
}

void i2c_receive_init (void){
/*Hier wird der Empfang für den Atmega als Slave deklariert. DAzu muss TWAR gesetzt werden*/
TWAR = 0x02; //Adresse des Slaves ist 0x02

//Dazu muss noch TWEN gesetzt werden, um TWI zu erlaubgen
TWCR = (1<<TWEA)|(1<<TWEN);
}

unsigned char i2c_send_start (void)
{
/*writing a one to TWINT clears it, TWSTA=Start, TWEN=TWI-enable*/
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
/*wait, until start condition has been sent --> ACK*/
while (!(TWCR & (1<<TWINT)));
return TWSR;
}


void i2c_send_stop (void)
{
/*writing a one to TWINT clears it, TWSTO=Stop, TWEN=TWI-enable*/
TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN);
}


unsigned char i2c_send_add_rw (unsigned char address, unsigned char rw)
{
/*address can be 0 .. 3; rw=0 --> write, rw=1 --> read*/
unsigned char addr_byte = 0;
/*shift address one bit left*/
addr_byte = address << 1;
/*set RW-Bit, if necessary*/
addr_byte |= rw;
/*0b10100xxx --> address of EEPROM*/
addr_byte |= 0xA0;
/*TWDR contains byte to send*/
TWDR = addr_byte;
/*send content of TWDR*/
TWCR = (1<<TWINT) | (1<<TWEN);

/*wait, until address has been sent --> ACK*/
while (!(TWCR & (1<<TWINT)));

return TWSR;
}


unsigned char i2c_send_byte (unsigned char byte)
{
/*TWDR contains byte to send*/
TWDR = byte;
/*send content of TWDR*/
TWCR = (1<<TWINT) | (1<<TWEN);

/*wait, until byte has been sent --> ACK*/
while (!(TWCR & (1<<TWINT)));

return TWSR;
}


unsigned char i2c_read_byte (void)
{
/*send content of TWDR; TWEA = enable ACK*/
TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
/*wait, until byte has been received --> ACK*/
while (!(TWCR & (1<<TWINT)));
return TWDR;
}

void i2c_send (unsigned char deviceadd, unsigned char value)
{
/*initialization*/
i2c_send_init ();
PORTB |= (1<<PB1);
/*start condition*/
i2c_send_start ();

/*send device address an R/W*/
i2c_send_add_rw (deviceadd, 0);

i2c_send_byte (value);

/*send stop condition*/
i2c_send_stop ();
PORTB |= (1<<PB2);
}

unsigned char i2c_receive (void)
{
unsigned char value = 0;
/*initialization*/
i2c_receive_init ();

value = i2c_read_byte ();

return value;
}


das ganze wird dann aufgerufen über
#include <avr/io.h>
#include <avr/interrupt.h>
#include "i2c/i2cbus.h"
#include <compat/twi.h>




void main(void){
DDRD = 0x00; //PORTD als Eingang
PORTD = 0xFF; // Pull-Up Widerstände an Port D aktiviert -> Schalter als Active-Low ausführen

unsigned char goal1 = 23;
timer_init();


for(;;){

if (!(PIND & (1 << PD7))){

goal1++;
i2c_send(0x02, goal1);
}


}
}
//end of bedienfeld.c

uwegw
06.08.2006, 12:37
für den master nehm ich die lib von p. fleury. Die funktioniert gut, und so muss man sich nur noch mit den slave rumschlagen...

Fro
06.08.2006, 14:11
Also ich hab jetzt mal die Master-lib von p.fleury verwendet und den Slave-Code von uwegw. In twimaster.c habe ich die Taktfrequenz angepasst und in i2cmaster.S die Ports für TWI auf PORTC umgestellt.

Ich bekomme jedoch beim compilieren ein menge fehlermeldungen, die sich so äußern:

Linking: bedienfeld.elf
avr-gcc -mmcu=atmega8 -I. -gdwarf-2 -DF_CPU=10000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=bedienfeld.o -std=gnu99 -MD -MP -MF .dep/bedienfeld.elf.d bedienfeld.o i2cmaster/i2cmaster.S i2cmaster/twimaster.o C:/WinAVR/avr/include/avr/version.h --output bedienfeld.elf -Wl,-Map=bedienfeld.map,--cref -lm
C:/WinAVR/avr/include/stdint.h: Assembler messages:
C:/WinAVR/avr/include/stdint.h:116: Error: unknown opcode `typedef'
C:/WinAVR/avr/include/stdint.h:117: Error: unknown opcode `typedef'
C:/WinAVR/avr/include/stdint.h:118: Error: unknown opcode `typedef'
C:/WinAVR/avr/include/stdint.h:119: Error: unknown opcode `typedef'
C:/WinAVR/avr/include/stdint.h:120: Error: unknown opcode `typedef'
C:/WinAVR/avr/include/stdint.h:121: Error: unknown opcode `typedef'
C:/WinAVR/avr/include/stdint.h:122: Error: unknown opcode `typedef'
C:/WinAVR/avr/include/stdint.h:123: Error: unknown opcode `typedef'
C:/WinAVR/avr/include/stdint.h:135: Error: unknown opcode `typedef'
C:/WinAVR/avr/include/stdint.h:140: Error: unknown opcode `typedef'
C:/WinAVR/avr/include/stdint.h:152: Error: unknown opcode `typedef'
C:/WinAVR/avr/include/stdint.h:157: Error: unknown opcode `typedef'
C:/WinAVR/avr/include/stdint.h:162: Error: unknown opcode `typedef'
C:/WinAVR/avr/include/stdint.h:167: Error: unknown opcode `typedef'
C:/WinAVR/avr/include/stdint.h:172: Error: unknown opcode `typedef'
C:/WinAVR/avr/include/stdint.h:177: Error: unknown opcode `typedef'
C:/WinAVR/avr/include/stdint.h:182: Error: unknown opcode `typedef'
C:/WinAVR/avr/include/stdint.h:187: Error: unknown opcode `typedef'
C:/WinAVR/avr/include/stdint.h:200: Error: unknown opcode `typedef'
C:/WinAVR/avr/include/stdint.h:205: Error: unknown opcode `typedef'
C:/WinAVR/avr/include/stdint.h:210: Error: unknown opcode `typedef'
C:/WinAVR/avr/include/stdint.h:215: Error: unknown opcode `typedef'
C:/WinAVR/avr/include/stdint.h:220: Error: unknown opcode `typedef'
C:/WinAVR/avr/include/stdint.h:225: Error: unknown opcode `typedef'
C:/WinAVR/avr/include/stdint.h:230: Error: unknown opcode `typedef'
C:/WinAVR/avr/include/stdint.h:235: Error: unknown opcode `typedef'
C:/WinAVR/avr/include/stdint.h:249: Error: unknown opcode `typedef'
C:/WinAVR/avr/include/stdint.h:254: Error: unknown opcode `typedef'
C:/WinAVR/avr/include/inttypes.h:76: Error: unknown opcode `typedef'
C:/WinAVR/avr/include/inttypes.h:80: Error: unknown opcode `typedef'
i2cmaster/i2cmaster.S:94: Error: bad expression
i2cmaster/i2cmaster.S:94: Error: missing ')'
i2cmaster/i2cmaster.S:94: Error: missing ')'
i2cmaster/i2cmaster.S:94: Error: missing ')'
i2cmaster/i2cmaster.S:94: Error: missing ')'
i2cmaster/i2cmaster.S:94: Error: missing ')'
i2cmaster/i2cmaster.S:94: Error: constant value required
i2cmaster/i2cmaster.S:94: Error: `,' required
i2cmaster/i2cmaster.S:94: Error: constant value required
i2cmaster/i2cmaster.S:94: Error: garbage at end of line
i2cmaster/i2cmaster.S:95: Error: bad expression
i2cmaster/i2cmaster.S:95: Error: missing ')'
i2cmaster/i2cmaster.S:95: Error: missing ')'
i2cmaster/i2cmaster.S:95: Error: missing ')'
i2cmaster/i2cmaster.S:95: Error: missing ')'
i2cmaster/i2cmaster.S:95: Error: missing ')'
i2cmaster/i2cmaster.S:95: Error: constant value required
i2cmaster/i2cmaster.S:95: Error: `,' required
i2cmaster/i2cmaster.S:95: Error: constant value required
i2cmaster/i2cmaster.S:95: Error: garbage at end of line
i2cmaster/i2cmaster.S:96: Error: bad expression
i2cmaster/i2cmaster.S:96: Error: missing ')'
i2cmaster/i2cmaster.S:96: Error: missing ')'
i2cmaster/i2cmaster.S:96: Error: missing ')'
i2cmaster/i2cmaster.S:96: Error: missing ')'
i2cmaster/i2cmaster.S:96: Error: constant value required
i2cmaster/i2cmaster.S:96: Error: `,' required
i2cmaster/i2cmaster.S:96: Error: constant value required
i2cmaster/i2cmaster.S:96: Error: garbage at end of line
i2cmaster/i2cmaster.S:97: Error: bad expression
i2cmaster/i2cmaster.S:97: Error: missing ')'
i2cmaster/i2cmaster.S:97: Error: missing ')'
i2cmaster/i2cmaster.S:97: Error: missing ')'
i2cmaster/i2cmaster.S:97: Error: missing ')'
i2cmaster/i2cmaster.S:97: Error: constant value required
i2cmaster/i2cmaster.S:97: Error: `,' required
i2cmaster/i2cmaster.S:97: Error: constant value required
i2cmaster/i2cmaster.S:97: Error: garbage at end of line
i2cmaster/i2cmaster.S:113: Error: bad expression
i2cmaster/i2cmaster.S:113: Error: missing ')'
i2cmaster/i2cmaster.S:113: Error: missing ')'
i2cmaster/i2cmaster.S:113: Error: missing ')'
i2cmaster/i2cmaster.S:113: Error: missing ')'
i2cmaster/i2cmaster.S:113: Error: missing ')'
i2cmaster/i2cmaster.S:113: Error: constant value required
i2cmaster/i2cmaster.S:113: Error: `,' required
i2cmaster/i2cmaster.S:113: Error: constant value required
i2cmaster/i2cmaster.S:113: Error: garbage at end of line
i2cmaster/i2cmaster.S:132: Error: bad expression
i2cmaster/i2cmaster.S:132: Error: missing ')'
i2cmaster/i2cmaster.S:132: Error: missing ')'
i2cmaster/i2cmaster.S:132: Error: missing ')'
i2cmaster/i2cmaster.S:132: Error: missing ')'
i2cmaster/i2cmaster.S:132: Error: missing ')'
i2cmaster/i2cmaster.S:132: Error: constant value required
i2cmaster/i2cmaster.S:132: Error: `,' required
i2cmaster/i2cmaster.S:132: Error: constant value required
i2cmaster/i2cmaster.S:132: Error: garbage at end of line
i2cmaster/i2cmaster.S:134: Error: bad expression
i2cmaster/i2cmaster.S:134: Error: missing ')'
i2cmaster/i2cmaster.S:134: Error: missing ')'
i2cmaster/i2cmaster.S:134: Error: missing ')'
i2cmaster/i2cmaster.S:134: Error: missing ')'
i2cmaster/i2cmaster.S:134: Error: missing ')'
i2cmaster/i2cmaster.S:134: Error: constant value required
i2cmaster/i2cmaster.S:134: Error: `,' required
i2cmaster/i2cmaster.S:134: Error: constant value required
i2cmaster/i2cmaster.S:134: Error: garbage at end of line
i2cmaster/i2cmaster.S:136: Error: bad expression
i2cmaster/i2cmaster.S:136: Error: missing ')'
i2cmaster/i2cmaster.S:136: Error: missing ')'
i2cmaster/i2cmaster.S:136: Error: missing ')'
i2cmaster/i2cmaster.S:136: Error: missing ')'
i2cmaster/i2cmaster.S:136: Error: missing ')'
i2cmaster/i2cmaster.S:136: Error: constant value required
i2cmaster/i2cmaster.S:136: Error: `,' required
i2cmaster/i2cmaster.S:136: Error: constant value required
i2cmaster/i2cmaster.S:136: Error: garbage at end of line
i2cmaster/i2cmaster.S:138: Error: bad expression
i2cmaster/i2cmaster.S:138: Error: missing ')'
i2cmaster/i2cmaster.S:138: Error: missing ')'
i2cmaster/i2cmaster.S:138: Error: missing ')'
i2cmaster/i2cmaster.S:138: Error: missing ')'
i2cmaster/i2cmaster.S:138: Error: missing ')'
i2cmaster/i2cmaster.S:138: Error: constant value required
i2cmaster/i2cmaster.S:138: Error: `,' required
i2cmaster/i2cmaster.S:138: Error: constant value required
i2cmaster/i2cmaster.S:138: Error: garbage at end of line
i2cmaster/i2cmaster.S:159: Error: bad expression
i2cmaster/i2cmaster.S:159: Error: missing ')'
i2cmaster/i2cmaster.S:159: Error: missing ')'
i2cmaster/i2cmaster.S:159: Error: missing ')'
i2cmaster/i2cmaster.S:159: Error: missing ')'
i2cmaster/i2cmaster.S:159: Error: missing ')'
i2cmaster/i2cmaster.S:159: Error: constant value required
i2cmaster/i2cmaster.S:159: Error: `,' required
i2cmaster/i2cmaster.S:159: Error: constant value required
i2cmaster/i2cmaster.S:159: Error: garbage at end of line
i2cmaster/i2cmaster.S:181: Error: bad expression
i2cmaster/i2cmaster.S:181: Error: missing ')'
i2cmaster/i2cmaster.S:181: Error: missing ')'
i2cmaster/i2cmaster.S:181: Error: missing ')'
i2cmaster/i2cmaster.S:181: Error: missing ')'
i2cmaster/i2cmaster.S:181: Error: missing ')'
i2cmaster/i2cmaster.S:181: Error: constant value required
i2cmaster/i2cmaster.S:181: Error: `,' required
i2cmaster/i2cmaster.S:181: Error: constant value required
i2cmaster/i2cmaster.S:181: Error: garbage at end of line
i2cmaster/i2cmaster.S:182: Error: bad expression
i2cmaster/i2cmaster.S:182: Error: missing ')'
i2cmaster/i2cmaster.S:182: Error: missing ')'
i2cmaster/i2cmaster.S:182: Error: missing ')'
i2cmaster/i2cmaster.S:182: Error: missing ')'
i2cmaster/i2cmaster.S:182: Error: missing ')'
i2cmaster/i2cmaster.S:182: Error: constant value required
i2cmaster/i2cmaster.S:182: Error: `,' required
i2cmaster/i2cmaster.S:182: Error: constant value required
i2cmaster/i2cmaster.S:182: Error: garbage at end of line
i2cmaster/i2cmaster.S:184: Error: bad expression
i2cmaster/i2cmaster.S:184: Error: missing ')'
i2cmaster/i2cmaster.S:184: Error: missing ')'
i2cmaster/i2cmaster.S:184: Error: missing ')'
i2cmaster/i2cmaster.S:184: Error: missing ')'
i2cmaster/i2cmaster.S:184: Error: missing ')'
i2cmaster/i2cmaster.S:184: Error: constant value required
i2cmaster/i2cmaster.S:184: Error: `,' required
i2cmaster/i2cmaster.S:184: Error: constant value required
i2cmaster/i2cmaster.S:184: Error: garbage at end of line
i2cmaster/i2cmaster.S:186: Error: bad expression
i2cmaster/i2cmaster.S:186: Error: missing ')'
i2cmaster/i2cmaster.S:186: Error: missing ')'
i2cmaster/i2cmaster.S:186: Error: missing ')'
i2cmaster/i2cmaster.S:186: Error: missing ')'
i2cmaster/i2cmaster.S:186: Error: missing ')'
i2cmaster/i2cmaster.S:186: Error: constant value required
i2cmaster/i2cmaster.S:186: Error: `,' required
i2cmaster/i2cmaster.S:186: Error: constant value required
i2cmaster/i2cmaster.S:186: Error: garbage at end of line
i2cmaster/i2cmaster.S:209: Error: bad expression
i2cmaster/i2cmaster.S:209: Error: missing ')'
i2cmaster/i2cmaster.S:209: Error: missing ')'
i2cmaster/i2cmaster.S:209: Error: missing ')'
i2cmaster/i2cmaster.S:209: Error: missing ')'
i2cmaster/i2cmaster.S:209: Error: missing ')'
i2cmaster/i2cmaster.S:209: Error: constant value required
i2cmaster/i2cmaster.S:209: Error: `,' required
i2cmaster/i2cmaster.S:209: Error: constant value required
i2cmaster/i2cmaster.S:209: Error: garbage at end of line
i2cmaster/i2cmaster.S:212: Error: bad expression
i2cmaster/i2cmaster.S:212: Error: missing ')'
i2cmaster/i2cmaster.S:212: Error: missing ')'
i2cmaster/i2cmaster.S:212: Error: missing ')'
i2cmaster/i2cmaster.S:212: Error: missing ')'
i2cmaster/i2cmaster.S:212: Error: missing ')'
i2cmaster/i2cmaster.S:212: Error: constant value required
i2cmaster/i2cmaster.S:212: Error: `,' required
i2cmaster/i2cmaster.S:212: Error: constant value required
i2cmaster/i2cmaster.S:212: Error: garbage at end of line
i2cmaster/i2cmaster.S:215: Error: bad expression
i2cmaster/i2cmaster.S:215: Error: missing ')'
i2cmaster/i2cmaster.S:215: Error: missing ')'
i2cmaster/i2cmaster.S:215: Error: missing ')'
i2cmaster/i2cmaster.S:215: Error: missing ')'
i2cmaster/i2cmaster.S:215: Error: missing ')'
i2cmaster/i2cmaster.S:215: Error: constant value required
i2cmaster/i2cmaster.S:215: Error: `,' required
i2cmaster/i2cmaster.S:215: Error: constant value required
i2cmaster/i2cmaster.S:215: Error: garbage at end of line
i2cmaster/i2cmaster.S:219: Error: bad expression
i2cmaster/i2cmaster.S:219: Error: missing ')'
i2cmaster/i2cmaster.S:219: Error: missing ')'
i2cmaster/i2cmaster.S:219: Error: missing ')'
i2cmaster/i2cmaster.S:219: Error: missing ')'
i2cmaster/i2cmaster.S:219: Error: missing ')'
i2cmaster/i2cmaster.S:219: Error: constant value required
i2cmaster/i2cmaster.S:219: Error: `,' required
i2cmaster/i2cmaster.S:219: Error: constant value required
i2cmaster/i2cmaster.S:219: Error: garbage at end of line
i2cmaster/i2cmaster.S:224: Error: bad expression
i2cmaster/i2cmaster.S:224: Error: missing ')'
i2cmaster/i2cmaster.S:224: Error: missing ')'
i2cmaster/i2cmaster.S:224: Error: missing ')'
i2cmaster/i2cmaster.S:224: Error: missing ')'
i2cmaster/i2cmaster.S:224: Error: missing ')'
i2cmaster/i2cmaster.S:224: Error: constant value required
i2cmaster/i2cmaster.S:224: Error: `,' required
i2cmaster/i2cmaster.S:224: Error: constant value required
i2cmaster/i2cmaster.S:224: Error: garbage at end of line
i2cmaster/i2cmaster.S:225: Error: bad expression
i2cmaster/i2cmaster.S:225: Error: missing ')'
i2cmaster/i2cmaster.S:225: Error: missing ')'
i2cmaster/i2cmaster.S:225: Error: missing ')'
i2cmaster/i2cmaster.S:225: Error: missing ')'
i2cmaster/i2cmaster.S:225: Error: missing ')'
i2cmaster/i2cmaster.S:225: Error: constant value required
i2cmaster/i2cmaster.S:225: Error: `,' required
i2cmaster/i2cmaster.S:225: Error: constant value required
i2cmaster/i2cmaster.S:225: Error: garbage at end of line
i2cmaster/i2cmaster.S:227: Error: bad expression
i2cmaster/i2cmaster.S:227: Error: missing ')'
i2cmaster/i2cmaster.S:227: Error: missing ')'
i2cmaster/i2cmaster.S:227: Error: missing ')'
i2cmaster/i2cmaster.S:227: Error: missing ')'
i2cmaster/i2cmaster.S:227: Error: missing ')'
i2cmaster/i2cmaster.S:227: Error: constant value required
i2cmaster/i2cmaster.S:227: Error: `,' required
i2cmaster/i2cmaster.S:227: Error: constant value required
i2cmaster/i2cmaster.S:227: Error: garbage at end of line
i2cmaster/i2cmaster.S:229: Error: bad expression
i2cmaster/i2cmaster.S:229: Error: missing ')'
i2cmaster/i2cmaster.S:229: Error: missing ')'
i2cmaster/i2cmaster.S:229: Error: missing ')'
i2cmaster/i2cmaster.S:229: Error: missing ')'
i2cmaster/i2cmaster.S:229: Error: missing ')'
i2cmaster/i2cmaster.S:229: Error: constant value required
i2cmaster/i2cmaster.S:229: Error: `,' required
i2cmaster/i2cmaster.S:229: Error: constant value required
i2cmaster/i2cmaster.S:229: Error: garbage at end of line
i2cmaster/i2cmaster.S:233: Error: bad expression
i2cmaster/i2cmaster.S:233: Error: missing ')'
i2cmaster/i2cmaster.S:233: Error: missing ')'
i2cmaster/i2cmaster.S:233: Error: missing ')'
i2cmaster/i2cmaster.S:233: Error: missing ')'
i2cmaster/i2cmaster.S:233: Error: missing ')'
i2cmaster/i2cmaster.S:233: Error: constant value required
i2cmaster/i2cmaster.S:233: Error: `,' required
i2cmaster/i2cmaster.S:233: Error: constant value required
i2cmaster/i2cmaster.S:233: Error: garbage at end of line
i2cmaster/i2cmaster.S:265: Error: bad expression
i2cmaster/i2cmaster.S:265: Error: missing ')'
i2cmaster/i2cmaster.S:265: Error: missing ')'
i2cmaster/i2cmaster.S:265: Error: missing ')'
i2cmaster/i2cmaster.S:265: Error: missing ')'
i2cmaster/i2cmaster.S:265: Error: missing ')'
i2cmaster/i2cmaster.S:265: Error: constant value required
i2cmaster/i2cmaster.S:265: Error: `,' required
i2cmaster/i2cmaster.S:265: Error: constant value required
i2cmaster/i2cmaster.S:265: Error: garbage at end of line
i2cmaster/i2cmaster.S:266: Error: bad expression
i2cmaster/i2cmaster.S:266: Error: missing ')'
i2cmaster/i2cmaster.S:266: Error: missing ')'
i2cmaster/i2cmaster.S:266: Error: missing ')'
i2cmaster/i2cmaster.S:266: Error: missing ')'
i2cmaster/i2cmaster.S:266: Error: missing ')'
i2cmaster/i2cmaster.S:266: Error: constant value required
i2cmaster/i2cmaster.S:266: Error: `,' required
i2cmaster/i2cmaster.S:266: Error: constant value required
i2cmaster/i2cmaster.S:266: Error: garbage at end of line
i2cmaster/i2cmaster.S:269: Error: bad expression
i2cmaster/i2cmaster.S:269: Error: missing ')'
i2cmaster/i2cmaster.S:269: Error: missing ')'
i2cmaster/i2cmaster.S:269: Error: missing ')'
i2cmaster/i2cmaster.S:269: Error: missing ')'
i2cmaster/i2cmaster.S:269: Error: missing ')'
i2cmaster/i2cmaster.S:269: Error: constant value required
i2cmaster/i2cmaster.S:269: Error: `,' required
i2cmaster/i2cmaster.S:269: Error: constant value required
i2cmaster/i2cmaster.S:269: Error: garbage at end of line
i2cmaster/i2cmaster.S:273: Error: bad expression
i2cmaster/i2cmaster.S:273: Error: missing ')'
i2cmaster/i2cmaster.S:273: Error: missing ')'
i2cmaster/i2cmaster.S:273: Error: missing ')'
i2cmaster/i2cmaster.S:273: Error: missing ')'
i2cmaster/i2cmaster.S:273: Error: missing ')'
i2cmaster/i2cmaster.S:273: Error: constant value required
i2cmaster/i2cmaster.S:273: Error: `,' required
i2cmaster/i2cmaster.S:273: Error: constant value required
i2cmaster/i2cmaster.S:273: Error: garbage at end of line
i2cmaster/i2cmaster.S:280: Error: bad expression
i2cmaster/i2cmaster.S:280: Error: missing ')'
i2cmaster/i2cmaster.S:280: Error: missing ')'
i2cmaster/i2cmaster.S:280: Error: missing ')'
i2cmaster/i2cmaster.S:280: Error: missing ')'
i2cmaster/i2cmaster.S:280: Error: missing ')'
i2cmaster/i2cmaster.S:280: Error: constant value required
i2cmaster/i2cmaster.S:280: Error: `,' required
i2cmaster/i2cmaster.S:280: Error: constant value required
i2cmaster/i2cmaster.S:280: Error: garbage at end of line
i2cmaster/i2cmaster.S:283: Error: bad expression
i2cmaster/i2cmaster.S:283: Error: missing ')'
i2cmaster/i2cmaster.S:283: Error: missing ')'
i2cmaster/i2cmaster.S:283: Error: missing ')'
i2cmaster/i2cmaster.S:283: Error: missing ')'
i2cmaster/i2cmaster.S:283: Error: missing ')'
i2cmaster/i2cmaster.S:283: Error: constant value required
i2cmaster/i2cmaster.S:283: Error: `,' required
i2cmaster/i2cmaster.S:283: Error: constant value required
i2cmaster/i2cmaster.S:283: Error: garbage at end of line
i2cmaster/i2cmaster.S:286: Error: bad expression
i2cmaster/i2cmaster.S:286: Error: missing ')'
i2cmaster/i2cmaster.S:286: Error: missing ')'
i2cmaster/i2cmaster.S:286: Error: missing ')'
i2cmaster/i2cmaster.S:286: Error: missing ')'
i2cmaster/i2cmaster.S:286: Error: missing ')'
i2cmaster/i2cmaster.S:286: Error: constant value required
i2cmaster/i2cmaster.S:286: Error: `,' required
i2cmaster/i2cmaster.S:286: Error: constant value required
i2cmaster/i2cmaster.S:286: Error: garbage at end of line
i2cmaster/i2cmaster.S:289: Error: bad expression
i2cmaster/i2cmaster.S:289: Error: missing ')'
i2cmaster/i2cmaster.S:289: Error: missing ')'
i2cmaster/i2cmaster.S:289: Error: missing ')'
i2cmaster/i2cmaster.S:289: Error: missing ')'
i2cmaster/i2cmaster.S:289: Error: missing ')'
i2cmaster/i2cmaster.S:289: Error: constant value required
i2cmaster/i2cmaster.S:289: Error: `,' required
i2cmaster/i2cmaster.S:289: Error: constant value required
i2cmaster/i2cmaster.S:289: Error: garbage at end of line
i2cmaster/i2cmaster.S:291: Error: bad expression
i2cmaster/i2cmaster.S:291: Error: missing ')'
i2cmaster/i2cmaster.S:291: Error: missing ')'
i2cmaster/i2cmaster.S:291: Error: missing ')'
i2cmaster/i2cmaster.S:291: Error: missing ')'
i2cmaster/i2cmaster.S:291: Error: missing ')'
i2cmaster/i2cmaster.S:291: Error: constant value required
i2cmaster/i2cmaster.S:291: Error: `,' required
i2cmaster/i2cmaster.S:291: Error: constant value required
i2cmaster/i2cmaster.S:291: Error: garbage at end of line
make.exe: *** [bedienfeld.elf] Error 1

Fro
06.08.2006, 15:00
Ah okay, ich hab festgestellt ist ja assembler. Ausserdem da ich Atmega8 benutze, kann ich die twimaster.c file benutzen...

Leider klappt es immer noch nicht. Ich habe meinem Slave die Adresse 0x02 zugewiesen und versuche also mit


i2c_start_wait(0x02+I2C_WRITE); // set device address and write mode
i2c_write(0x01); // write address = 5
i2c_write(0x0E); // write value 0x75 to EEPROM
i2c_stop(); // set stop conditon = release bus

auf den Slave zu schreiben.

Im Slave möchte ich dann diesen Wert mit

xyz = rxbuffer[1];

auslesen....ist das richtig so?

uwegw
06.08.2006, 16:52
So mach ich das auch, nur mit nem normalen i2c_start statt i2c-start_wait.

Fro
06.08.2006, 18:43
Es funktioniert! JuhuuuuuuuuU! :mrgreen:

Ich bin so glücklich! Benutzt habe ich wie gesagt die Libs von P.Fleury und Uwegw

Aber: Mein Slave scheint nach der ersten Übertragung keinen weiteren Wert mehr akzeptieren zu wollen... :-k

So soll es aussehen. Ich drück am Master einen Knopf -> der erste Wert wird zum Slave übertragen und angezeigt (per Ziffern) -> Ich drücke noch einmal, und es sollte der 2.Wert übertragen und angezeigt werden...

Kurze Anregung woran das liegen könnte? Quellcode reiche ich nach...

Fro
07.08.2006, 10:17
Apropos: Danke für die Hilfe bis hier her! =D>

Hatt ich in der Freude vergessen zu schreiben :oops:

Fro
07.08.2006, 14:10
Also es ist mittlerweile so weit gediehen, dass immer wieder übertragen wird. Manchmal scheint das ganze aber zu hängen, sprich der Master sendet nach einer Übertragung kein Stoppsignal mehr. Auf welche Fehlerquellen könnte das deuten?

Hier nun die Codes für Master:

#include <avr/io.h>
#include <avr/interrupt.h>
#include "i2cmaster.h"
#include <compat/twi.h>


void timer_init(void){
TCCR0 = (1 << CS02); //Frequenzteilung durch 256
}

void main(void){
DDRD = 0x00; //PORTD als Eingang
PORTD = 0xFF; // Pull-Up Widerstände an Port D aktiviert -> Schalter als Active-Low ausführen
DDRB = 0xFF;
PORTB = 0x00; //hier hängen LEDs dran, um eventuell beim Fehlersuchen zu helfen
unsigned int overflow_counter = 0;
unsigned char goal1[2];
goal1[0] = 0;
goal1[1] = 0;
timer_init();
i2c_init();
PORTB = (1 <<PB0);
for(;;){
PORTB = 0x00;
if ( TIFR & (1<<TOV0) ) {//wenn die timer/counter0 overflow Fahne '1' ist, dass ist immer wenn 1/152 sec erreicht sind (10Mhz/(256*256))
TIFR |= (1<<TOV0) ; //Overflow Bit wieder auf null setzen
overflow_counter++; //overflow counter inkrementieren
}
if (!(PIND & (1 << PD7)) && (overflow_counter > 100)){
PORTB = (1<<PB0);
goal[1]++;
i2c_start_wait(0x02+I2C_WRITE); // set device address and write mode
i2c_write(0x02); // write address = 2
i2c_write(goal1[1]); // write value goal[i] to Slave
i2c_stop();
i++;
overflow_counter = 0;
}

}
}
//end of bedienfeld.c

Und für den Slave:
//clockspeed 4Mhz ->

/* Dies ist das C-File für die Anzeigensteuerung, das I2C wird über einen Interrupt ausgelöst*/
#include <avr/io.h>
#include "show_digits.h" //File für die Umwandlung von Zehner- und Einserdezimal in BCD
#include <compat/twi.h>
#include <avr/interrupt.h>
#include "i2cnew/twislave.h"
#include <util/twi.h>

volatile unsigned char goal1 = 0;
volatile unsigned char goal2 = 0;

void timer_init(void){
TCCR0 = (1 << CS00); //Timer / Counter Control Register is set to devide by 8
}



void main(void){
int overflow_counter = 0; //overflow counter zählt die counter bit overflows
int pin_counter = 0;
DDRB = 0xFF;
PORTB = 0x00;

DDRD = 0xFF; //Alle PortD Pins auf Ausgang gesetzt (PD0-3 für BCD, PD4-7 für Ziffer 1-4)
PORTD = 0x00; //Alles auf Low, Anzeige aus

timer_init(); //timer wird gestartet
int i = 0;
init_twi_slave(0x02); //Alles für TWI Übertragung fertig machen


rxbuffer[6] = 78;
rxbuffer[2] = 00;

for(;;){
PORTB = 0x00;
goal1 = rxbuffer[2];
if ( TIFR & (1<<TOV0) ) {//wenn die timer/counter0 overflow Fahne '1' ist, dass ist immer wenn 1/195 sec erreicht sind (4Mhz/(8*256))
TIFR |= (1<<TOV0) ; //Overflow Bit wieder auf null setzen
overflow_counter++; //overflow counter inkrementieren
}
if (overflow_counter==30) {//Nach 10x256x8 = 20480 overflows oder 50ms
PORTD = 0x00; //Alle Ausgänge ausschalten
PORTD |= (1 << PD4); //Tor 1 Zehner anschalten
show_ten(goal1);
}
else if (overflow_counter==60) {
PORTD = 0x00; //Alle Ausgänge ausschalten
PORTD |= (1 << PD5); //Tor 1 Einser anschalten
show_one(goal1);
}
else if (overflow_counter==90) {
PORTD = 0x00; //Alle Ausgänge ausschalten
PORTD |= (1 << PD6); //Tor 2 Zehner anschalten
show_ten(goal2);
}
else if (overflow_counter==120) {
PORTD = 0x00; //Alle Ausgänge ausschalten
PORTD |= (1 << PD7); //Tor 2 Einser anschalten
show_one(goal2);
overflow_counter=0;
pin_counter++;
}
if (pin_counter > 60){
i++;
pin_counter = 0;
}
if (i == 7){
i=0;
}

}
}

bart
02.03.2007, 18:02
Hallo, wenn ich an dieses Thread mal anknüpfen darf ....

Ich möchte ebenfalls einen ATmega8 als Slave verwenden (RN-Mini Control), nun habe ich das Problem, dass jedes mal wenn ich vom Master aus was senden möchte scheinbar ein Reset an dem ATmega8 ausgeführt wird. Ich sende vom Master aus an den Slave (Code für Slave steht unten) ein Byte in das register rxbuffer[0]. Jedoch schaltet sich die Diode die an Port PC1 hängt über die If-Abfrage in der for-Schleife nie ein, sondern der AVR startet anscheinden neu weil sie dann kurz aufblinkt.

Was mache ich falsch bitte um Hilfe ... :-k

P.S. benutze auch die Libs von P.Fleury und Uwegw, nur die i2cmaster.S habe ich gelöscht da ich die twimaster.c verwende.



#include <avr/interrupt.h>
#include <avr/signal.h>
#include <compat/twi.h>
#include <avr/io.h>
#include <compat/twi.h>

#define F_CPU 16000000

volatile uint8_t rxbuffer[8];
#define rx_PWM_L 2
#define rx_PWM_R 3
#define rx_DIR 1
volatile uint8_t txbuffer[8]

void init_twi_slave (uint8_t adr)
{
TWAR= adr; //Adresse setzen

TWCR|= (1<<TWEA) | (1<<TWEN)|(1<<TWIE);
TWCR &= ~(1<<TWSTA)|(1<<TWSTO);
buffer_adr=0xFF;
sei();
}

int main(void) {

/************************************************** ************************************************** ***************/
/* Initialisierung */
/************************************************** ************************************************** ***************/

//*** Alle Ports an PortD als Ausgang definieren
DDRB = 0xFF;
PORTB = 0x00;

DDRD = 0xFF;
PORTD = 0x00;

DDRC = 0xFF;
PORTC= 0x00;
PORTC &= ~(1<<DDC1);

init_twi_slave(0x60); // Init I2C interface

Delay(1000);

// Diode einmal anblicken ob sie funktioniert
PORTC |= (1<<DDC1);
Delay(400);
PORTC &= ~(1<<DDC1);
Delay(400);
rxbuffer[0]=0;

for(;;){
if (rxbuffer[0]!= 0){
PORTC |= (1<<DDC1);
Delay(2000);
}
}

linux_80
02.03.2007, 20:30
Hallo,

Es gibt keine ISR, das Bit wird aber aktiviert, deshalb gehts bei einem IRQ dann ab zum Reset !

Und es macht sich nicht Gut, das TWCR per OR oder AND zu manipulieren (bzw. in zwei Zeilen aufeinander), denn jeder Schreibzugriff löst eine Aktion aus, also immer die benötigten Bits setzen und alles auf einmal ans TWCR übergeben !

bart
02.03.2007, 22:08
Ups sorry, die ISR muss wohl beim "copy pasten" unter den Tisch gefallen sein. Hier nochmal dem komplette Code Problem wie beschrieben



#include <avr/interrupt.h>
#include <avr/signal.h>
#include <compat/twi.h>
#include <avr/io.h>
#include <compat/twi.h>

#define F_CPU 16000000

volatile uint8_t rxbuffer[8];
#define rx_PWM_L 2
#define rx_PWM_R 3
#define rx_DIR 1
volatile uint8_t txbuffer[8]

void init_twi_slave (uint8_t adr)
{
TWAR= adr; //Adresse setzen

TWCR|= (1<<TWEA) | (1<<TWEN)|(1<<TWIE);
TWCR &= ~(1<<TWSTA)|(1<<TWSTO);
buffer_adr=0xFF;
sei();
}

int main(void) {

/************************************************** ************************************************** ***************/
/* Initialisierung */
/************************************************** ************************************************** ***************/

//*** Alle Ports an PortD als Ausgang definieren
DDRB = 0xFF;
PORTB = 0x00;

DDRD = 0xFF;
PORTD = 0x00;

DDRC = 0xFF;
PORTC= 0x00;
PORTC &= ~(1<<DDC1);

init_twi_slave(0x60); // Init I2C interface

Delay(1000);

// Diode einmal anblicken ob sie funktioniert
PORTC |= (1<<DDC1);
Delay(400);
PORTC &= ~(1<<DDC1);
Delay(400);
rxbuffer[0]=0;

for(;;){
if (rxbuffer[0]!= 0){
PORTC |= (1<<DDC1);
Delay(2000);
}
}

ISR (TWI_vect) { //ISR, die bei einem Ereignis auf dem Bus ausgelöst wird. Im Register TWSR befindet sich dann
//ein Statuscode, anhand dessen die Situation festgestellt werden kann.

uint8_t data=0;

switch (TWSR) //TWI-Statusregister prüfen und nötige Aktion bestimmen
{
case TW_SR_SLA_ACK: // 0x60 Slave Receiver, wurde adressiert
TWCR = (1<<TWEN)| // TWI Interface enabled
(1<<TWIE)|(1<<TWINT)| // Enable TWI Interupt and clear the flag to send byte
(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // Expect ACK on this transmission
(0<<TWWC); //
buffer_adr=0xFF; //Bufferposition ist undefiniert
break;

case TW_SR_DATA_ACK: // 0x80 Slave Receiver,Daten empfangen
data=TWDR;
if (buffer_adr == 0xFF) //erster Zugriff, Bufferposition setzen
{
buffer_adr= data; //Bufferposition wie adressiert setzen
TWCR = (1<<TWEN)| // TWI Interface enabled
(1<<TWIE)|(1<<TWINT)| // Enable TWI Interupt and clear the flag to send byte
(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // Send ACK after next reception
(0<<TWWC);
}
else //weiterer Zugriff, Daten empfangen
{
rxbuffer[buffer_adr]=data; //Daten in Buffer schreiben
buffer_adr++; //autoincrement Buffer-Adresse
if(buffer_adr<7)
{
//nächstes Byte lesen, ACK danach
TWCR = (1<<TWEN)| // TWI Interface enabled
(1<<TWIE)|(1<<TWINT)| // Enable TWI Interupt and clear the flag to send byte
(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // Send ACK after next reception
(0<<TWWC);
}
else
{
//letztes Byte lesen, dann NACK
TWCR = (1<<TWEN)| // TWI Interface enabled
(1<<TWIE)|(1<<TWINT)| // Enable TWI Interupt and clear the flag to send byte
(0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|
(0<<TWWC);
}
}
break;


case TW_ST_SLA_ACK:
case TW_ST_DATA_ACK: //0xB0 weitere Daten gefordert
TWDR = txbuffer[buffer_adr];
buffer_adr++;
TWCR = (1<<TWEN)|
(1<<TWIE)|(1<<TWINT)|
(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|
(0<<TWWC);
break;

case TW_ST_DATA_NACK: //0xC0 Keine Daten mehr gefordert
case TW_SR_DATA_NACK: //0x88
case TW_ST_LAST_DATA: //0xC8 Last data byte in TWDR has been transmitted (TWEA = “0”); ACK has been received
case TW_SR_STOP: // 0xA0 STOP empfangen
default:
TWCR = (1<<TWEN)|
(1<<TWIE)|(1<<TWINT)|
(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|
(0<<TWWC);
//buffer_adr=0xFF; //Bufferposition ist undefiniert
break;


} //end.switch
} //end.twi_ISR

uwegw
02.03.2007, 23:00
Mich wundert, dass du das programm überhaupt kompiliert bekommst. Du hast die Deklaration von buffer_adr nicht drin. Eigentlich müsste der Compiler an zig Stellen meckern.
Pack am besten mal meinen Code (aber komplett!) in ne separate Datei, wie ich es in den Kommentaren geschreiben habe.

bart
02.03.2007, 23:19
So hab ich gemacht komplett rauskopiert und in i2cslave.c gespeichert und im programm included. Hab nur den Pfad für #include <compat/twi.h> angepasst.

Immer noch gleiches Problem :-(

main.c


// AVR Bibs
#include <stdio.h>
#include <stdlib.h>
#include <avr/io.h> // I/O Ports
#include <inttypes.h> // Datentypen
#include <avr/pgmspace.h> // Stringfunktionen
#include <string.h> // Stringfunktionen
#include <avr/interrupt.h> // Interrupts
#include <avr/signal.h> // Timer
#include <math.h>



/************************************************** * Globale Variablen ************************************************/


/************************************************** * Init defines ************************************************** *****/
// Werte zur Berechnung der Interrupt-Rate bei AVR-Fuses,
// die auf 1MHz eingestellt sind (Werkseinstellung für internen RC-Oszillator)
#define F_CPU 16000000

// Geräteadressen
#define KEYLCD 0x40
#define RELAIS 0x76
#define SERVOS 0x68
#define PCFA 0x9E
#define PCF1 0x72
#define PCF2 0x7E
#define PCF3 0x74
#define PCF4 0x7C
#define PCF5 0x7A
#define PCF6 0x78

// Eigene Bibs
#include "func.h" // Allgemeine Funktionen
#include "sens.h" // Sensorfunktionen
#include "i2cslave.c"


int main(void) {

/************************************************** ************************************************** ***************/
/* Initialisierung */
/************************************************** ************************************************** ***************/

//*** Alle Ports an PortD als Ausgang definieren
DDRB = 0xFF;
PORTB = 0x00;

DDRD = 0xFF; //Alle PortD Pins auf Ausgang gesetzt (PD0-3 für BCD, PD4-7 für Ziffer 1-4)
PORTD = 0x00; //Alles auf Low, Anzeige aus

DDRC = 0xFF;
PORTC= 0x00;
PORTC &= ~(1<<DDC1);

init_twi_slave(0x60); // Init I2C interface

Delay(1000);

PORTC |= (1<<DDC1);
Delay(400);
PORTC &= ~(1<<DDC1);
Delay(400);
rxbuffer[0]=0;

for(;;){
if (rxbuffer[0]!= 0){
PORTC |= (1<<DDC1);
Delay(2000);
}
}

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

}


i2cslave.c


/*
Dieses Programm kann in einer separaten Datei (z.B. twislave.c) abgespeichert und in anderen Programmen
eingebunden werden.

Betrieb eines AVRs mit Hardware-TWI-Schnittstelle als Slave. Zu Beginn muss init_twi_slave mit der gewünschten
Slave-Adresse als Parameter aufgerufen werden. Der Datenaustausch mit dem Master erfolgt über die Buffer
rxbuffer und txbuffer, auf die von Master und Slave zugegriffen werden kann.
rxbuffer und txbuffer sind globale Variablen (Array aus uint8_t).
Die Ansteuerung des rxbuffers, in den der Master schreiben kann, erfolgt ähnlich wie bei einem normalen I2C-EEPROM.
Man sendet zunächst die Bufferposition, an die man schreiben will, und dann die Daten. Die Bufferposition wird
automatisch hochgezählt, sodass man mehrere Datenbytes hintereinander schreiben kann, ohne jedesmal
die Bufferadresse zu schreiben.
Um den zxbuffer vom Amster aus zu lesen, überträgt man zunächst in einem Schreibzugriff die gewünschte Bufferposition und
liest dann nach einem repeated start die Daten aus. Die Bufferposition wird automatisch hochgezählt, sodass man mehrere
Datenbytes hintereinander lesen kann, ohne jedesmal die Bufferposition zu schreiben.


Autor: Uwe Große-Wortmann (uwegw), Juli 2006.
Status: Testphase, keine Garantie für ordnungsgemäße Funktion! Empfangen scheint zu funktionieren.
letze Änderungen: Senden über den txbuffer implementiert, noch weitgehend ungetestet!
*/


#include <avr/interrupt.h>
#include <avr/io.h>
#include <compat/twi.h>

uint8_t buffer_adr; //"Adressregister" für den Buffer

/*Der Buffer, in dem die empfangenen Daten gespeichert werden. Der Slave funktioniert ähnlich wie ein normales
Speicher-IC [I2C-EEPROM], man sendet die Adresse, an die man schreiben will, dann die Daten, die interne Speicher-Adresse
wird dabei automatisch hochgezählt*/
volatile uint8_t rxbuffer[8];

#define rx_PWM_L 2
#define rx_PWM_R 3
#define rx_DIR 1
/*Der Sendebuffer, der vom Master ausgelesen werden kann. [noch nicht implementiert!]*/
volatile uint8_t txbuffer[8];


void init_twi_slave (uint8_t adr)
{
TWAR= adr; //Adresse setzen

TWCR|= (1<<TWEA) | (1<<TWEN)|(1<<TWIE);
TWCR &= ~(1<<TWSTA)|(1<<TWSTO);
buffer_adr=0xFF;
sei();
}


ISR (TWI_vect) //ISR, die bei einem Ereignis auf dem Bus ausgelöst wird. Im Register TWSR befindet sich dann
//ein Statuscode, anhand dessen die Situation festgestellt werden kann.
{

uint8_t data=0;

switch (TWSR) //TWI-Statusregister prüfen und nötige Aktion bestimmen
{
case TW_SR_SLA_ACK: // 0x60 Slave Receiver, wurde adressiert
TWCR = (1<<TWEN)| // TWI Interface enabled
(1<<TWIE)|(1<<TWINT)| // Enable TWI Interupt and clear the flag to send byte
(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // Expect ACK on this transmission
(0<<TWWC); //
buffer_adr=0xFF; //Bufferposition ist undefiniert
break;

case TW_SR_DATA_ACK: // 0x80 Slave Receiver,Daten empfangen
data=TWDR;
if (buffer_adr == 0xFF) //erster Zugriff, Bufferposition setzen
{
buffer_adr= data; //Bufferposition wie adressiert setzen
TWCR = (1<<TWEN)| // TWI Interface enabled
(1<<TWIE)|(1<<TWINT)| // Enable TWI Interupt and clear the flag to send byte
(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // Send ACK after next reception
(0<<TWWC);
}
else //weiterer Zugriff, Daten empfangen
{
rxbuffer[buffer_adr]=data; //Daten in Buffer schreiben
buffer_adr++; //autoincrement Buffer-Adresse
if(buffer_adr<7)
{
//nächstes Byte lesen, ACK danach
TWCR = (1<<TWEN)| // TWI Interface enabled
(1<<TWIE)|(1<<TWINT)| // Enable TWI Interupt and clear the flag to send byte
(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // Send ACK after next reception
(0<<TWWC);
}
else
{
//letztes Byte lesen, dann NACK
TWCR = (1<<TWEN)| // TWI Interface enabled
(1<<TWIE)|(1<<TWINT)| // Enable TWI Interupt and clear the flag to send byte
(0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|
(0<<TWWC);
}
}
break;


case TW_ST_SLA_ACK:
case TW_ST_DATA_ACK: //0xB0 weitere Daten gefordert
TWDR = txbuffer[buffer_adr];
buffer_adr++;
TWCR = (1<<TWEN)|
(1<<TWIE)|(1<<TWINT)|
(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|
(0<<TWWC);
break;

case TW_ST_DATA_NACK: //0xC0 Keine Daten mehr gefordert
case TW_SR_DATA_NACK: //0x88
case TW_ST_LAST_DATA: //0xC8 Last data byte in TWDR has been transmitted (TWEA = “0”); ACK has been received
case TW_SR_STOP: // 0xA0 STOP empfangen
default:
TWCR = (1<<TWEN)|
(1<<TWIE)|(1<<TWINT)|
(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|
(0<<TWWC);
//buffer_adr=0xFF; //Bufferposition ist undefiniert
break;


} //end.switch
} //end.twi_ISR

bart
04.03.2007, 14:13
Mache ich vom Master aus vielleicht einen Fehler?

Wie gesaght ich möchte einen ATmega8 als Slave verwenden (RN-Mini Control), nun habe ich das Problem, dass jedes mal wenn ich vom Master aus was senden möchte scheinbar ein Reset an dem ATmega8 ausgeführt wird. Ich sende vom Master aus an den Slave (Code für Slave steht im vorherigen Beitrag) ein Byte in das register rxbuffer[0]. Jedoch schaltet sich die Diode die an Port PC1 hängt über die If-Abfrage in der for-Schleife nie ein, sondern der AVR startet anscheinden neu weil sie dann kurz aufblinkt.

Spreche den Slave folgendermassen an...



adc_werte = 3;
i2c_start_wait(0x60+I2C_WRITE);
i2c_write(0);
i2c_write(adc_werte);
i2c_stop();

uwegw
04.03.2007, 14:23
Der Mastercode müsste so passen. Hol dir mal die aktuelle Version der twislave.c, hab ich gerade ins Wiki gepackt: https://www.roboternetz.de/wissen/index.php/TWI_Slave_mit_avr-gcc

bart
04.03.2007, 17:17
Hallo uwegw,

hab den neuen code übernommen, immer noch gleiches problem :-(

Der Kompiler spuckt folgende Meldungen aus:



Compiling: main.c
avr-gcc -c -mmcu=atmega168 -I. -g -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=main.lst -std=gnu99 main.c -o main.o
In file included from main.c:48:
twislave.c:77: warning: return type defaults to `int'
twislave.c:77: warning: function declaration isn't a prototype
twislave.c: In function `ISR':
twislave.c:77: warning: type of "TWI_vect" defaults to "int"
twislave.c:150: warning: control reaches end of non-void function


Kanns vielleicht an der twi.h liegen? Ich includiere sie aus dem Verzeichnis compat?

Oder habe ich ein zu altes WinAVR?

Ich habe das Gefühl das der Code in Ordnung...

Eine Frage noch muss man den I2C Bus mit einem Endwiderstand eigendlich terminieren?

Ich bin langsam am verzweifeln :-(

bart
04.03.2007, 17:17
Sorry, doppelpost...

uwegw
04.03.2007, 20:47
Das riecht nach zu altem Winavr. Bei älteren Versionen (bis 3.4.4) wurden die Interrupts etwas anders geschrieben, und man brauchte noch die signal.h.
Ich verwende 3.4.5.

bart
04.03.2007, 21:30
Ohhh, hab die Version 2.0.5

Schande über mein Haupt, werde mal ein neueres suchen ;-)

bart
04.03.2007, 22:23
Sir Uwegw, ich verneige mich vor Ihnen! Es lag tatsächlich am WinAVR nun läuft das program einwandfrei, sowohl senden als auch empfangen. Wie gesagt Code war ok :-)

1000dank \:D/