Forum: Mikrocontroller und Digitale Elektronik USART AVR-GCC Empfang abfragen und in Variable speichern problem.


von Martin Z. (Gast)


Lesenswert?

Hallo,

nachdem ich jetzt ewig lange C Handbuch und hier das AVR-GCC Tut gelesen 
habe und rumprobiert und Fehler gesucht hab frag ich nun wieder euch..


Also ich wollte testweise ein Programm schreiben dem ich ein Zeichen 
sende und der mir dann das selbige zurückschickt so das ich im Terminal 
das so empfange ">A<" das A steht für das entsprechende Zeichen welches 
ich über USART gesendet habe und so zurück bekomme.

das ganze klappt aber nur genau einmal danach siehts im Terminal dann so 
aus:
1
>A<
2
3
>
4
 <
5
6
><
7
8
>
9
<
10
11
>
12
<
13
14
>
15
<
Die Schleife läuft weiter obwohl ich keine weiteren eingabe mache
als würde die Funktion trotz Endloschleife garnichtmehr aufgerufen 
werden
und wenn ich nochmal ein Buchstaben schicke wird der ignoriert.
Dabei sollte man doch annehmen das in jedem Schleifendurchlauf die 
Funktion neu abgerufen und der Variable data zugewiesen wird.

Hier mein Quellcode:
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <stdint.h>
4
5
void USART_Init( unsigned int ubrr)
6
{
7
  UBRRH = (unsigned char)(ubrr>>8); // Set baud rate in high- and low-register
8
  UBRRL = (unsigned char)ubrr;
9
  UCSRB = 0b00011000; // USART Receiver und Transmitter ein.
10
  UCSRC = 0b10001110; // URSEL ein Übertragung 8 Bit 1 Stopbit
11
}
12
13
14
void USART_Transmit(unsigned char data)
15
16
{
17
  while ( !( UCSRA & (1<<UDRE)) ); // Wait for empty transmit buffer
18
19
  UDR = data; // Put data into buffer, sends the data
20
}
21
22
uint8_t USART_Receive(void)
23
24
{
25
  while ( !(UCSRA & (1<<RXC)) ); // Wait for data to be received
26
27
  return UDR; // Get and return received data from buffer
28
}
29
30
void USART_Flush(void) // Flush Receive-Buffer (entfernen evtl. vorhandener ungültiger Werte)
31
32
{
33
  unsigned char dummy;
34
35
  while (UCSRA & (1<<RXC))
36
37
  dummy = UDR;
38
}
39
40
void main( void )
41
42
  {
43
  uint8_t data;
44
45
  USART_Init(63); // Init UART
46
47
  USART_Flush(); // Flush Receive-Buffer
48
49
  DDRD = 0b10000000;
50
51
  while(1)
52
53
  {
54
    PORTD ^= (1 << PD7);
55
56
    data = USART_Receive();
57
58
    USART_Transmit('>');
59
    USART_Transmit(data);
60
    USART_Transmit('<');
61
    USART_Transmit('\n');
62
    USART_Transmit('\n');
63
64
    _delay_ms(1000);
65
  }
66
}

Vielen Dank im voraus

Martin

von Unwissender (Gast)


Lesenswert?

Ich hab das jetzt versucht, zum laufen zu bekommen, und hab dann aber 
die Lust verloren, da dies so intransparent geproggt ist. Fang doch 
nochmal von vorne an und schau Dir das UART Tutorial an - da siehst Du, 
wie man es auch lesbarer machen kann.

von Martin Z. (Gast)


Lesenswert?

@ Unwissender
Bitte was?
Der Code ist sehr leicht zu lesen und wurde bis auf die main Funktion 
kopiert und steht in allen Tuts ganz genauso selbst hier im AVR-GCC UART 
Tut.
Ich denke mal du bist ein Troll oder wirklich sehr unwissend.

@ Allgemein
Im übrigen hab ich jetzt mal überprüft ob die Funktion aufgerufen wird 
und das wird sie. Da ist irgendwie mit dem lesen aus dem UDR 
Empfangsregister nicht in ordnung. Da stehen sachen drinne die ich 
gesendet habe wie kann das denn sein?

von Uwe (de0508)


Lesenswert?

Guten Morgen,

was mir bei deinen Ausführungen fehlt sind angaben über den verwendeten 
AVR µC, den angeschlossenen Quarz und deiner gewünschten Baudrate.

Mit dem Wert UBRR=(64-1) komme ich auf keinen 'grünen' Zweig !

