Hallo, ich habe ein seltsames Problem ich habe 2 Platinen. Darauf ist erstmal nur die AVR Grundkonfiguration. Mit 7805 und Abblock Kondi, ISP. Nun habe ich 2 Mega162 einen älteren und einen neueren. Ich betreibe die Platine mit nem 7,3728 MHz Baudratenquarz. Dieser hat 2 26pF Lastkondensatoren. Das Programm benutzt den USART. Ich stlle damit die Verbindung zwischen meinem Taschenrechner und dem Mega her. Nun das Problem ich habe auf beide Megas das gleiche Programm und die gleichen Fuses geschrieben. Der Programmer meint auch Equal bei den Programmen. Der eine Mega kommuniziert wunderbar auf beiden Platinen. Der andere auf gar keiner. Da kommt auf dem Rechner ein Com Error. Wenn ich jedoch ein kleines Programm auf den Mega schreibe, wo die Kommunikation nicht klappt also nur Port setzen. Dann Funktioniert dieses Programm. Die UART Pins Funktionieren auch ich kann RX und TX auf High stellen. Was kann hier das Problem sein? Viele Grüße Florentin
> Was kann hier das Problem sein?
Bei den Fusebits vielleicht?
die sind bei beiden gleich.
>die sind bei beiden gleich.
Sind sie wahrscheinlich nicht. Sonst würde dein
Proggi funktionieren.
die Fuses sind definitiv gleich. Ich habe jetzt mal 2 22p Lastkondensatoren genommen, da wird der Controller gar nicht mehr erkannt. An der Platine kanns nicht liegen. Der eine Controller funtzt ja auf beiden.
Schmeiss den einen einfach weg un bestell dir nen neuen ;) Vlt hat der doch ma n schlag gekrigt und hardwareseitig ist was am Uart durchgebrannt...
hmm...sieht echt danach aus. also mit nem Externen Oszi geht das Programm auch nicht. na dann werde ich mir wohl einen neuen bestellen müssen. Aber der war ganz neu.
Wie stehts bei dir mit ESD Schutz? eigendlich sind ja die Megas nicht soo empfindlich, aber ein paar grundlegende sachen dazu sollte man meiner meinung nach schon einhalten...
naja ich hab den Controller eigentlich nur auf den Sockel gesteckt. Für mich sieht das einfach nach nem Produktionsfehler aus.
Also ich versuche immerhin den controller nicht an den Kontakten zu berühren und mich, wenn möglich, zuvor zu Erden. Kann natürlich sein dass der controller in der PRoduktion einen fehler hatte, ich weis nicht in wie weit die geprüft werden.
>Für mich sieht das einfach nach nem Produktionsfehler aus.
Vorsicht mit solchen Aussagen, in 99,9957% der Fälle hat der Anwender
das Problem verursacht!
naja ich werde in Zukunft auch mehr auf ESD Schutz achten. Aber ich hatte eigentlich nicht nie Probleme dadurch. Aber es schadet ja auch nicht sich mal zu entladen an der Heizung.
Lass uns mal wissen, ob und wann Du das Problem geloest hast ;)
@Travel Rec.: Sicher dass es nicht 99,9967% sind ?
mglw. unterschiedliche Daten im EEPROM!?!? Spreche aus Erfahrung ;) Gruß
>Sicher dass es nicht 99,9967% sind ?
Das kommt auf die Anwender und auf das Wetter an ;-)
also den EEprom habe ich nie beschrieben bei beiden Controllern. Ich werds aber mal probieren.
ich habe jetzt nochmal auf den Funktionierenden Controller ein Programm geschrieben, was permanent was sendet über den USART. Direkt nach dem Programmieren kann ich das Signal am USART messen. Nachdem ich allerdings den Strom trenne und wieder verbinde kommt kein Signal mehr. Wenn ich den Resetpin manuell auf Low ziehe kommt wieder ein Signal. Den Resetpin habe ich mittel 10k Widerstand auf VCC gezogen. Ich habe auch mal einen 100nF kondensator von Reset gegen GND geschalten. Das brachte allerdings auch nichts. Manchmal kommt kurz ein Signal, wenn ich wieder Strom anschließe. Anscheinend mache ich irgendwas falsch. Nur was?Das andere Porgramm funktioniert ja genau auf dem Controller und läuft über den gleichen USART. Hier der Quelltext:
1 | #include <avr/io.h> |
2 | #include <avr/interrupt.h> |
3 | #include <inttypes.h> |
4 | #include <util/delay.h> |
5 | |
6 | #define BAUD 9600L // Baudrate, das L am Ende ist wichtig, NICHT UL verwenden!
|
7 | |
8 | #define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1) // clever runden
|
9 | #define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1))) // Reale Baudrate
|
10 | #define BAUD_ERROR ((BAUD_REAL*1000)/BAUD-1000) // Fehler in Promille
|
11 | |
12 | |
13 | |
14 | #define AKTIV 1
|
15 | #define INAKTIV 0
|
16 | |
17 | |
18 | |
19 | |
20 | // Variablen für USART Senden
|
21 | volatile uint8_t irq_send_num0; |
22 | volatile uint8_t irq_send_num1; |
23 | uint8_t irq_send_cnt0; |
24 | uint8_t irq_send_cnt1; |
25 | uint8_t irq_send_buf0[50]; |
26 | uint8_t irq_send_buf1[50]; |
27 | |
28 | |
29 | |
30 | /**********************************************************
|
31 | USART-UDRE-Interrupthandler (SENDEN)
|
32 | ***********************************************************/
|
33 | |
34 | #define USART0_UDRE_ANSCHALTEN() ( UCSR0B |= (1<<UDRIE0) )
|
35 | #define USART0_UDRE_ABSCHALTEN() ( UCSR0B &= ~(1<<UDRIE0) )
|
36 | |
37 | // UART0 UDR EMPTY Interrupt --> jetzt Senden wenn was da ist
|
38 | ISR(USART0_UDRE_vect) |
39 | {
|
40 | if (irq_send_num0) |
41 | {
|
42 | UDR0 = irq_send_buf0[irq_send_cnt0++]; |
43 | irq_send_num0--; |
44 | }
|
45 | |
46 | if (!irq_send_num0) |
47 | {
|
48 | USART0_UDRE_ABSCHALTEN(); |
49 | irq_send_cnt0 = 0; |
50 | }
|
51 | }
|
52 | |
53 | |
54 | |
55 | void Transmit0(char Senden) |
56 | {
|
57 | |
58 | while(irq_send_num0); |
59 | |
60 | irq_send_buf0[0] = Senden; |
61 | irq_send_num0 = 1; |
62 | USART0_UDRE_ANSCHALTEN(); |
63 | }
|
64 | |
65 | |
66 | |
67 | int main(void) |
68 | {
|
69 | uint8_t c; |
70 | |
71 | // Baudrate 9k6 UART0
|
72 | UBRR0H = UBRR_VAL >> 8; |
73 | UBRR0L = UBRR_VAL & 0xFF; |
74 | |
75 | |
76 | // Uebertragungsart
|
77 | UCSR0C |= (1<<URSEL0)|(1<<USBS0)|(1<<UCSZ01)|(1<<UCSZ00); |
78 | |
79 | //Interrupts, Senden und Empfangen aktivieren
|
80 | UCSR0B |= (1<<RXCIE0)|(1<<RXEN0)|(1<<TXEN0); // UDRIE0 wird erst beim Senden aktiviert |
81 | |
82 | |
83 | // Interrupts global aktivieren
|
84 | sei(); |
85 | while(1) |
86 | {
|
87 | irq_send_buf0[0] = 0x06; |
88 | irq_send_num0 = 1; |
89 | USART0_UDRE_ANSCHALTEN(); |
90 | }
|
91 | |
92 | |
93 | }
|
ich habe nochmal den Controller auf der anderen Platine probiert, die hat nen Oszillator und da habe ich das gleiche Problem auch mit nem anderen Programm. Nach dem Manuellen Reset geht alles 1a. Nach dem Strom neu anlegen funktioniert der UART ca. 2 Sekunden danach geht nichts mehr. Ich weis nicht was ich falsch gemacht habe. Ich habe alle Lötstellen nochmal erhitzt, das hat auch nichts gebracht. Gruß Florentin
> while(1) > { > irq_send_buf0[0] = 0x06; > irq_send_num0 = 1; > USART0_UDRE_ANSCHALTEN(); > } Das wird natürlich gar nichts senden. Von alleine springt das Programm nicht in den Interrupt um dort dann in UDR0 zu schreiben.
Vergiss meinen letzten Post :( >Nachdem ich allerdings den Strom trenne und wieder >verbinde kommt kein Signal mehr. Da würde ich mal die Brown Out Fuse programmieren. Level so weit wie möglich an dein VCC ran.
Nach 2 Sekunden? Könnte das der Watchdog sein?
hat ich eigentlich alles schon probiert. Also Watchdog ist in den Fuses aus und ich hats auch mal im Programm dissabled. Die Brown Out habe ich schon deaktiviert bzw. den höchstmöglichen wert genommen.
In dem Quelltext von oben finde ich irgendwie nirgendwo eine Quarzdefinition. Also keine Angabe, wie schnell Dein Quarz eigentlich ist. Vielleicht ist das Dein Problem. Bei der Baudratenberechnung steht F_CPU drin, aber definiert wird die nirgends.
das ist im makefile F_CPU = 7372800
Okay, dann passt das. Hab auch erst jetzt gelesen, daß auf Deiner Platine ein Abblockkondensator drauf ist. Frage: Wenn Du den Strom länger trennst, eine Minute zum Beispiel, läuft das Programm dann nach dem Wiedereinschalten korrekt an, oder hakt's dann trotzdem? Hatte nämlich auch mal so ein Problem, der Abblock-C hat sich erst entladen müssen. Wenn ich den Strom zu schnell wieder eingeschaltet hab, hat sich jedesmal der µC aufgehängt.
so ich habe jetzt mal den Fehler lokalisiert. Hier mal das wichtigste aus dem code:
1 | volatile unsigned char ucUDR1 = 0; |
2 | volatile unsigned char ucUDR_valid1 = 0; |
3 | volatile unsigned int uiVerloreneZeichen1; |
4 | |
5 | ISR(USART1_RXC_vect) |
6 | {
|
7 | //UART1 Interrupt Routine
|
8 | if (ucUDR_valid1) |
9 | uiVerloreneZeichen1++; |
10 | |
11 | //Empfangenes Byte in ucUDR1 einlesen
|
12 | ucUDR1 = UDR1; |
13 | |
14 | //ucUDR_valid1 setzen
|
15 | ucUDR_valid1 = 1; |
16 | }
|
17 | |
18 | int main (void) { |
19 | UBRR0H = UBRR_VAL >> 8; |
20 | UBRR0L = UBRR_VAL & 0xFF; |
21 | |
22 | |
23 | UBRR1H = UBRR_VAL >> 8; |
24 | UBRR1L = UBRR_VAL & 0xFF; |
25 | |
26 | UCSR1C |= (1<<URSEL1)|(1<<USBS1)|(1<<UCSZ11)|(1<<UCSZ10); |
27 | UCSR0C |= (1<<URSEL0)|(1<<USBS0)|(1<<UCSZ01)|(1<<UCSZ00); |
28 | |
29 | UCSR1B |= (1<<RXCIE1)|(1<<RXEN1)|(1<<TXEN1); |
30 | UCSR0B |= (1<<RXCIE0)|(1<<RXEN0)|(1<<TXEN0); |
31 | }
|
wenn ich das lösche:
1 | ISR(USART1_RXC_vect) |
2 | {
|
3 | //UART1 Interrupt Routine
|
4 | if (ucUDR_valid1) |
5 | uiVerloreneZeichen1++; |
6 | |
7 | //Empfangenes Byte in ucUDR1 einlesen
|
8 | ucUDR1 = UDR1; |
9 | |
10 | //ucUDR_valid1 setzen
|
11 | ucUDR_valid1 = 1; |
12 | }
|
tritt der Fehler auf.
Natürlich passiert das wenn Du den Interrupt im Main-Code aktivierst, es aber keine Interrupt Service-Routine im gesamten Code dann zu dem entsprechenden Interrupt gibt. Wenn Du die oben genannte Routine löscht würde ich mal über UCSR1B |= (1<<RXCIE1)|(1<<RXEN1)|(1<<TXEN1); nachdenken das ebenso zu entfernen oder den Int. abzustellen.
ja genau das habe ich mir auch grade gedacht. Naja also ich brauch am UART0 kein Receive. Da dürfte doch:
1 | UCSR1B |= (1<<TXEN1); |
gehen. Es war eben nur merkwürdig, das nach einem manuellen Reset der Code geht, nach einem automatischen aber nicht.
Ach so vergessen: in Deinem Post weiter oben hört es sich so an als ob Du 100nF oder 10k am Reset angeklemmt hast. Dort sind wie im Tutorial beschrieben aber beide notwendig, der 10k Pullup zieht den Reset pin nach VCC, wo bei der 100nF Kondensator definitiv einen kurzen definierten GND Pegel am Reset Pin bewirkt. Gruß und g. n8
also ich habe einen 100nF zwischen VCC und GND, einen 100k vom Rest gegen VCC und vom Resetpin einen 100nF gegen Ground. Also danke für eure Hilfe! Viele Grüße Florentin
Also lese bitte mal das Datenblatt, ich habe es gerade nicht zur Hand aber: UCSR1B müsste für UART 1 UCSR0B müsste für UART 2 zuständig sein. In Deienem letzten main schaltest Du also beide UART ein und auch die Interrupts, aber Du wertest nicht beide in einer Interrupt routine aus; das führt zu unerklärlichen Fehlern.
>> UCSR0B müsste für UART 2 zuständig sein.
Sollte natürlich UART 0 heissen
Florentin S. wrote: > also ich habe einen 100nF zwischen VCC und GND, einen 100k vom Rest > gegen VCC und vom Resetpin einen 100nF gegen Ground. Eigentlich musst du am RESET-Pin gar nichts zwingend anschalten. Ansonsten sind wohl (in der Appnote AVR040) 10 kΩ, überbrückt mit einer Diode, und 4,7 nF empfohlen. Mit deinem recht großen Kondensator triggerst du u. U. wirklich bereits einen externen Reset (normalerweise genügt aber der power-on reset), und hast noch dazu eine recht lange Anstiegszeit der Flanke. Die sollte eigentlich aber nicht stören, da intern ein Schmitt-Trigger drin ist. Du darfst davon ausgehen, dass jeder AVR einzeln geprüft wird, bevor er ausgeliefert wird. Die Prüfung verursacht einen nicht unwesentlichen Teil der Kosten für den Chip, außerdem wird während dieser Prüfung der Flash-ROM in Betrieb genommen. Den kann man nicht einfach nach der Fertigung benutzen, der muss irgendwie formiert werden.
holger wrote: >> while(1) >> { >> irq_send_buf0[0] = 0x06; >> irq_send_num0 = 1; >> USART0_UDRE_ANSCHALTEN(); >> } > > Das wird natürlich gar nichts senden. > Von alleine springt das Programm nicht in den > Interrupt um dort dann in UDR0 zu schreiben. Ach? Du weißt aber, wie ein UART data register empty Interrupt funktioniert, ja?
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.