Forum: Mikrocontroller und Digitale Elektronik Komisches Problem: ein Controller geht der andere nicht (gleiches Programm)


von Flo S. (tuxianer)


Lesenswert?

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

von Fuse (Gast)


Lesenswert?

> Was kann hier das Problem sein?
Bei den Fusebits vielleicht?

von Flo S. (tuxianer)


Lesenswert?

die sind bei beiden gleich.

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Hardwareproblem.

von holger (Gast)


Lesenswert?

>die sind bei beiden gleich.

Sind sie wahrscheinlich nicht. Sonst würde dein
Proggi funktionieren.

von Flo S. (tuxianer)


Lesenswert?

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.

von Jochen R. (josch90)


Lesenswert?

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...

von Flo S. (tuxianer)


Lesenswert?

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.

von Jochen R. (josch90)


Lesenswert?

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...

von Flo S. (tuxianer)


Lesenswert?

naja ich hab den Controller eigentlich nur auf den Sockel gesteckt. Für 
mich sieht das einfach nach nem Produktionsfehler aus.

von Jochen R. (josch90)


Lesenswert?

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.

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

>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!

von Flo S. (tuxianer)


Lesenswert?

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.

von Michael G. (linuxgeek) Benutzerseite


Lesenswert?

Lass uns mal wissen, ob und wann Du das Problem geloest hast ;)

von Michael K. (mmike)


Lesenswert?

@Travel Rec.: Sicher dass es nicht 99,9967% sind ?

von Mikes (Gast)


Lesenswert?

mglw. unterschiedliche Daten im EEPROM!?!?

Spreche aus Erfahrung ;)

Gruß

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

>Sicher dass es nicht 99,9967% sind ?

Das kommt auf die Anwender und auf das Wetter an ;-)

von Flo S. (tuxianer)


Lesenswert?

also den EEprom habe ich nie beschrieben bei beiden Controllern. Ich 
werds aber mal probieren.

von Flo S. (tuxianer)


Lesenswert?

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
}

von Flo S. (tuxianer)


Lesenswert?

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

von holger (Gast)


Lesenswert?

>  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.

von holger (Gast)


Lesenswert?

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.

von B e r n d W. (smiley46)


Lesenswert?

Nach 2 Sekunden? Könnte das der Watchdog sein?

von Flo S. (tuxianer)


Lesenswert?

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.

von Dennis (Gast)


Lesenswert?

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.

von Flo S. (tuxianer)


Lesenswert?

das ist im makefile

F_CPU = 7372800

von Dennis (Gast)


Lesenswert?

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.

von Flo S. (tuxianer)


Lesenswert?

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.

von Gast (Gast)


Lesenswert?

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.

von Flo S. (tuxianer)


Lesenswert?

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.

von Gast (Gast)


Lesenswert?

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

von Flo S. (tuxianer)


Lesenswert?

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

von Gast (Gast)


Lesenswert?

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.

von Gast (Gast)


Lesenswert?

>> UCSR0B müsste für UART 2 zuständig sein.

Sollte natürlich UART 0 heissen

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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
Noch kein Account? Hier anmelden.