Forum: Mikrocontroller und Digitale Elektronik Atmega328p: Uart 7 data bits 1 stop bit


von M. K. (sylaina)



Lesenswert?

Ich habe ein Problem mit dem UART.
Auf die Gegenseite habe ich keinen Einfluss, ich muss also benutzen was 
da ist. Das Frameformat ist 7 bit, 1 stopbit und parity even. Das 
"blöde" ist, dass den Uart-Receiver die Einstellung beim Stopbit nicht 
interessiert (Datasheet Page 197: Bit 3 – USBSn: Stop Bit Select
This bit selects the number of stop bits to be inserted by the 
Transmitter. The Receiver ignores this setting.). Ich empfange immer nur 
richtig Daten wenn ich am PC auf 2 Stopbits umstelle, bei einem Stopbit 
werden die Zeichen schlicht falsch empfangen. Dazu die Bilder im Anhang:
1. Bild (von 13:30:59 Uhr): "Test"+CR+LF gesendet (bei den gezeigten 
Einstellungen)
2. Bild (von 13:31:33 Uhr): "Test"+CR+LF gesendet (bei den gezeigten 
Einstellungen)
3. Bild (von 13:31:54 Uhr): CR+LF gesendet (bei den gezeigten 
Einstellungen)
Ich muss eigentlich nur hinbekommen, dass der Receiver bei 1 Stopbit die 
Daten richtig empfängt. Muss ich da noch irgendwo was schubbsen wenn 
mein Frameformat nur 7 bit + 1 stop ist? Ich sehs grade nicht.

Mein Testcode:
main
1
#define ubbrFuer4800BD      185     //Bei 14,318 MHz Quarz fuer 4800 Bd
2
#define uart_str_length     19
3
4
5
#include <avr/io.h>
6
#include <avr/interrupt.h>
7
8
#include "uart.h"
9
#include "main.h"
10
11
volatile char uartString[uart_str_length] = "050.00\r\n";
12
volatile uint8_t uart_str_count = 0;
13
volatile uint8_t uartGetMessage = 0;
14
15
int main(void)
16
{
17
    /* insert your hardware initialization here */
18
    setup();
19
    sei();
20
    for(;;){
21
        /* insert your main loop code here */
22
        while (uartGetMessage == 0);
23
        uartGetMessage = 0;
24
        sendString(uartString);
25
    }
26
    return 0;   /* never reached */
27
}
28
29
void setup(void) {
30
    //setup uart/rs232
31
    uartSetup(ubbrFuer4800BD);
32
}
33
ISR(USART_RX_vect){
34
    unsigned char nextChar;
35
    // Daten aus dem Puffer lesen
36
    nextChar = UDR0;
37
    if ( uartGetMessage == 0) {
38
        // Daten werden erst in uart_string geschrieben, wenn nicht String-Ende bzw. maximale Zeichenlaenge erreicht ist
39
        if( (nextChar != '\n') &&
40
           (nextChar != '\r') &&
41
           (uart_str_count < uart_str_length) ) {
42
            // Zeichen abspeichern
43
            uartString[uart_str_count] = nextChar;
44
            // und String-Count um 1 erhoehen
45
            uart_str_count++;
46
        }
47
        else {
48
            // Stringende definieren
49
            uartString[uart_str_count] = '\0';
50
            // Zeichenempfangszaehler zuruecksetzen
51
            uart_str_count = 0;
52
            // und Flag setzen für Datenempfang Abgeschlossen
53
            uartGetMessage = 1;
54
        }
55
        
56
    }
57
}
uart.c
1
#include "uart.h"
2
3
4
void uartSetup(uint16_t baudrate){
5
    //set Baudrate
6
    UBRR0H = baudrate >> 8;
7
    UBRR0L = baudrate & 0xFF;
8
    //set other UART Settings
9
    UCSR0B |= (1<<TXEN0)|(1 << RXEN0)|(1<<RXCIE0);  // UART TX/RX einschalten, RXIE einschalten
10
    UCSR0C |= (1 << UPM01)|(1<<UCSZ01); // Asynchron 7N1 und Parity even
11
}
12
void sendChar(unsigned char zeichen){
13
    {
14
        /* Wait for empty transmit buffer */
15
        while ( !( UCSR0A & (1<<UDRE0)) );
16
        /* Put data into buffer, sends the data */
17
        UDR0 = zeichen;
18
    }
19
}
20
void sendString(const char* charOfString){
21
    //send string from ram
22
    /* while *charOfString != '\0 */
23
    while (*charOfString) {
24
        sendChar(*charOfString);
25
        charOfString++;
26
    }
27
}
28
void sendString_p(const char* charOfString){
29
    //send string from flash
30
    register char c;
31
    /* while *charOfString != '\0 */
32
    while ( (c = pgm_read_byte(charOfString++)) ) {
33
        sendChar(c);
34
    }
35
}

