Forum: Mikrocontroller und Digitale Elektronik Frage zu UART AVR Code


You were forwarded to this site from EmbDev.net. Back to EmbDev.net
von avro (Gast)


Lesenswert?

Hallo guten Tag,

ich habe gerade im AVR Studio 4 unten stehenden Code simuliert.
Der Debugger wiederholt am Ende nur "while (!(UCSR0A & (1<<UDRE0)));"
Zumindest ist dort die ganze Zeit der gelbe Pfeil.
Ich habe das Programm mit SimulIDE woanders getestet.
UART empfängt 9 mal etwas.

* Wie kann man AVR Studio denn dafür nutzen auch UART anzuzeigen?
* Warum bleibt der immer bei dieser Stelle? Er müsste doch aufhören nach 
9 mal senden.

1
41:           while (!(UCSR0A & (1<<UDRE0)));
2
+0000004C:   918000C0    LDS       R24,0x00C0     Load direct from data space
3
+0000004E:   FF85        SBRS      R24,5          Skip if bit in register set
4
+0000004F:   CFFC        RJMP      PC-0x0003      Relative jump
1
//UCSRnA,
2
//Configuration + Status
3
4
//UDRn
5
// read/ write 8 Bit
6
7
8
#include <avr/io.h>
9
#include <util/delay.h>
10
#include <stdio.h>
11
12
#define F_CPU 16000000UL // clock frequency of AVR in Hz
13
#define BAUD 9600        // desired baud rate
14
#define MYUBRR F_CPU/16/BAUD-1 // calculate baud rate register value
15
16
// function to initialize UART
17
void USART_init(unsigned int ubrr)
18
{
19
  // set the baud rate
20
  //UBRRnH:UBRRnL
21
  //Baudrate : fosc / 16*(UBRR+1)
22
23
    UBRR0H = (unsigned char)(ubrr>>8);
24
    UBRR0L = (unsigned char)ubrr;
25
    // enable transmitter and receiver
26
    UCSR0B = (1<<RXEN0)|(1<<TXEN0);
27
    // set frame format: 8 data bits, 1 stop bit
28
    UCSR0C = (1<<USBS0)|(3<<UCSZ00);
29
}
30
31
// function to transmit data via UART
32
void USART_transmit(unsigned char data)
33
{
34
int  i = 2;
35
    // wait for empty transmit buffer
36
    // UDRE0 =  1 = UDR is empty
37
    // = 0 = UDR is still full
38
    while (!(UCSR0A & (1<<UDRE0)));
39
    // put data into buffer and send
40
    UDR0 = data;
41
  i--;
42
  
43
}
44
45
// function to receive data via UART
46
unsigned char USART_receive(void)
47
{
48
    // wait for data to be received
49
    // RXC0 = 1 = Data fully received
50
    // RXC0 = 0 = notfully received
51
    while (!(UCSR0A & (1<<RXC0)));
52
    // get and return received data from buffer
53
    return UDR0;
54
}
55
56
int main(void)
57
{
58
    char data=0xff;
59
    USART_init(MYUBRR);
60
  int i = 10;
61
    while (i> 1)
62
    {
63
        //data = USART_receive();
64
        USART_transmit(data);
65
     i--;
66
     
67
         }
68
    return 0;
69
}

Danke sehr.

von Falk B. (falk)


Lesenswert?

avro schrieb:
> ich habe gerade im AVR Studio 4 unten stehenden Code simuliert.
> Der Debugger wiederholt am Ende nur "while (!(UCSR0A & (1<<UDRE0)));"
> Zumindest ist dort die ganze Zeit der gelbe Pfeil.

Entweder wartest du nicht lange genug, denn der Sendevorgang ist langsam 
(viele Zehntausende CPU-Takte!) oder der Simulator simuliert den UART 
nicht korrekt. Bei 9600 Baud und 16 MHz CPU-Takt, dauert ein Zeichen mit 
10 Bit stolze 1,042ms, das sind 16.666 CPU-Takte.

: Bearbeitet durch User
von avro (Gast)


Lesenswert?

Falk B. schrieb:
> Bei 9600 Baud und 16 MHz CPU-Takt, dauert ein Zeichen mit
> 10 Bit stolze 1,042ms, das sind 16.666 CPU-Takte.

wow das ist viel.

von avro (Gast)


Lesenswert?

