Hallo ihr! Hab ein Problem, das Doppelregister UCSRC wird nicht gesetzt. Ich habe ein Pollin Platine und diesen Programm-code. Wenn ich im Einzelstep-Betrieb durch den Code gehe, dann wird nie das UCSRC Register gesetzt. Hat vielleicht jemand eine Idee warum? Danke schonmal vorab... #define F_CPU 16000000UL //CPU Takt vorgeben #include <avr/interrupt.h> #include <avr/io.h> //#include <lcd_func.h> #include <util/delay.h> void usart_init(void); //Funktion USART Initialisieren void uart_putc(unsigned char c) { while (!(UCSRA & (1<<UDRE))); /* warten bis Senden moeglich */ UDR = c; /* sende Zeichen */ } void uart_puts (unsigned char *s) { while (*s) { /* so lange *s != '\0' also ungleich dem "String-Endezeichen" */ uart_putc(*s); s++; } } //Hauptprogramm int main (void) { unsigned char string[8]= "Hallo"; usart_init(); //USART Initialisieren uart_puts(string); while(1); return 0; } //Funktion zur Initialisierung des USART //Baudrate=9600, Datenbits=8Datenbits //kein Parrity, 1Stopbit, asynchron void usart_init(void) { unsigned int baud = 0x0067; //Baudrate=9600; 16Mhz/(16*9600)-1=103,17=0x67 //UCSRC = 0x80; //UCSRC = UCSRC | 0xFF; UBRRH=(unsigned char)(baud>>8); //High Byte der Baudrate UBRRL=(unsigned char)baud; //Low Byte der Baudrate // Aktivieren von receiver und transmitter UCSRB = (1<<RXEN)|(1<<TXEN); UCSRC = (1<<URSEL); // Einstellen des Datenformats: 8 Datenbits, 1 Stoppbit UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); }
Lass das Register einfach in Ruhe. Dessen Voreinstellung ist genau das, was du willst.
Ja, laut der Anleitung musste die Voreinstellung stimmen. Stimmt aber leider nicht, das Register ist bei mir auf 0x00.
@ Thomas (Gast) >Ja, laut der Anleitung musste die Voreinstellung stimmen. >Stimmt aber leider nicht, das Register ist bei mir auf 0x00. Und genau das brauchst du ja! MFG Falk
Du kannst das nicht lesen, weil du dann immer nur das Alternativregister (ist ja ein Doppelregister) liest! Tu dir und uns einen Gefallen und glaube dem Datenblatt, dass die Voreinstellung OK ist und mach einfach weiter an dieser Stelle.
Mit diesem Programm müsste mir der Hyperterminal doch eigentlich das Hallo ausgeben, oder? von RS232 über Nullmodemkabel an PC und die Hyperterminal-Einstellungen wie bei USART.
Thomas wrote: > von RS232 über Nullmodemkabel an PC und die Hyperterminal-Einstellungen > wie bei USART. Wenn Du das Pollinbrett hast, dann brauchst Du ein Verlängerungskabel (1:1) und kein Nullmodemkabel.
1 | UBRRH = 0; |
2 | UBRRL = 7; //47=9k6, 7= 57k6, 3=115k2 bei 7.3728 MHz Quarz |
3 | UCSRB = 1<<RXEN | 1<<TXEN ; |
4 | UCSRC = 1<<URSEL | 1<<UCSZ1 | 1<<UCSZ0; //8N1 |
So geht's, wenn du das UCSRC Register unbedingt nochmal selber setzten willst.
Ich muss euch nochmal nerven. Bekomme nur ein Zeichen (ein großes C mit Punkt drüber) auf dem Hyperterminal dargestellt, wenn ich beim Hyperterminal eine Baudrate tiefer als bei USART_init. Benutze einfaches serielles Verlängerungskabel, Flusssteuerung aus. Hatte dein Eingang TX RX vom MAX232 schon überbrückt, dann bekomme ich das Echo vom Hyperterminal zurück. Was mache ich falsch? Wo muss so ein externer Quarz ran? Danke...
@ Thomas (Gast) >Bekomme nur ein Zeichen (ein großes C mit Punkt drüber) auf dem >Hyperterminal dargestellt, wenn ich beim Hyperterminal eine Baudrate >tiefer als bei USART_init. Warum tiefer? Sie muss GLEICH sein. >Benutze einfaches serielles Verlängerungskabel, Flusssteuerung aus. >Hatte dein Eingang TX RX vom MAX232 schon überbrückt, dann bekomme ich >das Echo vom Hyperterminal zurück. D.h. dein Kabel + MAX sind OK. Bleiubt nur noch der uC. >Was mache ich falsch? Wo muss so ein externer Quarz ran? An den uC. Und dann auch die AVR Fuses so setzen, dass der auch verwendet wird. MFg Falk
Thomas wrote:
> Was mache ich falsch?
Meine gerade aus der Reparatur gekommene Kristallkugel behauptet, dass
du noch mit dem internen RC-Oszillator (1 MHz bei Vcc = 5 V) arbeitest
statt mit einem Quarz.
Thomas wrote:
> Was mache ich falsch? Wo muss so ein externer Quarz ran?
Wo sind denn jetzt die ganzen Experten, die noch vor ein
paar Tagen behauptet haben mit dem internen Takt gäbe es
bei UART überhaupt keine Probleme?
Bin schon neugierig wie ihr diesen Fall jetzt lösen wollt.
>Bin schon neugierig wie ihr diesen Fall jetzt lösen wollt.
Mit konstanter Umgebungstemperatur und kalibriertem Oszillator. ;-)
MW
Karl heinz Buchegger wrote: > Wo sind denn jetzt die ganzen Experten, die noch vor ein > paar Tagen behauptet haben mit dem internen Takt gäbe es > bei UART überhaupt keine Probleme? Es gibt nur ein einziges Problem damit, vermute ich mal: er schwingt einfach mal nicht auf 16 MHz...
So, funktioniert. Externer Quarz war der Schlüssel zur Lösung. Nachdem ich die Fusebits gesetzt hab ging es. Ich danke euch alle... nochmal ne frage zum internen Clock, auf welcher Frequenz läuft der beim Atmega32. Hab irgendwo 1Mhz gelesen. Ist das richtig? Danke nochmal!
default clock source -> 1MHz Internal Calibrated RC Oscillator Operating Modes -> 1/2/4/8MHz
Gast wrote: > Internal Calibrated RC Oscillator Operating Modes -> 1/2/4/8MHz Beim ,,alten'' RC-Oszillator, das waren da noch vier verschiedene Oszillatoren, und automatisch kalibriert wurde nur der erste davon. Die neueren AVRs (das beginnt beim ATmega88 & Co.) haben nur noch einen RC-Oszillator, und der wird automatisch vorkalibriert (in der Regel für einen Betrieb bei Vcc = 5 V). Der Oszillator selbst läuft dort mit 8 MHz, allerdings ist im Auslieferungszustand die CKDIV8-Fuse gesetzt, die den clock prescaler auf 1:8 voreinstellt, sodass er effektiv auch wieder mit 1 MHz startet.
Mein Display funktioniert jetzt jedoch nicht mehr, sobald ich auf externen Quarz umschalte. Kann das an den Delay Schleifen liegen, das dort jetzt eine andere Zeit rein muss?
warum gebe ich dann die Frequnenz vom µC vor, wenn die sowieso abhängig ist von intern oder externen Quarz? #define F_CPU 16000000UL //CPU Takt vorgeben #include <util/delay.h> //Header für delay Mit der 16 x fachen Zeit (vorher 1Mhz intern, jetzt 16Mhz extern) in delay geht es aber leider auch nicht. Danke euch...
An den Parametern der _delay_XX-Aufrufe wird gar nichts geändert! Nur die Taktfrequenz muss richtig angegeben werden. Wenn die stimmt, dann stimmen auch die Wartezeiten.
Kann aber natürlich sein, dass dein Display einfach mal langsamer ist als die Annahmen, die der Code gemacht hat (vielleicht braucht der Controller einfach mehr Zeit, als der originale HD44780 spezifiziert hatte). Solange deine Delays alle auf Grund des falschen Taktes 16x so lange waren, hat's dann noch funktioniert, nun nicht mehr.
Auch muss man die maximalen Werte bei der _delay_ms und _delay_us Funktion beachten. Die Maximalwerte sind nämlich von der F_CPU abhängig und wenn die eigenen Werte diese überschreiten, gibt es keine "Funktionsgarantie" mehr. Unter Umständen muss man also ein _delay_ms(LANGEZEIT) in mehrere _delay_ms(KURZEZEIT) aufteilen. Bei einem Wechsel von 1 MHz auf 16 MHz ist es nahezu sicher, dass hier im Quellcode nachgearbeitet werden muss. Der Maximalwert bei 16 MHz ist nur 1/16-tel des Wertes bei 1 Mhz...
Ging mit 16-fach auch nicht. Also, habe das FuseBit auf 16MHz externen Quarz eingestellt, danach ging das Display nicht mehr. Hab jetzt in der Header von delay die 1Mhz durch 16Mhz ersetzt #ifndef F_CPU /* prevent compiler error by supplying a default */ # warning "F_CPU not defined for <util/delay.h>" #define F_CPU 16000000UL // <-----Hier #endif In meinen Programmkopf steht trotzdem noch mein CPU Takt #ifndef F_CPU #define F_CPU 16000000UL #endif Leider funktioniert es aber immernoch nicht. Habe auch spassighalber mal die Delays verlängert. Auch keine Änderung!
Stefan "stefb" B. wrote: > Auch muss man die maximalen Werte bei der _delay_ms und _delay_us > Funktion beachten. ...Steht aber auch alles in der erwähnten Dokumentation...
#ifndef F_CPU #define F_CPU 16000000UL #endif Das hat nur eine Wirkung, wenn F_CPU nicht anderswo definiert ist. Wenn F_CPU anderswo definiert ist, wird der dortige Wert genommen. Anderswo kann heissen in den Projekteinstellungen (project configuration) von AVR Studio oder im Makefile, wenn du mit WinAVR arbeitest oder AVR Studio mit einem externen Makefile arbeitest. Benutze mal nur #define F_CPU 16000000UL und achte auf Warnungen bzgl. Redefinition von F_CPU bzw. ob das LCD jetzt funktioniert. Wenn du den LCD Code in einem extra *.c File hast, achte darauf, dass dort auch die richtige F_CPU ankommen muss! Es nutzt nix das im main.c zu setzen und im lcd.c wegen fehlendem F_CPU einen anderen Defaultwert zu benutzen.
Johannes M. wrote: > Stefan "stefb" B. wrote: >> Auch muss man die maximalen Werte bei der _delay_ms und _delay_us >> Funktion beachten. > ...Steht aber auch alles in der erwähnten Dokumentation... Für 2008 habe ich mir vorgenommen, einmal am Tag das RTFM zu vermeiden ;-)
So läuft wieder mit den alten Delay Einstellungen. Nur in der Header von delay die neue Frequenz eingestellt. Muss jedoch den Optimierungsgrad auf von Os auf O0 (keine Optimierung) stellen. Andere Optimierungsgrade gehen auch nicht. Leider wird mein Programm dadurch zu groß. Kann ich da noch was dran ändern? Warum wird die Delay Funktion mit Optimiert?
Deine Zeiten sind zu kurz für dein Display! Glaub's doch endlich, statt mit trial&error hier irgendwas zusammenzuwurschteln. Ermittle doch bitte mal einfach systematisch, welche der Zeiten du vergrößern musst, damit das Display wieder ,,spielt''. U. U. ist es nur eine einzige Zeit, an der du was drehen musst, z. B. die für den E-Impuls.
Thomas wrote: > So läuft wieder mit den alten Delay Einstellungen. > Nur in der Header von delay die neue Frequenz eingestellt. > Muss jedoch den Optimierungsgrad auf von Os auf O0 (keine Optimierung) > stellen. Die Funktionen aus der delay.h funktionieren aber nur mit eingeschalteter Optimierung korrekt. Dass es bei Dir jetzt funktioniert, liegt mit Sicherheit daran, dass durch die abgeschaltete Optimierung die Zeiten viel länger sind, als eingestellt.
Die delay Zeiten sind lang genug. Hab den Grund jetzt raus gefunden. Und zwar frage ich ab einer betimmten Stelle bei der Display init nur noch das Busy ab. Dazu werden die Werte von PINB gelesen. Wenn das Display jedoch noch nicht fertig ist, gehe ich in eine Schleife und Frage immer wieder Busy ab. Jedoch wird der Wert an PINB nicht mehr aktualisert. Er bleibt in der Schleife hängen. Hab es schon mit volatile PINB versucht. Klappt aber auch nicht. Werd weiter suchen... #define PINB* (volatile unsigned char*)0x16 //Funktion fragt das Busy des Display2 ab, ob Display bereit ist //neue Befehle zu verarbeiten void dis2_ready(void) { volatile unsigned char a=0; unsigned char busy=1,status; DDRB=0xF0; //B0-B3 Eingänge, B4-B7 Ausgänge while (busy) //Schleife solange Busy=1 { PORTB = 0x00; //EN2=0, RS=0, R/W=0 PORTB = PORTB | 0x10; //R/W=1 PORTB = PORTB | 0x80; //EN2=1 a=PINB; //PORTB lesen, High Nibbel 1 PORTB = PORTB &~ 0x80; //EN2=0 status = (a<<4) & 0xF0; //4x shifting links PORTB = PORTB | 0x80; //EN2=1 a = PINB & 0x0F; //PORTB lesen, low Nibbel 2 PORTB = PORTB &~ 0x80; //EN2=0 status = status | a; if ((status & 0x80)==0x00) busy=0; //Busy=0 Abbruch }
Leg da > PORTB = PORTB | 0x80; //EN2=1 > a=PINB; //PORTB lesen, High Nibbel 1 mal eine kleine Pause dazwischen und gib dem Display ein bischen Zeit auf deinen Leseversuch zu reagieren und die Daten auf den Bus zu legen
Karl heinz Buchegger wrote: > ... mal eine kleine Pause dazwischen und gib dem Display > ein bischen Zeit auf deinen Leseversuch zu reagieren > und die Daten auf den Bus zu legen Jaja, da bin ich seinerzeit auch drüber gestolpert bei meiner LCD-Bibliothek. ;-) Das ist ein AVR-Feature (ist so dokumentiert): Das Sampeln der Eingangsdaten an PINx erfolgt vor dem Aktivieren der Ausgangsdaten von PORTx. Gesampelt wird auf der steigenden Taktflanke des CPU-Taktes, aber die Ausgangsregister werden erst mit der fallenden Flanke aktualisiert. Das LCD müsste also einige 100 ns vorher bereits ahnen, dass es jetzt das BUSY-Bit ausgeben soll... Ein einzelner NOP (oder jeder beliebige andere Befehl) dazwischen genügt. Mit ausgeschalteter Optimierung geht es, weil die PORTx- und PINx- Aktivitäten dann über LDS/STS in mehreren Befehlen realisiert werden.
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.