PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : IC2 ohne Libary



klucky
25.12.2004, 16:25
Ich hab mir mal den Artikel hier durchgelesen und wollte jetzt gerne die das ganze in meinem Programm verwenden. https://www.roboternetz.de/phpBB2/viewtopic.php?t=3447

Jetzt hab ich das ganze Fertig und es sieht so aus:



#include <avr/io.h>
#include <inttypes.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <avr/delay.h>
#include <stdlib.h> /*für exit*/

/*SD20 Adresse mit Lese- oder Schreibbit*/
#define SD20_W 0xC2
#define SD20_R 0xC3

typedef unsigned char BYTE;
typedef unsigned short WORD;

void i2c_start(BYTE ADRESSE)
{

TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); /*Startbedingung senden*/
while (!(TWCR & (1<<TWINT))); /*Darauf warten dass TWINT gesetzt wurde was aussagt das die Startbedingung gesendet wurde*/
if ((TWSR & 0xF8) != START) exit; /*Überprüfen ob START erfolgreich gesendet wurde sonst abbrechen*/
TWDR = ADRESSE; /*Slave Adresse in TWDR laden*/
TWCR = (1<<TWINT)|(1<<TWEN); /*TWINT und TWEN löschen damit die ADRESSE gesendet wird*/
while (! (TWCR & (1<<TWINT))); /*Darauf warten dass TWINT gesetzt wurde was aussagt dass die ADRESSE gesendet wurde*/
if ((TWSR & 0xF8) != MT_SLA_ACK) exit; /*Überprüfen ob ADRESSE erfolgreich gesendet wirde sonst abbrechen*/

}
void i2c_data(BYTE DATA)
{

TWDR = DATA; /*DATA in TWDR laden*/
TWCR = (1<<TWINT)|(1<<TWEN); /*TWINT und TWEN löschen damit die DATA gesendet wird*/
while (! (TWCR & (1<<TWINT))); /*Darauf warten dass TWINT gesetzt wurde was aussagt dass die DATA gesendet wurde*/
if ((TWSR & 0xF8) != MT_DATA_ACK) exit; /*Überprüfen ob DATA erfolgreich gesendet wirde sonst abbrechen*/

}
void i2c_stop(void)
{

TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO); /*Stopbedingung senden*/

}
int main(void)
{

i2c_start(SD20_W);
i2c_data(0x7F);
i2c_stop();

}


Naja jetzt bekomm ich nur leider einen ganzen haufen Fehlermeldungen:



> "make.exe" all

-------- begin --------
avr-gcc (GCC) 3.4.1
Copyright (C) 2004 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