wie kann man denn
delays überspringen?
Irgendwie klappt das nicht mit den breakpoints.
Sonst hätte ich die einfach übergangen.
D.h. der Debugger bleibt einfach bei _delay_ms(50) hängen..
1
#define F_CPU 8000000UL
2
#include <avr/io.h>
3
#include <util/delay.h>
4
5
int main(void)
6
{
7
        DDRB |= (1<<DDB1);
8
//PORTB=0x00;
9
    while (1) 
10
    {
11
        PORTB |= (1<<PORTB1);
12
        _delay_ms(50);
13
        PORTB &= ~ (1<<PORTB1);
14
        _delay_ms(50);
15
    }
16
}

Danke..

von Falk B. (falk)


Lesenswert?

avro schrieb:
> Irgendwie klappt das nicht mit den breakpoints.

Dann probier es noch mal und setz die Breakpoints auf die 
Portzuweisungen.

von Klaus S. (kseege)


Lesenswert?

avro schrieb:
> wie kann man denn
> delays überspringen?


Ganz grundsätzlich benutzt man delay() nur da, wo die Programme so 
einfach sind, daß man sie nicht im Simulator testen muß.

Zum Lernen im Simulator benutzt man einfach eine eigene delay-Routine, 
die im echten Betrieb die passende Libraryroutine aufruft, im Debugmodus 
aber zurückkehrt, ohne etwas zu machen, oder eine Schleife ausführt, die 
dann einfach einen Zähler hochzählt.

Gruß Klaus (der soundsovielte)

von avro (Gast)


Lesenswert?

Falk B. schrieb:
> Dann probier es noch mal und setz die Breakpoints auf die
> Portzuweisungen.

dann kommt die Fehlermeldung, dass das Setzen nicht funktioniert.
Der Breakpoint wird dann einfach nicht gesetzt und auf das delay gesetzt 
:D

Klaus S. schrieb:
> Zum Lernen im Simulator benutzt man einfach eine eigene delay-Routine,
> die im echten Betrieb die passende Libraryroutine aufruft, im Debugmodus
> aber zurückkehrt, ohne etwas zu machen, oder eine Schleife ausführt, die
> dann einfach einen Zähler hochzählt.

Habe ich mir auch schon gedacht.
Aber es kam mir etwas umständlich vor.

Wie macht man das denn dann ?
Also ich könnte jetzt irgendwas zusammenschreiben.
Aber es gibt sicherlich eine bewährte Schreibweise dafür.
Wonach sollte ich googlen?

Danke

von Stefan F. (Gast)


Lesenswert?

avro schrieb:
> dann kommt die Fehlermeldung, dass das Setzen nicht funktioniert.

Kann es sein, dass du mit einer hohen Optimierungsstufe compiliert hast?

Ich benutze normalerweise -O1, damit kommt der Debugger meistens klar. 
Ansonsten weiche ich auf -Og oder notfalls gar auf -O0 aus. _delay_ms() 
funktioniert mit -O0 allerdings nicht richtig.

von Falk B. (falk)


Angehängte Dateien:

Lesenswert?

Läuft problemlos, auch mit Optimierung -Os, siehe Anhang.

von Klaus S. (kseege)


Lesenswert?

avro schrieb:
> Aber es gibt sicherlich eine bewährte Schreibweise dafür.
> Wonach sollte ich googlen?

Gar nicht. Nur Hirn einschalten.

void my_delay(int nrofmilliseconds)
 { while (nrofmilliseconds > 0) {nrofmilliseconds--;} 
/*Simulatorbetrieb*/
   // _delay_ms(nrofmilliseconds); /*Arbeitsbetrieb*/
 }

Dann schiebt man die // nur vor die Zeile, die man nicht benutzen 
möchte.  Falls die nrofmilliseconds ein anderer Typ sind als int, sollte 
man das natürlich anpassen.

Gruß Klaus (der soundsovielte)

von Fronk (Gast)



Lesenswert?

Klaus S. schrieb:
> Gar nicht. Nur Hirn einschalten.

Wollte nur fragen, ob es eine Lösung gibt, um möglichst keinen Code bei 
der Simulation zu ändern.

Falk B. schrieb:
> Läuft problemlos, auch mit Optimierung -Os, siehe Anhang.

Habe meine den aktuellen Stand im Anhang.

Klaus S. schrieb:
> void my_delay(int nrofmilliseconds)
>  { while (nrofmilliseconds > 0) {nrofmilliseconds--;}
> /*Simulatorbetrieb*/
>    // _delay_ms(nrofmilliseconds); /*Arbeitsbetrieb*/
>  }

