Forum: Mikrocontroller und Digitale Elektronik Verständnissfrage Serielles Senden - UDR Register


von Matthias L. (lindner8712)


Angehängte Dateien:

Lesenswert?

Liebe Gemeinde,

ich bin vor kurzem von Bascom auf C umgestiegen. Nachdem ich das AVR GCC 
Tutorial durchgearbeitet habe und ein paar LED's blinken lassen habe,

wollte ich eine vor kurzem geschriebenen Code in Basic (2 Drehencoder, 
Daten seriell senden) nun in C übersetzen. Die Logik, Interrupts usw. 
funktioniert soweit auch nur aus irgendeinem Grund empfange ich mit 
Putty keine Daten.
Habe auch mit der Foren-Suchfunktion bzw. Google nichts finden können!!

Anbei die - meiner Meinung nach wichtigen Code Zeilen;
1
#define F_CPU 16000000UL
2
#define BAUD 250000UL
3
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   
4
5
Serial[0]=1;
6
Serial[1]=2;
7
Serial[2]=7;
8
Serial[3]=-;
9
Serial[4]=2;
10
Serial[5]=5;
11
Serial[6]=5;
12
Serial[7]=;;
13
14
UCSRC |= ((1<<UMSEL)|(1<<UCSZ1)|(1<<UCSZ0));
15
UCSRB |= (1<<RXEN)|(1<<TXEN)|(1<<RXCIE);
16
UBRRH = UBRR_VAL >> 8;
17
UBRRL = UBRR_VAL & 0xFF;
18
19
ISR( TIMER1_OVF_vect )               
20
{                
21
22
for(uint8_t Send=0;Send<sizeof(Serial);Send++)                           {                           
23
UDR=Serial[Send];                              
24
UDR_DBG=Serial[Send];               
25
}                  
26
27
}
Eigentlich sollte ich in Putty ja 127-255; empfangen
Selbst wenn die Baudraten bzw. CPU Takt nicht stimmen, empfängt Putty 
wenigstens Datenmüll nur bei mir kommt garnix an!

Wäre nett wenn mir hier wer weiterhelfen könnte.
Vielen Dank im Vorraus für eure Hilfe!!

von holger (Gast)


Lesenswert?

>for(uint8_t Send=0;Send<sizeof(Serial);Send++)
>{
>UDR=Serial[Send];
>UDR_DBG=Serial[Send];
>}

Jo, immer schön in UDR reinballern und bloss nicht warten
bis das Byte auch gesendet werden konnte.

Kein Wunder das das nicht geht.

von René B. (reneb)


Lesenswert?

Was Holger meint ist, dass du immer erstmal auf das UDR-empty Bit warten 
solltest, bevor du neue Daten dort reinschaufelst.
Einfach in die Schleife vor dem befüllen von UDR
while (!(UCSRA&_BV(UDRE)));
einfügen.

Und UBRR errechnet sich als FCPU/16/baud-1:
Für 19.2k bei 16MHz CPU mal 51 hart in UBRRL schreiben und in UBRRH eine 
0.

von Martin N. (kaktus2)


Lesenswert?

und dies Zeile:
1
UCSRB |= (1<<RXEN)|(1<<TXEN)|(1<<RXCIE);

würde ich noch klammern:
1
UCSRB |= ((1<<RXEN)|(1<<TXEN)|(1<<RXCIE));

von Peter II (Gast)


Lesenswert?

Martin N. schrieb:
> würde ich noch klammern:

warum?

von Matthias L. (lindner8712)


Lesenswert?

Hallo zusammen,

vielen Dank für die Antworten! :-)

Das mit der While schleife leuchtet ein, werde ich gleich anwenden. Da 
hat mir meine ewige Bascomprogrammierung einen "Streich" gespielt!! 
(printbin)

2. BAUD-RATEN Berechnung: Ich hab das Makro zwar so aus dem Tutorial 
kopiert, aber weiter oben steht ja die Formel wie von dir angegeben, 
wird ebenfalls angepasst!

Vielen Dank an euch schonmal für die schnellen Antworten!!

Gruß

Matthias

von Matthias L. (lindner8712)


Lesenswert?

Martin N. schrieb:
> würde ich noch klammern:UCSRB |= ((1<<RXEN)|(1<<TXEN)|(1<<RXCIE));

