Hallo. Ich bin derzeit dabei mir eine Lüftersteuerung zu basteln, die erweiterungsfähig ist. Deshalb habe ich mich dazu entschieden den I²C zu benutzen, da darüber ja Daten gesendet und empfangen werden können. Nun mein Problem: Der mega8 hat ja hardwaremäßg ein I²C-Port (PC4 und PC5) wie kriege ich das hinn, dass er sich als Ein- und Ausgang konfigurieren lässt? Kann ich da einfach die Lese-/Schreibrichtung umdrehen? Kann man das nur für einen einzigen Pin, also, dass PC0-PC3 und PC5-PC7 Ausgänge bleiben aber PC4 ein Eingang wird? Die Eigentliche Programmierung (Star/Data/Stop) ist kein Problem. Danke schon mal im Voraus. Lars
dazu musst du nichts "einstellen". Wenn Du ihn als I2C benutzt "geht es einfach".. Du musst noch an beide Leitungen einen Pull-Up-Widerstand anbringen.. Bin zufällig auch gerade dabei mich in den I2C einzuarbeiten (DS1621- Temperatur Sensor).. bisher klappt es, nur beim STOP hängt er.. vielleicht jmd nen tip? TWBR = 255; // Baudrate TWSR = TWSR | 1 | 2; TWCR = (1<<7) |(1<<5)|(1<<2); // Startcondition while (!(TWCR & (1<<7))) // warten, dass Start ok ; TWCR = (1<<2); // start beenden if ((TWSR & 0xF8) != 0x08) ;// start error TWDR = 144; // slave address TWCR = (1<<TWINT) | (1<<TWEN); // send slave adr while (!(TWCR & (1<<TWINT))) // warten auf ACK ; if ((TWSR & 0xF8) != 0x18) ; // kein ACK TWDR = 0xEE; // Command byte (was gesendet werden soll) TWCR = (1<<TWINT) | (1<<2); // und raus damit while (!(TWCR & (1<<7))) ;// warten bis gesendet if ((TWSR & 0xF8) != 0x28) ;//error TWCR = (1<<7)|(1<<2)|(1<<4); // Stop while (!(TWCR & (1<<7))) // warten das Stop gesendet ; // hier hängt er und kommt nicht aus der schleife :/
Wenn ich das richtig verstanden habe, dann hast du etwas nicht ganz verstanden G DDRx (Data Direction Register von X) gibt an, ob IN oder OUT; jedes Bit steht für einen Pin; 1 = OUT / 0 = IN PORTx gibt an, was der OUTPUT sein soll, (Besonderheit: ist der entsprechende Pin ein INput, dann wird der PullUp eingeschaltet) PINx ist ein imaginäres Register, das den Zustand der Pins wiederspiegelt, z.B. um Taster abzufragen etc. (bei neueren AVR kann man damit die Pins toggeln) Wenn PC4 ein INput sein soll, dann: ldi r16, 0b1110 1111 out ddrc, r16 Ich hoffe, das war dein Problem, sonst genauer definieren. dave
Wenn das das Problem war... Man kann AFAIK auch die Internen PullUps für TWI nehmen, das hat bei meinem ds1621 auch funktioniert. @Florian: Lass das nach dem Stop doch einfach weg. Ist im Datenblatt auch ohne Stop, aufpassen musste nur, wenn du danach ne neue Übertragung starten willst: es könnte als repeated startcondition erkannt werden. dave
> Lass das nach dem Stop doch einfach weg. Ist im Datenblatt auch > ohne Stop, aufpassen musste nur, wenn du danach ne neue Übertragung > starten willst: es könnte als repeated startcondition erkannt werden. naja.. irgenwie muss das doch gehen? ich muss ja im konkreten fall direkt danach den Befehl "Schick mir die Temperatur" absenden.. also brauch ich ein Stop. Repeated start würde auch gehen, aber da da ne sekunde zwischen liegen muss, die man ja nicht verschwenden will, sollte der TWI schon ein Stop bekommen ;) nur warum geht's nicht? :/
Hardwaremäßig bin ich ja fertig mit dem ganzen Kram, Pullups und so sind alle da. Es Hängt nur an der Programmierung. Start und Stop Kondition sind grade fertig geworden und ich bin derzeit dabei mir eine Datenübertragungsmöglichkeit (übersetzt Paralelle Daten in I²C-Format) zusammenzuschreiben. Das mit dem PC4-Gedöns: Ich meinte eigentlich, ob man nachdem man was gesendet hat, den Pin zu nem Eingang umschalten kann (und nachher wieder zu einem Ausgang). Ich programmiere in Assembly, da bringt mir ein C-Code leider recht wenig. Ich brauche den Input ja nur um mir mein "Acknowledged" abzuholen. Mir fällt da bis jetzt nur ein einen anderen Permanennt als Eingang zu konfiguriren und den dann abzufragen (das wäre kein Problem, ist mir aber zu einfach ;D ) Lars
/******************************************************************** header fuer IIC-HW (C) HPO 08/02 ********************************************************************/ // def's fuer I2C #define SDA 4 // PORTD PIN4 #define SCL 5 // PORTD PIN5 #define ACK 1 // Acknowledge senden #define NACK 0 // NO-Acknowledge senden #define TWINT 7 // BIT7 in TWCR #define TWEA 6 // BIT6 in TWCR #define TWSTA 5 // BIT5 in TWCR #define TWSTO 4 // BIT4 in TWCR #define TWEN 2 // BIT2 in TWCR #define TWIE 0 // BIT0 in TWCR // Slave Adressen ( schreiben) unsigned char adr_lcd = 0x74; // Adr. LCD 0111 0100 unsigned char adr_temp_sens = 0x9e; // Adr. Temeratursensor 1001 1110 unsigned char adr_rtc = 0xd0; // Adr. Realtimeclock 1101 0000 // Variablen fuer I2C unsigned char twcr_byte=0x00,receivebuffer=0x00; // ISR fuer IIC-HW -------------------------------------------------- interrupt [TWI] void twi_isr(void) { // nichts tun } // INIT fuer IIC-HW ------------------------------------------------- void IIC_INIT(void) { // IIC INIT (100kHz) TWSR &= 0xfc; // Vorteiler im IIC STATUS-REGISTER auf "1" ( TWPS1=TWPS0 = 0 ) TWBR=0x0c; // IIC BIT-RATE-Register Manual Seite 165 ( doc2486.pdf ) TWBR = ( CPU_Clock/SCL_Clock - 16) / 2 // TWBR = ( 4MHz/100kHz - 16) / 2 = 12 -> 0x0c } // IIC START -------------------------------------------------------- void IIC_START(void) { TWSR &= 0x02; // Statusregister ruecksetzen twcr_byte= 0x00; twcr_byte = ((1<<TWINT)|(1<<TWSTA)|(1<<TWEN)); TWCR=twcr_byte; while (!(TWCR & (1<<TWINT))); } // IIC STOP --------------------------------------------------------- void IIC_STOP(void) { TWSR &= 0x02; twcr_byte= 0x00; twcr_byte = ((1<<TWINT)|(1<<TWEN)|(1<<TWSTO)); TWCR=twcr_byte; } /* IIC SENDE BYTE --------------------------------------------------- - das zu sendende Byte wird mit der Variable "sendbyte" übergeben -------------------------------------------------------------------*/ void IIC_SEND(unsigned char sendbyte) { TWSR &= 0x02; TWDR = sendbyte; twcr_byte= 0x00; twcr_byte = ((1<<TWINT) | (1<<TWEN)); TWCR=twcr_byte; while (!(TWCR & (1<<TWINT))); } /*------------------------------------------------------------------- IIC EMPFANGE BYTE - in der Variable "receive" wird festgelegt, ob mit ACK oder NACK empfangen wird; - das empfangene Byte ist nach Beendigung der Funk- tion in der globalen Variable "receivebuffer" abgelegt -------------------------------------------------------------------*/ void IIC_REC(unsigned char receive) { TWSR &= 0x02; twcr_byte= 0x00; switch(receive) { case 0: twcr_byte=((1<<TWINT) | (1<<TWEN)); break; case 1: twcr_byte=((1<<TWINT) | (1<<TWEN) | (1<<TWEA)); break; default: break; } TWCR=twcr_byte; while (!(TWCR & (1<<TWINT))); receivebuffer=TWDR; } //********************************************************************** ********************** char Read_I2C (char Adr, char Reg) //IN: Speicheradresse in der Uhr { IIC_START(); // BUS Start IIC_SEND(Adr); // Bus Adresse schreiben IIC_SEND(Reg); // Register ptr auf x IIC_STOP(); // BUS Stopp IIC_START(); // BUS Start IIC_SEND(Adr | 0x01); // Adr. x lesen IIC_REC(NACK); // Sekunden lesen IIC_STOP(); // BUS Stopp return ( receivebuffer); // Sekunden-Byte speichern } //*************************I2C beschreiben********************************************** void Wr_I2C (char Adr, char Reg , char Dat) { IIC_START(); // BUS Start IIC_SEND(Adr); // Adr. x schreiben IIC_SEND(Reg); // Register ptr auf 0x00 IIC_SEND(Dat); // sende Sekunden = 00, Uhr an IIC_STOP(); // BUS Stopp } //********************************************************************** ************
hmm, das löst mein Problem nicht wirklich, vom Programmiren in C habe ich kaum Ahnung. Außerdem ist ja das Senden kein problem, nur das "acknowledged"-Signal stellt eins dar. Lars
Bisher bin ich soweit: ;Startup-command for I²C i2c_start: cbi PORTC,4 ;clear SDA (SCL stays high) rcall delay25us ;call delay routine ret ;go back ;25us Delay between commands. delay25us: ldi temp1, $21 delay25us_: dec temp1 ;decrease brne delay25us_ ;Break if zero ret ;End-command i2c_end: sbi PORTC,5 ;set SCL rcall delay50us sbi PORTC,4 ;set SDA rcall delay50us ret ;Transmit Address (Only for fan-control) i2c_address: cbi PORTC,5 ;clear SCL rcall delay25us cbi PORTC,4 ;clear SDA for 1st adress 0 rcall delay25us rcall pulse ;Transmit-pulse on SCL sbi PORTC,4 ;set SDA for 2nd adress 1 rcall delay25us rcall pulse cbi PORTC,4 ;0 rcall delay25us rcall pulse nop ;0 rcall delay25us rcall pulse nop ;0 rcall delay25us rcall pulse nop ;0 rcall delay25us rcall pulse nop ;0 rcall delay25us rcall pulse nop ;0 rcall delay25us rcall pulse ;Transferpulses on SCL pulse: sbi PORTC,5 ;set SCL rcall delay25us cbi PORTC,5 rcall delay25us ret
Könnt ihr die Dateien nicht einfach anhängen, hier scrollt man sich ja die Finger wund ... Man muss C nicht verstehen, um zu sehen, welche Bits er setzt, löscht bzw. prüft.
Ja, das mit dem setzen und prüfemn ist ja auch nicht das problem, sondern das Problem ist, wie ich dem uC beibringe, das er über PC4 auch daten empfangen kann! Senden oder Empfangen alleine geht ja, nur geht es, dass man zB einen Eingang einfach wärend des Programmes zu nem Ausgang umkonfiguriert? Wen ja ist mein Problem gelöst und den Code krige ich dan selber zusammen. Lars
So wird das nichts. Wenn Du Software-I2C machen willst, dann mußt Du auf die DDRx-Bits zugreifen, die PORTx-Bits für SDA und SCL müssen konstant auf low bleiben. Und wenn Dein Gegenüber auch ein µC ist, dann nützen konstante Delays garnichts, Du must nach jedem Bit warten, bis der den SCL wieder freigegeben hat (SCL = 1). Aber beim ATMega8 nimm das Hardware-I2C, dazu ist es ja da. Peter
Okay, soweit klar. Aber: wie greife ich auf das Hardware I²C per assembly zu? Übrigens ist der gegenüber ein D/A-Converter (TDA8444) den man nicht programmieren kann (naja Adresse kann man ändern). Lars
Um mit Assembler auf den Hardware-I²C zuzugreifen (nennt sich beim Atmel "TWI"): RTFM.
Danke, das ist das Problem wenn man sich nur das Documentation-Summary runterladt.... Das ausführliche Dokument hat mein Problem jetzt gelöst, danke nochmals Lars
>> Das ausführliche Dokument hat mein Problem jetzt gelöst, danke
nochmals
Kannst Du dazu nähere Angaben machen. Ich habe mal nach Datenblatt
Hardware-TWI beim ATmega32 probiert (sollte wie beim ATmega8 sein),
aber der hat sich immer mal zwischendurch aufgehängt, sodass ich jetzt
wieder Software-TWI verwende. Auch das Repeated-Start hat nie richtig
funktioniert. Es ging dabei um eine RTC und EEPROMs, aber dass sollte
ja immer gleich sein...
Sven
Ich habe die Hardware noch nicht bekommen, die hängt noch irgendwo in der Post fest. Wenn sie da ist wird die Zusammengebaut (geschätzt 2 Tage) und dann gibts einen Bericht, wenn bis dahein das Betriebssystem steht. Lars
Lars: das was du da im Code machst, ist aber kein Hardware-I2C sondern ein Software-I2C.. Der HW-I2C macht dir die Takte z.B. selber.. auch start und stop brauchst du nicht "manuell" hoch/runterzuziehen.. das was du da machst, kannst du mit beliebigen PINs machen, die I/O können..
Kann man das so machen, wie im Anhang? Müsste funktionieren, es sei denn er mag dass mit dem Variablen übergeben nicht. Kann das ja erst prüfen wen die Hardware da ist. Lars
Jo das habe ichjetzt auf die reihe bekommen mit Soft/Hardware, wusste die Befehle dafür nicht, da ich nur n zusammengefasstes Datenblatt hatte (21 Seiten gegenüber 305 Seiten). In der ausführlichen Dokumentation steht das mit dem Hardware I²C drinne, den ich jetzt auch verprogrammiert habe. Lars
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.