Komisches Problem: ein Controller geht der andere nicht (gleiches Programm)

OP #1038492
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
OP #1039320
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
}
OP #1041116
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
Gast #1041138
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.
Gast #1041151
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.
Gast #1041236
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.
Gast #1041253
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.
OP #1041548
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.
Gast #1041554
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.
Gast #1041557
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
Gast #1041560
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.
Moderator Persönliche Seite #1042209
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.
Moderator Persönliche Seite #1042212
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?

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren