ATMega88 UART nimmt erst zweites Zeichen an

#1956459
Lesenswert?

Ich habe für die Hochschule einen Datenlogger auf Basis eines ATMega88 
programmiert. Dieser soll, wenn er ein "R|" über den UART empfängt, die 
im externen EEPROM abgelegten Daten per UART rausschicken. Im Grunde 
funktioniert das ganze. Problem ist allerding:

Beim Erstmaligem Auslesen muss ich die oben genannte Zeichenkette zwei 
mal schicken damit ich die Messdaten bekomme. Das erste "R|" wird 
einfach igoniriert. Die Daten kommen eben erst beim zweiten "R|".

Möchte ich das EEPROM ein zweites mal auslesen, so genügt ein einziges 
"R|", was ja auch richtig ist.

Jemand eine Ahnung woran sowas liegen könnte?
#1956489
Lesenswert?

Ok, nur kurz zum verständnis.
an dem INT0 hängt mein RTC dran der in dem angegebenen Intervall einen 
Interrupt auslöst und somit die Messung startet. Das delay kommt noch 
weg.
Der INT1 wird ausgelöst, nachdem ich meinen Stecker für den UART 
angeschlossen habe. Und in dieser ISR wird INT0 deaktiviert. Von daher 
dürfte das delay in der ISR INT0 nicht von Bedeutung sein.

Hier nochmal die Initialisierung des UARTS:
1
#include <avr/io.h>
2
#include "usart.h"
3

4
#define BAUD 9600UL      // Baudrate
5
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
6

7

8
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
9
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD)      // Fehler in Promille, 1000 = kein Fehler.
10

11
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
12
  #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch!
13
#endif
14

15

16
void USART_INIT(void)
17
{
18
  UBRR0 = UBRR_VAL;
19
  
20
  USART_UCSRB |= (1 << USART_TXEN) | (1<<USART_RXEN) | (1<<USART_RXCIE);
21
  USART_UCSRC |= ((1 << UCSZ00) | (UCSZ01));    // muss außer der des Headerfiles angepasst werden
22
}
23

24
void writeChar(unsigned char c)
25
{
26
  while (!(USART_UCSRA & (1<<USART_UDRE)));
27
    USART_UDR = c ;
28
}
29

30

31
uint8_t uart_getc(void)
32
{
33
    while (!(USART_UCSRA & (1<<USART_RXC)));   // warten bis Zeichen verfuegbar
34
    return USART_UDR;                          // Zeichen aus UDR an Aufrufer zurueckgeben
35
}
Gast #1956490
Lesenswert?

Es mag eine dumme Frage sein aber warum wartest du nach Eintreten des 
ISR 20ms (500!!! ms)? Welchen Sinn hat das denn? Und bei deinem UART 
fragst du auch nicht ob ein 'R|' kam sondern lediglich nach '|'. 
Initialisiert wird er richtig sein, nutzt ja die AVR-Bibliothek dafür. 
Wie gesagt, schau mal wo der Simulator dir sagt, dass es hängt und 
klemmt.
#1956492
Lesenswert?

und die uart.h
1
void USART_INIT(void);
2
void writeChar(unsigned char c);
3
uint8_t uart_getc(void);
4

5
#define USART_BAUD_RATE  9600
6
#define USART_UBRRH    UBRR0H
7
#define USART_UBRRL    UBRR0L
8
#define USART_UCSRB    UCSR0B
9
#define USART_UCSRC    UCSR0C
10
#define USART_UCSRA    UCSR0A
11
#define USART_UDRE    UDRE0
12
#define USART_UDR    UDR0
13
#define USART_TXEN    TXEN0
14
#define USART_RXEN    RXEN0
15
#define USART_RXC    RXC0
16
#define USART_RXCIE    RXCIE0
#1956499
Lesenswert?

Die lezte konfiguration war so gewesen, dass der Controller im Powerdown 
war, über den INT0 aufgeweckt wurde, dann wurde die Messung gemacht.

Laut Tutorial und Datenblatt kann man den Controll in diesem Modus nicht 
flankengesteuert sondern  nur levelgesteuert aus dem Powerdown holen.