Angenommen F_CPU = 8MHz, dann liegt die Baudrate bei :

Baudrate = F_CPU/ 16 /(UBRR+1) = 7812,5

Will man z.B. Baudrate = 19200 setzen ergibt sich:
UBRR = F_CPU/ 16 /Baudrate -1 = 26 -1 = 25

evtl. noch aufrunden, ich schreibe die Formel dafür aus.
UBRR = (uint16_t)(1.0 * F_CPU/ 16 /Baudrate +.5 -1 )

: Bearbeitet durch User
von Martin Z. (Gast)


Lesenswert?

Guten Morgen dir auch,

da ja sonst alles richtig beim PC ankommt habe ich das für nicht wichtig 
gehalten und deswegen nicht beigeschrieben aber hier trotzdem mal die 
gewünschten Daten.

Ich verwende einen ATMEGA32 (ein ATTiny2313 brachte mir das gleiche 
ergebnis) mit einem 9.8304 MHz Quarz bei 9600 Baud.

Den Wert für die Baudrate habe ich dem von dieser Seite entnommen:

http://www.gjlay.de/helferlein/avr-uart-rechner.html

von Unwissender (Gast)


Lesenswert?

Ich mag ja unwissend sein, aber mein Uart funktioniert, und die Settings 
sind lesbar, im Gegensatz zu Deinen. Immerhin hab ich mir ne Stunde 
verbraten, um Deinen Fehler zu finden und der Hinweis mit dem Tutorial 
war durchaus gut gemeint.

Weiterhin war ich ja wohl der einzige, der sich bis gestern überhaupt 
die Mühe gemacht hat zu Antworten.

Daher finde ich Deine Reaktion ziemlich unhöflich und hoffe eigentlich, 
dass Du noch lang nach Deinen Fehlern suchen darfst - allein.

von katastrophenheinz (Gast)


Lesenswert?

>UCSRC = 0b10001110; // URSEL ein Übertragung 8 Bit 1 Stopbit
Dieses Setting bedeutet "2 Stopbits", da USBS=1.

Die Richtung von AVR->PC scheint ja zu funktionieren.
Lass doch mal nach dem Empfang eines Zeichens die Fehlerbits aus UCSRA,
indem du z.B. dein USART_Receive so modifizierst:
1
uint8_t USART_Receive(void)
2
3
{
4
  while ( !(UCSRA & (1<<RXC)) ); // Wait for data to be received
5
6
  uint8_t sra = UCSRA;
7
  uint8_t ret = UDR;
8
  
9
  if ( sra & ( 1 << FE )  ) USART_Transmit('F');
10
  if ( sra & ( 1 << DOR ) ) USART_Transmit('D');
11
12
  return ret; 
13
}

von al_guesto (Gast)


Lesenswert?

Ich würde mal den delay rausschmeißen und senden lassen, wenn auch was 
angekommen ist. Ich denke darauf bezieht sich auch der Hinweis mit dem 
Tut.

von katastrophenheinz (Gast)


Lesenswert?

>>UCSRC = 0b10001110; // URSEL ein Übertragung 8 Bit 1 Stopbit
>Dieses Setting bedeutet "2 Stopbits", da USBS=1.
Das scheint mir die Fehlerursache zu sein, da den PC bei Empfang das 
zweite Stopbit überhaupt nicht interessiert, daher wird jedes Zeichen 
korrekt empfangen.

Andersrum wartet der AVR immer vergeblich auf ein zweites Stopbit, daher 
wirst du wahrscheinlich beim Empfang auf dem AVR immer "Frame Errors" 
haben.

Gruss, Heinz

von Martin Z. (Gast)


Lesenswert?

Unwissender schrieb:
> Ich mag ja unwissend sein, aber mein Uart funktioniert, und die Settings
> sind lesbar, im Gegensatz zu Deinen.

dein problem sind also die binärangaben ?

von Unwissender (Gast)


Lesenswert?

Nicht mein Problem, aber möglicherweise Deines.

Aber ja, das meinte ich.
Der Rest des Programmes ist sicherlich gut lesbar, das war kein Thema.

von Martin Z. (Gast)


Lesenswert?

Unwissender schrieb:
> Nicht mein Problem, aber möglicherweise Deines.
>
> Aber ja, das meinte ich.
> Der Rest des Programmes ist sicherlich gut lesbar, das war kein Thema.