Danke sehr :)

von Falk B. (falk)


Lesenswert?

Fronk schrieb:
> Habe meine den aktuellen Stand im Anhang.

Du sollst die Breakpoints auf die Portausgaben setzen, NICHT die 
_delay_ms() Aufrufe!

von avro (Gast)


Lesenswert?

Wenn ich die Breakpoints auf die Portausgaben setze und dann auf "Start 
Debugging" klicke werden die Breakpoints wie auf dem Bild verschoben. Es 
erscheint dazu noch die Fehlermeldung.

von Falk B. (falk)


Angehängte Dateien:

Lesenswert?

avro schrieb:
> Wenn ich die Breakpoints auf die Portausgaben setze und dann auf
> "Start
> Debugging" klicke werden die Breakpoints wie auf dem Bild verschoben. Es
> erscheint dazu noch die Fehlermeldung.

Moment mal! Benutzt du den Simulator? Dafür braucht man keine Hardware. 
Oder einen Debugger mit Hardwar? Wenn ja, welchen Debugger und welche 
Hardware?

: Bearbeitet durch User
von avro (Gast)


Angehängte Dateien:

Lesenswert?

Ich benutze den Simulator2 mit Device ATmega328p

von Stefan F. (Gast)


Lesenswert?

Der Simulator läuft auf jeden Fall viel langsamer als ein echter 
Mikrocontroller. Deswegen führt kein Weg umhin, delays in 
Größenordnungen von Sekunden durch etwas anderes zu ersetzen.

Dazu bieten sich Makros an:
1
#ifndef DEBUG
2
    _delay_ms(1000);
3
#endif

In dem Dialog "Custom compiler options", der in 
Beitrag "Re: Frage zu UART AVR Code" gezeigt wurde, 
kannst du dann das Makro definieren:

-DDEBUG

Wenn das Makro definiert ist, wird der Delay Aufruf ausgelassen (ifndef 
bedeutet "if not defined"). Mehr dazu auf 
https://wr.informatik.uni-hamburg.de/_media/teaching/sommersemester_2013/cgk-13_stabe_preprocessor_ausarbeitung.pdf

von avro (Gast)


Lesenswert?

Ok.
Aber man sieht bei dem Code nicht mehr den  gelben Pfeil.
Nur wenn man den Dissembler anschaut kann man den Assembler-Code 
mitverfolgen.
Ist das normal?
Außerdem musste ich -O0 einstellen..

1
#define F_CPU 8000000UL
2
#include <avr/io.h>
3
#include <util/delay.h>
4
#define DEBUG 
5
#ifdef DEBUG
6
7
#define _delay_ms(x) 1
8
#endif
9
10
int main(void)
11
{
12
        DDRB |= (1<<DDB1);
13
//PORTB=0x00;
14
    while (1) 
15
    {
16
        PORTB |= (1<<PORTB1);
17
        _delay_ms(50);
18
        PORTB &= ~ (1<<PORTB1);
19
        _delay_ms(50);
20
    }
21
}

von Stefan F. (Gast)


Lesenswert?

Kann es sei, dass du einen neueren Compiler als WinAvr2010 (avr-gcc 
4.3.3) verwendest? Ich frage, weil der Simulator/Debugger mit neueren 
Versionen öfter Probleme hatte, bis hin zum Absturz.

von Falk B. (falk)


Angehängte Dateien:

Lesenswert?

avro schrieb:
> Ich benutze den Simulator2 mit Device ATmega328p

Geht bei mir auch problemos. Die Simulation des _delay_ms(50) dauert ca. 
3s.

von avro (Gast)


Lesenswert?

Wie simuliert Ihr UART normalerweise?

Oder simuliert ihr/man das gar nicht und testet das einfach direkt am 
Controller?

Wahrscheinlich sollte ich das ganze mal in Assembler schreiben um ein 
besseres Gefühl dafür zu bekommen worum es hier eigentlich geht...

von Steve van de Grens (roehrmond)


Lesenswert?

avro schrieb:
> Wie simuliert Ihr UART normalerweise?

Gar nicht. Dafür gibt es In-Circuit Debugger, Logic Analyzer und 
Log-Meldungen.

: Bearbeitet durch User
von avro (Gast)


Lesenswert?