Durch den Interrupt vom RTC wurde die Routine aber mehrmals durchlaufen. 
Deswegen hatte ich als Provisorium das Delay mit reingeschrieben.

Und das 500ms delay in der INT1 habe ich schon rausgeschmissen, ändert 
aber nichts an der Problematik.
#1956507
Lesenswert?

1
ISR (USART_RX_vect)
2
{
3
  rx[rx_i] = uart_getc();
4

5
    if(rx[rx_i] == '|')
6
    {
7
      rx_valid_command = 1;
8
    }
9
  
10
  rx_i++;
11
}

wenn der interrupt auslöst, steht das zeichen schon bereit und du kannst 
es direkt abgreifen. ich würde es so machen:
1
ISR (USART_RX_vect)
2
{
3
  rx[rx_i] = UDR;
4

5
  if(rx[rx_i] == '|')
6
  {
7
    rx_valid_command = 1;
8
  }
9

10
  rx_i++;
11
}

ansonsten schmeiß mal den rest des codes, der nix mit den usart zu tun 
hat raus und kümmre dich nur um den usart, um sicherzustellen, das der 
erstmal läuft und nix anderes dazwischen funkt
toogle in der isr mal nen freien portpin, um zu schaun, ob er beim 
erstmaligen senden des befehls überhaupt die isr anspringt
[EDIT]Sorry, für den Doppelpost!
#1956520
Lesenswert?

Er schein beim ersten zeichen garnicht den interrupt aus zu lösen. Denn 
habe alles in der ISR mal auskommentiert und nur das Zeichen 
zurückschicken lassen was angekommen ist. Da kommt es beim ersten mal 
auch nicht zurück.

ist ja gut zu wissen, nur wie zu lösen?
mir fällt einfach nichts mehr ein warum es beim ersten mal nicht geht 
und sonst aber immer.
#1956536
Lesenswert?

> Der INT1 wird ausgelöst, nachdem ich meinen Stecker für den UART
> angeschlossen habe.

Wie genau ist das zu verstehen?
Steckst du die UART ein/aus?
Ist das in deinem jetzigen Testcode noch relevant?

Mach deine Tests so einfach wie möglich. Ohne irgendwelche Sonderfälle 
oder Spezialzuckerl.

Zeichn kommt rein - Zeichen wird zurückgeschickt. Alles andere fliegt 
aus dem Testcode raus. Und zwar wirklich: fliegt raus. Nicht "dürfte gar 
nicht mehr aufgerufen werden" oder "hat eh keinen Effekt", sondern 
"fliegt raus".

Alternativ: neues Programm anfangen und von 0 an beginnend aufbauen. Das 
ist schneller gemacht, als das vorhandene abzuspecken.
#1956629
Lesenswert?

Ehm mir ist was ganz anderes aufgefallen. Undzwar das die LED am Wandler 
ab und an mal blinkt obwohl ich nichts über den Port schicke.
Habe mal einen Logic Analyzer an den Controller gehangen und gesehen 
dass in regelmäßigen Zeitabständen immer das selbe ankommt. Nur was 
könnte das sein? Normalerweise kommt doch  nichts über den Port wenn ich 
nicht wirklich was sende...
#1956632
Lesenswert?

Rush ... schrieb:
> ja du verstehst schon richtig. Im fertigen Zustand soll das Einstecke
> des UARTs das Aufwachen des Controllers und das Stoppen der Messung
> bewirken. Außerdem wird noch Konfigurationsmöglichket per UART
> relaisiert werden.

Ich frage deshalb, weil es beim Einstecken eines Steckers schon mal zu 
Knacksern auf den Leitungen kommt. Die UART interpretiert die aber als 
den Beginn einer Übertragung und macht ein Zeichen daraus, welches dem 
Empfängercode dann zugeführt wird. Mit diesem  falschen, zufälligem 
Zeichen muss der klar kommen.

Daher hat man oft auch ein einleitendes Zeichen in einer Übertragung. 
Der Empfänger ignoriert alles, bis er dieses Zeichen sieht.

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