Dann entschuldige ich mich für die Vorwürfe.
Drücke dich dann aber nächstesmal bitte etwas konkreter aus und schreib 
nicht man soll den ganzen Code neu schreiben.
Ausserdem ist die Binärangabe in meinen Augen praktischer.
Man braucht natürlich das entsprechende Handbuch dazu aber da kann man 
ja kurz reingucken.

@ Heinz
danke für den Hinweis auf die falsche Angabe für die Stopbits da hab ich 
mich wohl im Handbuch verlesen :P
Hab es angepasst auf 1 Stopbit aber es hat nichts geändert.
Ich hab dafür aber ein Ergebnis bei überprüfung der Fehlerbits erhalten.
Er meldet mir einen Data OverRun.

Ein Zeichen senden geht doch mit "echo A > /dev/ttyS0" oder ist das 
falsch?

von katastrophenheinz (Gast)


Lesenswert?

Martin z. schrieb:
> Er meldet mir einen Data OverRun.

Bei jedem Zeichen oder sporadisch ?
delay_ms(1000) auch rausgenommen?
Da du für jedes empfangene Zeichen fünf Zeichen zurückgibst, darfst zu 
immer nur ein Zeichen auf einmal zum Controller senden. Bei mehr als 
einem in Folge ist klar, daß Overrun auftritt, weil du zu selten das 
Empfangsregister liest.
Abhilfe: für jedes empfangene Zeichen auch nur eines zurückschicken oder 
Umstellen auf Interruptgesteuert -> z.B. P. Fleurys UART-Library.

>Ein Zeichen senden geht doch mit "echo A > /dev/ttyS0" oder ist das
>falsch?
Da hängt wahrscheinlich noch ein \r mit dran.
Vllt mal ein Terminalprogramm a la microterm nehmen...

gruss, Heinz

von Martin Z. (Gast)


Angehängte Dateien:

Lesenswert?

Hey,

also wenn ich das delay rausnehm und dann ein Zeichen schicke bekomm ich 
im Terminal ganz viele F und D für die entsprechenden Fehler und ne 
bunte Tüte Zeichen die ich alle ausser dem ersten nicht geschickt habe 
und es nimmt auch kein ende mehr.
Gibs noch n alternatives programm statt microterm?
ich weiß nämlich nicht was daran besonders ist.
Hab XTerm ausprobiert der bringt das selbe Ergebnis.


Hab ein Screenshot vom Terminal angehangen.
Falls das irgendwie weiterhilft.

Gruß
Martin

von katastrophenheinz (Gast)


Lesenswert?

Hi,

ich hab dein Programm incl. der oben angegebenen Änderungen mal bei mir 
rennen lassen ( mega32@8MHz/38400Bd ) - funktioniert fehlerfrei.

D.h. der Fehler bei dir liegt an anderer Stelle.
 - wie sieht dein AVR-Testaufbau aus ( Eval-Board, Arduino, Steckbrett ) 
?
 - Wie sieht die serielle Strecke zw. AVR und PC aus ( RS232 / 
TTL-Level, Bluetooth, USB-to-Serial, ... )

>Gibs noch n alternatives programm statt microterm?
>ich weiß nämlich nicht was daran besonders ist.
>Hab XTerm ausprobiert der bringt das selbe Ergebnis.
egal - irgendein Terminalprogramm.

Gruss, Heinz

von Martin Z. (Gast)


Lesenswert?

Guten Tag,

ich hab mir den MAX232N geholt und die schaltung nach dem UART Tut von 
hier gelötet so als Modul das in verbindung mit meinem Breadboard 
verwende.
(ich habs jetzt 4 mal überprüft auf korrete Schaltung und Lötbrücken)

Ich hab dieses Modul auf dem Board an die Stromversorgung angeschlossen 
(5V aus einem PC Netzteil) und die beiden drähte RXD Pin 14 und TXD an 
Pin 15 des MC.

Ansonsten habe ich am MC die eigene Stromversorgung an Pin 10 und 11 mit 
einem Kerko (104 Unterstrich) zwischen + und - an dem gleichen PC 
Netzteil angeschlossen.

Eine LED an PD7 und natürlich den Quarz an Pin 12 und 13 und sonst ist 
garnichts angeschlossen.

Ich hab die Fuses vom ATMega32 auf lfuse DC hfuse D8 gestellt.

----------------

Ich hab gerade versucht das ganze mal mit einem 16 Mhz Quarz am laufen 
zu bekommen und habe dazu die Fuses auf lfuse DC hfuse D8 (von Medium 
Freq auf High Freq) gestellt.
Beim Flashen hab ich dann den Fehler hier bekommen:

avrdude: verifying ...
avrdude: verification error, first mismatch at byte 0x0000
         0x00 != 0x0c
avrdude: verification error; content mismatch

avrdude: safemode: lfuse changed! Was de, and is now 0
Would you like this fuse to be changed back? [y/n]



Gruß
Martin

von katastrophenheinz (Gast)


Lesenswert?

>Ich hab gerade versucht das ganze mal mit einem 16 Mhz Quarz am laufen
>zu bekommen und habe dazu die Fuses auf lfuse DC hfuse D8 (von Medium
>Freq auf High Freq) gestellt.
Wenns mit 8MHz nicht geht, wird's mit 16 genauso wenig gehen.
Ein Blick ins mega32-Manual p.27: Bei Frq > 8Mhz auch CKOPT auf 1, 
CSEL[3:1] = 111 für > 3 MHz.

>den Quarz an Pin 12 und 13 und sonst ist garnichts angeschlossen.
Zwischen XTAL1/XTAL2 und GND jeweils ein 12-22pF-Kondensator?

Dann bau mal auf der 5V-Seite des Max232 eine Brücke zwischen TxD und 
RxD, und klemm den Controller komplett ab. d.h. prüfe mit dieser 
Echo-Schaltung einfach mal deine serielle Übertragungsstrecke.

Gruss, Heinz

von Martin Z. (Gast)


Lesenswert?

Also erstmal wollte ich nochmal vielen Dank für deine Hilfe sagen :)

Hätte wohl ins Handbuch gucken sollen was die Fuses angeht hab das 
einfach mit dem Rechner hier gemacht: http://www.engbedded.com/fusecalc/
und ich dachte 9.8304 MHz würd das noch unter Medium Freq fallen.
Hab es jetzt auf low DE high C8 angepasst und die Kondensatoren (20p 
Kerkos) an den Quarz angeschlossen.

wenn ich RXD und TXD miteinander verbinde bekomme ich im Terminal immer 
wieder den gesendeten Buchstaben gefolgt von zeichenumbrüchen wobei mir 
aufgefallen ist das der Abstand zwischen den Buchstaben pro ausgabe 
verdoppelt.

Ich habe zum vergleich nochmal mein Pollin Eval Board rausgekramt und 
bin da zu dem gleichen ergebnis gekommen.

Mir ist außerdem ausgefallen das das Program auf dem MC scheinbar normal 
läuft wenn ich das Terminal nicht auf Empfang stelle (ich seh es daran 
das die LED pro senden umgeschaltet wird).

von Martin Z. (Gast)


Lesenswert?

Ich hab jetzt eine Lösung :) statt cat und echo hab ich das "ssterm" 
genommen das Programm ist speziell für die kommunikation über die 
Serielle Schnittstelle und gibt es z.B in der Archlinux AUR.

Danke für die Mühen :)

von katastrophenheinz (Gast)


Lesenswert?

Martin z. schrieb:
> wenn ich RXD und TXD miteinander verbinde bekomme ich im Terminal immer
> wieder den gesendeten Buchstaben gefolgt von zeichenumbrüchen wobei mir
> aufgefallen ist das der Abstand zwischen den Buchstaben pro ausgabe
> verdoppelt.

Nochmal genauer: Du hast jetzt auf der 5V-Seite des selbstgelöteten 
Max232 Rxd und Txd miteinander verbunden, korrekt?

Und wenn du jetzt z.B. einmal 'a' (ohne Return) über Xterm oder was 
weiß ich sendest, dann kommt wiederholt 'a' + immer mehr '\n' zurück??

Wenn das so ist, dann hat deine RS232-Strecke irgendwo nicht nur ein 
Gedächtnis, sondern auch eine fette Macke.

Und mit dem Pollin Eval Board ( das hat einen eigenen RS232-Treiber, 
korrekt? ) kommt dieselbe schrottige Ausgabe?

Und der Serial-Port deines Rechners ist der normale 9polige 
DB9-Male-Stecker? Dann schließe an diesem Stecker mal, zB. mit einer 
Krokodilklemme, die Pins 2 und 3 kurz (das sind der zweite und dritte 
von links in der oberen Reihe) und gucke, was das Terminalprogramm dann 
macht.

Gruss, Heinz

von katastrophenheinz (Gast)


Lesenswert?

Martin z. schrieb:
> Ich hab jetzt eine Lösung :)

Na, das war ja eine schwere Geburt ;-)
Gruss, Heinz

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.