von S. Landolt (Gast)


Lesenswert?

> UCSR0B |= (1<<TXEN0)|(1 << RXEN0)|(1<<RXCIE0);
> UCSR0C |= (1 << UPM01)|(1<<UCSZ01);

Das 'oder' ist schlecht, UCSZ00 ist ja bereits gesetzt als initial 
value, das führt also zum 8-bit-mode.

von Max D. (max_d)


Lesenswert?

Den receiver interessieren die stop-bits deswegen nicht, weil er ein 
zweites stop-bit nicht von einer kleinen Pause unterscheiden kann. Also 
tut er immer so als würde er mit einem einzelnen SB rechnen und 
interpretiert "bei Bedarf" das zweite als Ruhepegel.

von spess53 (Gast)


Lesenswert?

Hi

>Hat jemand eine Verbesserungsidee?

Was für einen Oszillator benutzt du beim  Atmega328p?

MfG Spess

von Thomas E. (thomase)


Lesenswert?

S. Landolt schrieb:
> das führt also zum 8-bit-mode

So ist es.

Der Empfänger erwartet somit 11 Bit: Start-8-P-Stop
Der PC sendet aber nur 10 Bit: Start-7-P-Stop

Das 11. Bit, welches vom Empfänger erwartet wird, ist dann das 1. Bit 
vom nächsten Frame. Das ist aber das Startbit und immer 0. Erwartet wird 
aber Stop=1. Das führt dann zu einem Frameerror. Mit einem 2.Stopbit 
sind die Daten zwar immer noch falsch, zumindest passt aber der Frame.

mfg.

: Bearbeitet durch User
von M. K. (sylaina)


Lesenswert?

S. Landolt schrieb:
> Das 'oder' ist schlecht, UCSZ00 ist ja bereits gesetzt als initial
> value, das führt also zum 8-bit-mode.

Ohm man, natürlich. Du hast recht, der Receiver ist ja auf 8 bit 
default-mäßig eingestellt. Ich war soo blind...

von spess53 (Gast)


Lesenswert?

Hi

>Ich war soo blind...

Deswegen macht man in der Initialisierung auch '=' und nicht '|='.

MfG Spess

von Max D. (max_d)


Lesenswert?

spess53 schrieb:
> Deswegen macht man in der Initialisierung auch '=' und nicht '|='.

Da aber bitte vorsichtig wenn sich mehere Elemente ein Register teilen.

von M. K. (sylaina)


Lesenswert?

spess53 schrieb:
> Hi
>
>>Ich war soo blind...
>
> Deswegen macht man in der Initialisierung auch '=' und nicht '|='.
>
> MfG Spess

Es gibt viele Wege. 99,9% aller Register (in der Regel sinds nur die 
Port-Register, mache nicht soo viel mit µCs), die ich für gewöhnlich 
beim AVR benutze sind komplett mit 0 initialisiert. Mir ist einfach 
entfallen, dass der UART initialmäßig beim Atmeg328 auf 8N1 eingestellt 
ist.

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.