Hallo! Ich habe ein Problem mit dem Starten des TWI: Ich verwende die TWI kommunikation, so wie sie im Datenblatt verwendet wird. Allerdings: Er geht mir nicht mehr aus der While Schleife unter twi_start() raus. while (!(TWCR & (1<<TWINT)));//Wenn Bus Frei ist: Außerdem habe ich keine ahnung, wie das mit den auskommentierten zeilen darunter funktionieren soll (habe ich aus dem datenblatt, da ich nicht weiß was in der Konstanten START drinstehen sollte... Ich bitte um Hilfe. main: #include <avr/io.h> #include "uart.h" #include "twi_bib.h" #include "lcd.h" #include <util/delay.h> #define F_CPU 3000000UL #define DevPCF8574P 0b01000000 // device address of DS1678, see datasheet #define Display 0x74 int main(void) { twi_init(); // init I2C interface uart_init(); DDRB = 0xff; // use all pins on port B for output PORTB = 0xff; GICR|=0x20; MCUCR=0x00; MCUCSR=0x40; GIFR=0x20; TIMSK=0x05; uart_puts("\n\n\rHallo! Ich melde mich sofort am System an:\n\r"); uart_puts("\n\n\rProbiere zu Starten:\n\r"); twi_start(); PORTB = 0xf0; uart_puts("\n\n\rStart hat funtktioniert!"); while(1); return 0; //Wird nie erreicht } verwendete TWI-funktionen: void twi_init() { TWAR=0x00;//Slave Adress für I2C wird aber nicht benötigt //scl-Freq=CPU-Freq/(16+2(TWBR)*4^(Prescaler-Bits(siehe 1))) TWBR=0x00;//Da wir 1/16 der CPU-Frequenz wollen. TWCR=0x04;//Kein Interrupt/Kein Acknol./TWI Aktivieren } short int twi_start() { TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);//Setzt Start while (!(TWCR & (1<<TWINT)));//Wenn Bus Frei ist: //if((TWSR&0xF8)!=START) // return 0; //else return 1; }
Schau mal ob du die Pull-Ups drin hast und ob du du ein Acknowledge bekommst (von einem TWI-Slave).
Danke für deine Antwort: Also Pull Ups sind drin, gnd ist mit dem GND von dem stk-500 verbunden... Der slave hat auch die benötigten 5V. Allerdings habe ich keine ahnung wie ich das acknolage kontrollieren sollte... Wäre es möglich, dass ich das TWSR register irgendwie überprüfen kann? irgendwie steht da was im datenblatt von dem register, allerdings habe ich keine ahnung wie das funktionieren sollte. Also das Problem nochmals.... Er geht in das Start-Unterprogramm rein und dann warte ich ca. 4 min und erst dann kommt er aus dem unterprogramm raus... Ich habe am I2C nur ein Display angeschlossen(EAT123A-I2C)
Ein Logic-Analyzer oder ein DSO wäre hilfreich. Dann könntest du schauen was dein TWI treibt. Schon mal das I2C Master Interface von Peter Fleury ausprobiert? Man muss das Rad ja nicht nochmal erfinden. (http://homepage.hispeed.ch/peterfleury/avr-software.html#libs) Einfach twimaster.c ins Projekt und i2cmaster.h einbinden. Dann noch i2c_init(); und i2c_start(); usw. Nicht vergessen die Rückgabewerte auszuwerten.
Hallo! Danke für die Antwort: Ja ich habe es schon mal ausprobiert mit dem fleury, aber auch ohne erfolg... Ich weiß wirklich nicht was da schuld sein soll. Es müsste doch auch so gehen, wenn ich den code vom MEGA 16 datenblatt verwende... oder sehe ich das falsch... ich bin schon sehr frustriert, da ich schon seit wochen den fehler versuche zu finden.... gibt es denn sonst nichts? (Logic analyser ist denke ich ein problem, da dies ein schulprojekt ist und wir an der schule nicht das nötige kleingeld dafür haben.
Also erstmal musst du pruefen ob an den SDA und SCL Pins vom AVR tatsaechlich high-pegel liegen (I2C braucht Pull-ups! entweder externe oder die von den Portpins muessen eingeschaltet sein). Wenn nicht beide Pins im Ruhezustand high sind wird der AVR glauben der I2C Bus sei belegt und NIE das START-Signal ausgeben. zu der Konstante "START": jedes mal wenn irgendwas auf dem Bus passiert ist (START gesendet, daten gesendet, daten empfangen etc.) wird das TWINT-Flag in TWCR gesetzt, das du ja schon auswertest. TWSR gibt dann an, was genau passiert ist. Du willst pruefen ob die START-Bedingung tatsaechlich gesendet wurde (es koennte auch z.B. Busfehler auftreten oder sowas, musst mal im Datenblatt nachlesen). Das tust du indem du auf die entsprechende Konstante vergleichst, alle die im Datenblatt vorkommen sind auch in der avr-libc in der Datei <util/twi.h> definiert.
Also wenn ihr an der Schule öfter mit Embedded Systemen arbeitet ist die Anschaffung eines Intronic Logigport zu empfehlen. Den bekommt man für knapp 300€ und deine wochenlange Suche verkürzt sich in den meisten Fällen auf einige Stunden. Ich denke dein Problem liegt bei der Adressierung des EAT123A. Was du noch überprüfen solltest: - Verwendest du die richtige I2C Slave-Adresse für dein Display? Wenn ich das richtig gesehen habe verwendet dein EAT123A entweder die 0x36 oder die 0x37 (hängt wohl von einem SA0-Pin ab?) - teste mal nochmal mit Fleury und achte darauf, daß du die Adresse richtig übergibst: i2c_start((slave_address<<1)+I2C_WRITE)
Hallo nochmal... Also das mit dem Intronic Logigport liegt nicht in meiner hand, da ich nur schüler bin und nicht bestimmen kann, was wann wo gekauft wird. Aber danke für den hinweis, ich werde es einem verantwortlichen sagen. und das START entspricht das dann unter GCC dem TW_START? würde die zeile dann so lauten: if((TWSR&0xF8)!=TW_START) Ich habe nochmal die Library von dem fleury genommen und bin darauf gekommen, dass das i2c display zumindest darauf reagiert... also wenn ich es anspreche, dann bekomme ich ein ack. zurück und wenn ich dem display sage, es soll gelöscht werden, dann tut es das auch, allerdings wenn ich ihm sage es sollte was anzeigen, dann macht es das nicht mehr... kann das daran liegen, dass zwischen den einzelnen paketen die gesendet werden eine kurze pause sein soll? (habe mit 200us pause und ohne pause probiert, geht aber beides nicht!) und ich glaube dass auch kein hardware-fehler mehr vorhanden ist, da er sofort einen fehler schreibt, wenn ich irgendwas ausstecke, also fehler erkennen das tut er. er löscht ja auch das display ordnungsgemäß (Das display ist vorher nur schwarz) hier mein code: //zur info: #define Display 0x74 ret = i2c_start(Display+I2C_WRITE); // set device address and write mode uart_putshortint(ret); if ( ret == 1) {//Wenn Fehler /* failed to issue start condition, possibly no device found */ i2c_stop(); uart_puts("Error beim Starten der Kommunikation:\n\r"); } else { PORTB=0xf0; uart_puts("Juhuu I hob starten kinna.\n\r"); /* issuing start condition ok, device accessible */ //_delay_us(200); //i2c_write(Display); // Control byte for init //_delay_us(200); i2c_write(0x00); // Control byte for init //_delay_us(200); i2c_write(0x3C); //Selects 4-line display //bis einschließlich hierher macht er alles, was er machen sollte... alles darunter ist sinnlos, da er es nicht macht// //_delay_us(200); i2c_write(0x0E); //turns on display and cursor //_delay_us(200); i2c_write(0x06); //Laut datenblatt benötigt i2c_start(Display+I2C_WRITE); //_delay_us(200); i2c_write(0x00); // Controll Byte for Write //_delay_us(200); i2c_write(0x50); //P //_delay_us(200); i2c_write(0x48); //H //_delay_us(200); i2c_stop(); Das PDF zum Displays ist hier: http://www.mpi.ch/files/attach/000013d1.pdf greetz
Also mich würde es trotzdem interessieren, warum bei mir das TWINT-Bit nicht gesetzt werden kann.. Habt ihr eine idee? Wenn ich mit der anderen bibliothek eine "verbindung" zusammenbringe, dann kann es ja wohl schlecht ein hardware-fehler sein oder? Also müsste ich irgendwas beim intitalisieren falsch haben oder? Oder muss ich irgendwo interrupts oder so aktivieren...
Martin Wührer wrote: > und das START entspricht das dann unter GCC dem TW_START? > würde die zeile dann so lauten: if((TWSR&0xF8)!=TW_START) Da kann ich auf die Schnelle nix dazu sagen weil ich eben mit dem I2C Master Interface arbeite. > kann das daran liegen, dass zwischen den einzelnen paketen die gesendet > werden eine kurze pause sein soll? (habe mit 200us pause und ohne pause > probiert, geht aber beides nicht!) Ich wüsste nicht warum man da eine Pause machen soll. Wie kommst du darauf? Du bist auf dem richtigen Weg. Wenn du noch ein bisschen das Datenblatt und den Abschnitt "Two-wire-Interface" von der µC-Spec durchforstest findest du deinen Fehler denk ich mal. > //bis einschließlich hierher macht er alles, was er machen sollte... > alles darunter ist sinnlos, da er es nicht macht// > > //_delay_us(200); > i2c_write(0x0E); //turns on display and cursor > //_delay_us(200); > i2c_write(0x06); //Laut datenblatt benötigt > > i2c_start(Display+I2C_WRITE); Versuchs hier mal mit einem i2c_rep_start() statt i2c_start(). Ein Hardwarefehler ist es nicht. Interrupts aktivierst du übrigens mit sei(); und deaktivierst sie mit cli();
Hallo braucht man für i2c interrupts? Wo ist denn sei() definiert? Wo könnte denn deiner ansicht nach der fehler am ehesten liegen?
Nein, man braucht nicht unbedingt Interrupts. Man kann auch das TWCR auch pollen. Das machen z.B. die Fleury-Routinen. Der Fehler liegt denk ist da, daß du nicht wirklich tief drin steckst in deinem Thema. Dir fehlen Grundkenntnisse in Bezug auf µC als auch in Sachen strukturierte Programmierung. Vielleicht solltest du dir das eine oder andere AVR-GCC-Tutorial vornehmen. Dein I2C-Bus funktioniert ja anscheinend, deshalb liegt der Fehler wohl eher darin wie du das Display an sich ansteuerst. Schau dir das Datenblatt genauer an.
Hallo nochmal! Naja mir ist aufgefallen, dass ich die SDA/SCL Pins nicht definiert habe! (das erklärt auch, warum meine selbstgeschriebenen funktionen nicht funktionieren! jedoch die anderen schon!) Wie definiert man die? mfg
I have a LCD display (EA T123A-I2C) but the code erase all the display and do not show any character, do you have any idea ? ;____________________________________________________________________ ; SENDDATA ; Send all the sequence to the slave (slave address + data (OUTPUT)) SENDDATA: Again: ; send start bit CALL STARTBIT ; acquire bus and send slave address ; send slave address MOV A, SLAVEADD LCALL SENDBYTE ; sets NOACK if NACK received JB NOACK, STOPSEND ; if no acknowledge send stop ;send the control byte for fonction set RS = 0 MOV A, #00h LCALL SENDBYTE ; sets NOACK if NACK received --many control commands follow MOV A, #2Ch ;send fonction set for 4-lines display LCALL SENDBYTE call DELAY MOV A, #0Eh ;turns ON display and cursor LCALL SENDBYTE MOV A, #06h ;turns ON display and cursor LCALL SENDBYTE AAA: call DELAY CALL STARTBIT ; acquire bus and send slave address MOV A, #074h ;turns ON display and cursor LCALL SENDBYTE MOV A, #40H ;send the control byte for fonction set RS = 1 LCALL SENDBYTE MOV A, #50H ;write to DDRAM (value ' P_ ' ) LCALL SENDBYTE MOV A, #48h ;send a control byte (value ' PH_ ' ) LCALL SENDBYTE NOP STOPSEND: CALL STOPBIT ; sends stop bit JNB NOACK, SENDRET ; if slave sends NACK send error SETB ERR ; sets the error flag SENDRET: JMP SENDRET RET ; SENDBYTE ; Send 8-bits in ACC to the slave SENDBYTE: MOV BITCNT,#8 ; 8 bits in a byte MOV R0,#8 ; 8 bits in a byte mov delayTime,#10 SETB MDE ; to enable SDATA pin as an output CLR MCO ; make sure that the clock line is low SENDBIT: RLC A ; put data bit to be sent into carry MOV MDO,C ; put data bit on SDATA line SETB MCO ; clock to send bit CLR MCO ; clear clock ;DJNZ BITCNT,SENDBIT ; jump back and send all eight bits DJNZ R0,SENDBIT ; jump back and send all eight bits ;NOP; wait small for the slave to acknowledge CLR MDE ; release data line for acknowledge SETB MCO ; send clock for acknowledge --->the is the 9th bit NOP ;call DELAY JNB MDI,NEXT ; this is a check for acknowledge SETB NOACK ; no acknowledge, set flag NEXT: CLR MCO ; clear clock NOP RET
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.