Steve van de Grens schrieb:
> Gar nicht. Dafür gibt es In-Circuit Debugger, Logic Analyzer und
> Log-Meldungen.

danke sehr :)

Warum simuliert man das nicht?

kann ja sein, dass man so in manchen Fällen Zeit spart wenn man testet.

von Stefan F. (Gast)


Lesenswert?

avro schrieb:
> Warum simuliert man das nicht?

Weil der Simulator die Gegenstelle mit der dein µC Kommuniziert nicht 
simulieren kann.

von MWS (Gast)


Lesenswert?

avro schrieb:
> kann ja sein, dass man so in manchen Fällen Zeit spart wenn man testet.

Schau Dir mal die "Stimuli" im Pdf zum AVR-Simulator an. Mit Stimuli 
kannst Du per Datei Register schreiben, lesen und loggen.

https://www.microchip.com/content/dam/mchp/documents/parked-documents/AVR-Simulator-UserGuide-DS50003042A.pdf

Für den Fall dass Dir Foren noch nicht geläufig sind: Man kann sich den 
Schubs in die richtige Richtung holen, dafür sind sie nützlich.
Und halt zum sozialen Austausch, als Wissensquelle sind sie eher vier 
minus.

Das innewohnende Problem ist, dass viele Teilnehmer tatkräftig ihr 
Unwissen verbreiten. Manchmal gezielt, aber meist weil sie's nicht 
besser wissen, jedoch mitreden wollen.

Du als Hilfesuchender müsstest bereits vorher das Wissen haben, das Dir 
zum Zeitpunk Deiner Frage noch fehlt, um die ganzen Falschinformationen 
von den Nutzinformationen auseinander zu halten.

Ein Ei vs. Henne Problem :D

von avro (Gast)


Lesenswert?

https://www.microchip.com/content/dam/mchp/documents/parked-documents/AVR-Simulator-UserGuide-DS50003042A.pdf

Werde ich mir mal anschauen.
Es sieht danach aus als wäre es möglich Register zu manipulieren.
Um gezielte Tests z.B. für UART durchzuführen, müsste man jedoch genau 
wissen worauf es ankommt.

Der File Stimulator ist interessant.

Dafür müsste ich mir Beispiele anschauen.

Stefan F. schrieb:
> Weil der Simulator die Gegenstelle mit der dein µC Kommuniziert nicht
> simulieren kann.

Warum?
Eingehende Daten könnten doch digital verarbeitet werden.
Meiner Meinung nach müsste ein digitales Software-Modell dazu in der 
Lage sein,eingehende UART Nachrichten zu verarbeiten.

https://stackoverflow.com/questions/25912799/atmel-simulating-uart-comm

" In this simulator you simply can add a c/c++-testprogram which runs on 
the host in the native host fashion and connect a simulated uart to the 
simulator which runs your avr program"

 "Soft I2C"
Beitrag "Soft I2C Master"
Alleine auf einem uC ist doch dann eine solche Simulation/ Verarbeitung 
von Kommunikation per Software möglich.


Oder was meintest du?

Danke :)

von Steve van de Grens (roehrmond)


Lesenswert?

avro schrieb:
>> Weil der Simulator die Gegenstelle mit der dein µC Kommuniziert nicht
>> simulieren kann.

> Warum?
> Eingehende Daten könnten doch digital verarbeitet werden.
> Meiner Meinung nach müsste ein digitales Software-Modell dazu in der
> Lage sein,eingehende UART Nachrichten zu verarbeiten.

Wenn ich zum Beispiel den seriellen Port eines Mikrocontrollers benutze, 
um meine Modelleisenbahn zu steuern, dann müsste dieses "digitale 
Software-Modell" die ganze Modelleisenbahn simulieren. Technisch ist das 
machbar, doch der Simulator vom AVR Studio bringt diese Funktion nicht 
ab Werk mit. Bevor ich hunderte Stunden in die Entwicklung von so einem 
Modell stecke, Debugge ich mein Programm lieber direkt in der echten 
Hardware.

: Bearbeitet durch User
von avro (Gast)


Lesenswert?

Steve van de Grens schrieb:
> Bevor ich hunderte Stunden in die Entwicklung von so einem
> Modell stecke, Debugge ich mein Programm lieber direkt in der echten
> Hardware.

ja das denke ich auch, würde ich auch so machen.

Aber in manchen Fällen kann man einfachere Tests schreiben, die Zeit 
sparen können.

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.