- MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad         
Ergebnis 1 bis 10 von 10

Thema: IC2 ohne Libary

  1. #1
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    03.05.2004
    Ort
    Hannover
    Beiträge
    414

    IC2 ohne Libary

    Anzeige

    LiFePo4 Akku selber bauen - Video
    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:

    Code:
    #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:

    Code:
    > "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!

  2. #2
    Gast
    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.

  3. #3
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    23.05.2004
    Ort
    Untersöchering(Bayern,Alpenvorland)
    Alter
    37
    Beiträge
    215
    Du musst die Datei twi.h includen. Da sind die alle definiert.
    Gruß Muraad

  4. #4
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    03.05.2004
    Ort
    Hannover
    Beiträge
    414
    Hab mich jetzt entschieden diese überprüfungen wegzulassen. Mein Quellcode sieht jetzt so aus und es gibt auch keien fehler mehr beim compilieren:

    Code:
    #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.

  5. #5
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    23.05.2004
    Ort
    Untersöchering(Bayern,Alpenvorland)
    Alter
    37
    Beiträge
    215
    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

  6. #6
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    03.05.2004
    Ort
    Hannover
    Beiträge
    414
    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 !

  7. #7
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    14.08.2004
    Ort
    Magdeburg
    Beiträge
    154
    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....





    Code:
    #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

  8. #8
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    03.05.2004
    Ort
    Hannover
    Beiträge
    414
    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.

    Code:
    #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:

    Code:
    	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?

  9. #9
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    03.05.2004
    Ort
    Hannover
    Beiträge
    414
    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?

  10. #10
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    23.05.2004
    Ort
    Untersöchering(Bayern,Alpenvorland)
    Alter
    37
    Beiträge
    215
    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

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Labornetzteil AliExpress