Frage zu UART AVR Code

Gast #7336425
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.

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

Gast #7337356
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..

#7337419
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)

Gast #7337501
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

Gast #7337511
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.

#7337579
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)

Gast #7338042
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 :)

#7338084
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?

Angehängte Dateien:
Gast #7338184
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

Gast #7338226
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
}
Gast #7341151
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...

Gast #7341302
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

Gast #7341779
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 :)

Gast #7341870
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.

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