@Martin N. da geb ich dir recht... man sollte sich als Anfänger eine 
einheitliche Schreibweise angewöhnen!

Danke für den Hinweis!

Matthias

von Wolfgang (Gast)


Lesenswert?

Matthias Lindner schrieb:
> Serial[0]=1;
...
> Serial[7]=;;

Guck dir mal an, wie in C Charakter-Konstanten aussehen.
So wird PUTTY da bestimmt nicht den Text "127-255;" empfangen - und das 
meinst du doch, oder?

von Matthias L. (lindner8712)


Lesenswert?

Hi,

Char ist in einfache Anführungszeichen zu setzen... also Serial='X';

Nur im Code sieht das wie folgt aus

volatile uint8_t Interm=45;     //Das - zeichen ist Datenblockende
volatile uint8_t Term=59;       //Semikolon ist Sendeende
volatile uint8_t Serial[8];     //Serielles Senderegister

Ich habe mir gedacht, wenn ich anhand der ASCII Tabelle das jeweilige 
Zeichen (anhand der Nummer) in eines der Bytes schreibe, kann der 
"Master"
sorry der läuft mit Bascom.. :-( das auch lesen. Soll heißen, das 
darzustellende zeichen berechnen z.b. 1 und dann 48 für Zahlenwerte 
addieren. Somit ist man in der ASCII Tabelle auf Pos 49 und somit bei 
"1"
Auch Putty kann das... oder konnte es als der Code noch als 
Bascom-Version lief.

Encoder_1_100=1;

Serial[0]=Encoder_1_100+48; // 1+48 = 49 ASCII Tabelle liefert 1 zurück
Serial[3]=Interm;           // daraus folgt >> Serial[3]=-
Serial[7]=Term;             // daraus folgt >> Serial[7]=;

An dieser Stelle muss ich mich wohl entschuldigen, da ich nicht alle 
Relevanten Codezeilen gepostet habe!!

Tut mir Leid

Matthias

von holger (Gast)


Lesenswert?

>>Serial[3]=-;
>>Serial[7]=;;
>
>Guck dir mal an, wie in C Charakter-Konstanten aussehen.

Wobei die beiden Zeilen oben nie einen C Compiler gesehen haben können.
Der hätte alles vollgekotzt.

>Anbei die - meiner Meinung nach wichtigen Code Zeilen;

Zeige nie Code den du nachweislich NICHT verwendet haben kannst.

Und rück deinen Code mal vernünftig ein. Oder speicherst du deinen Code
noch auf Diskette? Ein paar Spaces oder Tabs würden die Lesbarkeit
deutlich erhöhen.
1
int main(void)
2
{
3
  Bier_aufmachen();
4
5
  while(1)
6
  {
7
    if(Bier_is_alle() && Bier_vorhanden())
8
    {
9
      Mach_neues_Bier_auf();
10
    }
11
    else
12
    {
13
      Wecker_stellen();
14
      Schlafen_gehen();
15
    }
16
  }
17
}

Dann kann man deinen Code lesen wie eine Geschichte;)

von Matthias L. (lindner8712)


Angehängte Dateien:

Lesenswert?

@ Holger:

Danke für die Belehrung, ich werde versuchen mich in Zukunft daran zu 
halten!!!

Anbei nochmals mein Source file... eingerückt und mit allen 
Verbesserungen die ihr mir gennant habt; werde das dann morgen mal im 
Labor testen!

Bis dahin vielen Dank an ALLE!!

Grüße

Matthias

EDIT: Das mit der Diskette hab ich jetzt nicht verstanden... Aber ist ja 
auch egal! :-)

von Karl H. (kbuchegg)


Lesenswert?

>    if (PIND&(0<<PIND2)) Encoder_1_new |= (0 << Track0);

Das ist eine 0-Operation. Kannst du genauso gut auch einfach weglassen.

* so testet man nicht auf ein 0-Bit
* so werden Bits nicht auf 0 gesetzt

Bitmanipulation

Und nein, du darfst auf keinen Fall
* ein C Buch lesen
* anderer Leute C Code studieren
ansonsten bekommst du sofort Augenkrebs.

von Karl H. (kbuchegg)