Compiling: Lauflicht.c
avr-gcc -c -mmcu=atmega128 -I. -gstabs -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=Lauflicht.lst -std=gnu99 -Wp,-M,-MP,-MT,Lauflicht.o,-MF,.dep/Lauflicht.o.d Lauflicht.c -o Lauflicht.o
Lauflicht.c: In function `i2c_start':
Lauflicht.c:21: error: `START' undeclared (first use in this function)
Lauflicht.c:21: error: (Each undeclared identifier is reported only once
Lauflicht.c:21: error: for each function it appears in.)
Lauflicht.c:25: error: `MT_SLA_ACK' undeclared (first use in this function)
Lauflicht.c: In function `i2c_data':
Lauflicht.c:34: error: `MT_DATA_ACK' undeclared (first use in this function)
Lauflicht.c: In function `i2c_start':
Lauflicht.c:21: warning: statement with no effect
Lauflicht.c:25: warning: statement with no effect
Lauflicht.c: In function `i2c_data':
Lauflicht.c:34: warning: statement with no effect
make.exe: *** [Lauflicht.o] Error 1

> Process Exit Code: 2



Dass START, MT_SLA_ACK, MT_DATA_ACK Probleme machen würden hab ich mir schon direkt Gedacht als ich sie gelesen habe da sie ja nirgends vorher definiert werden. Nur wo bekomm ich die definition dafür her?

Würd mich freun wenn mir jemand von euch helfen könnte! THX schonmal für eure Mühe!

26.12.2004, 08:04
Im Zweifel RTFM :-)

Um auch was konstruktives beizutragen:

Was für Bauteile möchtest du denn per I²C verbinden? Für den Anfang ist es besser, auf die Auswertung des Statusregisters zu verzichten und sich dessen Inhalt statt dessen auf einem LCD oder über den USART ausgeben zu lassen. Was welcher Code dann bedeutet kann dem Datenblatt entnommen werden.
Beispiele für das Ansprechen von I²C-Bausteinen findest du auf mc-project.de in der Rubrik IC's&Co.

muraad
26.12.2004, 15:21
Du musst die Datei twi.h includen. Da sind die alle definiert.
Gruß Muraad

klucky
27.12.2004, 00:54
Hab mich jetzt entschieden diese überprüfungen wegzulassen. Mein Quellcode sieht jetzt so aus und es gibt auch keien fehler mehr beim compilieren:



#include <avr/io.h>
#include <inttypes.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <avr/delay.h>
#include <stdlib.h> /*für exit*/

/*SD20 Adresse mit Lese- oder Schreibbit*/
#define SD20_W 0xC2
#define SD20_R 0xC3

typedef unsigned char BYTE;
typedef unsigned short WORD;

void i2c_start(BYTE ADRESSE)
{

TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); /*Startbedingung senden*/
while (!(TWCR & (1<<TWINT))); /*Darauf warten dass TWINT gesetzt wurde was aussagt das die Startbedingung gesendet wurde*/
TWDR = ADRESSE; /*Slave Adresse in TWDR laden*/
TWCR = (1<<TWINT)|(1<<TWEN); /*TWINT und TWEN löschen damit die ADRESSE gesendet wird*/
while (! (TWCR & (1<<TWINT))); /*Darauf warten dass TWINT gesetzt wurde was aussagt dass die ADRESSE gesendet wurde*/

}
void i2c_data(BYTE DATA)
{

TWDR = DATA; /*DATA in TWDR laden*/
TWCR = (1<<TWINT)|(1<<TWEN); /*TWINT und TWEN löschen damit die DATA gesendet wird*/
while (! (TWCR & (1<<TWINT))); /*Darauf warten dass TWINT gesetzt wurde was aussagt dass die DATA gesendet wurde*/

}
void i2c_stop(void)
{

TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO); /*Stopbedingung senden*/

}
int main(void)
{

i2c_start(SD20_W);
i2c_data(0x01);
i2c_data(0x7F);
i2c_stop();

}


Aber irgendwie tuts das ganze trotzdem nicht. Ich möchte damit gerne den ersten Servo von einem SD20 in die Mittelstellung bringen aber es passiert einfach garnix.

muraad
27.12.2004, 02:07
Erstaml sorry das ich so oft des gleich geantwortet hab aber des Forum hat bei mir irgendwie gesponnen. Du brauchst diese überprüfung schon. Du programmierst doch mit WinAVR oder? Dann #include doch einfach die Datei twi.h dann geht dein Code auch. Dein Code ist übrigens der Beispiel Code aus dem ATmega Datenblatt.
Gruß Muraad

klucky
27.12.2004, 14:42
jap issa so ein genie das ich sowas selber schreib bin ich noch net ;)! https://www.roboternetz.de/phpBB2/viewtopic.php?t=3447 das ist auch der code aus dem Datenblatt ;)! Besser viele gleiche als garkeine antworten ;)!

UweMD
27.12.2004, 15:48
Hi Klucky...

Ich habe mir mal die twi.h angeschaut..
da wird START mit TW_START u. MT_SLA_ACK mit TW_MT_SLA_ACK
MT_DATA_ACK mit TW_MT_DATA_ACK
Deklariert



hoffe es hilft....







#include <avr/io.h>
#include <inttypes.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <avr/delay.h>
#include <avr/twi.h>
#include <stdlib.h> /*für exit*/

/*SD20 Adresse mit Lese- oder Schreibbit*/
#define SD20_W 0xC2
#define SD20_R 0xC3

typedef unsigned char BYTE;
typedef unsigned short WORD;

void i2c_start(BYTE ADRESSE)
{

TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); /*Startbedingung senden*/
while (!(TWCR & (1<<TWINT))); /*Darauf warten dass TWINT gesetzt wurde was aussagt das die Startbedingung gesendet wurde*/
if ((TWSR & 0xF8) != TW_START) exit; /*Überprüfen ob START erfolgreich gesendet wurde sonst abbrechen*/
TWDR = ADRESSE; /*Slave Adresse in TWDR laden*/
TWCR = (1<<TWINT)|(1<<TWEN); /*TWINT und TWEN löschen damit die ADRESSE gesendet wird*/
while (! (TWCR & (1<<TWINT))); /*Darauf warten dass TWINT gesetzt wurde was aussagt dass die ADRESSE gesendet wurde*/
if ((TWSR & 0xF8) != TW_MT_SLA_ACK) exit; /*Überprüfen ob ADRESSE erfolgreich gesendet wirde sonst abbrechen*/

}
void i2c_data(BYTE DATA)
{

TWDR = DATA; /*DATA in TWDR laden*/
TWCR = (1<<TWINT)|(1<<TWEN); /*TWINT und TWEN löschen damit die DATA gesendet wird*/
while (! (TWCR & (1<<TWINT))); /*Darauf warten dass TWINT gesetzt wurde was aussagt dass die DATA gesendet wurde*/
if ((TWSR & 0xF8) != TW_MT_DATA_ACK) exit; /*Überprüfen ob DATA erfolgreich gesendet wirde sonst abbrechen*/

}
void i2c_stop(void)
{

TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO); /*Stopbedingung senden*/

}
int main(void)
{

i2c_start(SD20_W);
i2c_data(0x7F);
i2c_stop();

}


mfg uwe

klucky
28.12.2004, 03:14
So jetzt wird das ganze soweit fehlerfrei kompiliert. Allerdings habe ich immer noch das Problem das es nicht das tut was es soll ;)! Ich wollte damit einen SD20 ansprechen. Ich habe das ganze jetzt mal so geändert das ich es an PortA ablesen kann wenn ein sendeversuch fehlgeschlagen ist.



#include <avr/io.h>
#include <inttypes.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <avr/delay.h>
#include <avr/twi.h>
#include <stdlib.h> /*für exit*/

/*SD20 Adresse mit Lese- oder Schreibbit*/
#define SD20_W 0xC2
#define SD20_R 0xC3

typedef unsigned char BYTE;
typedef unsigned short WORD;

void i2c_start(BYTE ADRESSE)
{

TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); /*Startbedingung senden*/
while (!(TWCR & (1<<TWINT))); /*Darauf warten dass TWINT gesetzt wurde was aussagt das die Startbedingung gesendet wurde*/
if ((TWSR & 0xF8) != TW_START) PORTA=0x01; /*Überprüfen ob START erfolgreich gesendet wurde sonst abbrechen*/
TWDR = ADRESSE; /*Slave Adresse in TWDR laden*/
TWCR = (1<<TWINT)|(1<<TWEN); /*TWINT und TWEN löschen damit die ADRESSE gesendet wird*/
while (! (TWCR & (1<<TWINT))); /*Darauf warten dass TWINT gesetzt wurde was aussagt dass die ADRESSE gesendet wurde*/
if ((TWSR & 0xF8) != TW_MT_SLA_ACK) PORTA=0x02; /*Überprüfen ob ADRESSE erfolgreich gesendet wirde sonst abbrechen*/

}
void i2c_data(BYTE DATA)
{

TWDR = DATA; /*DATA in TWDR laden*/
TWCR = (1<<TWINT)|(1<<TWEN); /*TWINT und TWEN löschen damit die DATA gesendet wird*/
while (! (TWCR & (1<<TWINT))); /*Darauf warten dass TWINT gesetzt wurde was aussagt dass die DATA gesendet wurde*/
if ((TWSR & 0xF8) != TW_MT_DATA_ACK) PORTA=0x04; /*Überprüfen ob DATA erfolgreich gesendet wirde sonst abbrechen*/

}
void i2c_stop(void)
{

TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO); /*Stopbedingung senden*/

}
int main(void)
{

DDRA=0xFF;
PORTA=0x0;

i2c_start(SD20_W);
i2c_data(0x01);
i2c_data(0x7F);
i2c_stop();

while(1)
{}

}


Und bei mir wird immer der PortA auf 0x02 geschaltet also bleibt das Programm an folgender stelle hängen:



if ((TWSR & 0xF8) != TW_MT_SLA_ACK) PORTA=0x02;


woran könnte das liegen?

So das habe ich noch zum ansprechen eines SD20 auf der Roboter-Teileseite im Forum gefunden:

Ein Schreibzugriff läuft also wie folgt ab:

- Startbedingung
- Adresse senden RW-Bit LOW (0xc2 / 194)
- Register senden (z.B. 1 für Servo 1)
- Wert schreiben (127 für Mittelstellung)
- Stopbedingung

Läuft mein schreibzugriff auch so hab oder habe ich da etwas falsch gemacht?

klucky
28.12.2004, 18:04
Kann das vielleicht auch daran liegen das der Atmel mit 16 Mherz und der SD20 mit 8 Mherz läuft und das der Atmel somit egentell einen zu schnellen Tackt vorgibt und der SD20 net mithalten kann?

muraad
29.12.2004, 12:15
Das hab ich noch garnicht gesehen aber du initialisierst in deinem Code nie den I2C Takt. Dafür gibt es zwei register die die CPU Clock teilen. Ich weiß grad nicht auswendig die Register, aber du solltest mal im Datenblatt nachschauen, da wird es am Anfang des TWI Kapitels erklärt.
Ich hab grad doch nochmal nachgeschaut. Füge diese Zeile Code am Anfang deines Programms ein.
TWBR=10;
TWPS nicht ändern das bleibt 1, also 00.
Damit kommst du bei einem CPU Takt von 16Mhz auf 166,7kHz, das dürte auch für alle nicht fast I2C Devices reichen. Die Formel ist übrigens
I2C Frequenz= CPU Frequenz/(16+2*TWBR*4<hoch>TWPS)
wobei TWPS die Prescaler Bits sind.
I2C Frequenz=16MHz/(16+2*10*4)=166,7 kHz.
Hoffe konnte dir nochmal helfen
Gruß Muraad