Lesenswert?

> volatile uint8_t Term=59;                       //Semikolon ist Sendeende

Warum schreibst du dann nicht ganz einfach
1
volatile uint8_t Term = ';';                       //Semikolon ist Sendeende

oder hier

>     Serial[0]=Encoder_1_100+48;
1
     Serial[0]=Encoder_1_100 + '0';

schreib das, was du meinst und so dass es lesbar ist! Dein Compiler 
kennt die ASCII Codes. Es gibt keinen Grund, warum du dir die Mühe 
machen sollst und die raussuchen musst.

Ausser natürlich, man programmiert BASCOM. Aber das hier ist C.

von Walter S. (avatar)


Lesenswert?

warum muss das Senden in einer Interruptroutine erfolgen?

von Matthias L. (lindner8712)


Lesenswert?

Also ihr habt recht... ich werde nochmal zurück ans "Reißbrett" gehen 
und mich genau in die Sprache C einlesen! Hab mir von meinen JAVA Skills 
doch zuviel erhofft.
1
int main(void)
2
{
3
  
4
  while(1)
5
  {
6
    if(C_Buch_gelesen() && Code_Samples_durchforstet() && Problem() )
7
    {
8
      Nochmal_fragen();
9
    }
10
    else
11
    {
12
      Nochmal_nachlesen();
13
      Probieren();
14
    }
15
  }
16
}
Sorry das ich eure Zeit verschwendet habe!!!

von Karl H. (kbuchegg)


Lesenswert?

Wenn wir schon dabei sind

das hier ....
1
     switch(Encoder_1_diff)
2
     {
3
        case 1:Encoder_1_value++;
4
      case 2:Encoder_1_value--;
5
      }
... meinst du garantiert nicht so. Lies nach, was es mit break auf sich 
hat und warum du (meistens) in einem case einen brauchst.
Dein obiger Code mal bereinigt, bleibt übrig
1
     if (Encoder_1_diff == 2)
2
       Encoder_1_value--;
und ich denke aus dem Bauch heraus nicht, dass das die Idee an dieser 
Stelle war.

von Matthias L. (lindner8712)


Lesenswert?

Karl Heinz Buchegger schrieb:
> ... meinst du garantiert nicht so. Lies nach, was es mit break auf sich
> hat und warum du (meistens) in einem case einen brauchst.

Stimmt, hab diesen Fehler heute Morgen noch gefunden... die Switch 
anweisung schaut genau so aus wie in JAVA.

Trotz allem Funktioniert jetzt das Hauptprogramm!!! Also 
Encoderauswertung und TIMER0 Interrupt!

Bevor ich mich an die Serielle Schnittstelle mache, muss ich wohl noch 
lesen und lernen, aber jetzt sind ja eh erstmal 6 Wochen Ferien.

Trotz allem, vielen Dank für eure Ratschläge und Verbesserungen!
Beim nächsten mal denke ich nach ob und was ich poste.

Grüße

Matthias

von Matthias L. (lindner8712)


Lesenswert?

Nochmal ich,

das Projekt funktioniert jetzt!!! Hatte UMSEL gesetzt.... habe das 
deaktiviert und jetzt funktionierts wie es sein soll!! und jedemenge 
anderer Fehler die Ihr gefunden habt!!

@Moderator:
1. wie kann ich bzw. darf ich den Thread schließen??
2. Besteht Interesse am Sourcecode?

Gruß

von Karl H. (kbuchegg)


Lesenswert?

Matthias Lindner schrieb:

> Beim nächsten mal denke ich nach ob und was ich poste.

Du sollst vor allen Dingen C lernen, ehe bzw. im Zuge dessen, was du 
programmierst.
Allgemein wird empfohlen sich ein C-Buch zu besorgen und damit die 
ersten Schritte auf einem PC(!) zu machen. Wenn du das C-Buch zu einem 
guten Drittel durch hast, hast du das Rüstzeug um dir die Besonderheiten 
der µC-Programmierung näher zu bringen.

Klar gehts auch so. Aber deine Frustschwelle muss um einiges höher sein. 
Lernen und was damit zusammenhängt, seine ersten Fehler debuggen, geht 
nun mal auf einem PC um Größenordnungen einfacher als am AVR.

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.