Forum: Mikrocontroller und Digitale Elektronik Schwierigkeiten mit dem UART AtTiny2313A


von Maximilian G. (chainex)


Angehängte Dateien:

Lesenswert?

Hallo liebes Forum,

ich habe leider ein sehr peinliches Problem.
Ich versuche nun schon seit geraumer Zeit mit meinem AtTiny2313A mittels 
UART (Asynchron) Daten zu senden.

Soweit hab ich das Datenblatt auch einigermaßen verstanden und der Code 
läuft im Simulator Debugger einwandfrei durch. Nur leider kommt aus dem 
realen Baustein an PD1 nichts heraus (kein Signal nur LOW).
Eine weitere komische Sache ist wenn ich im Debugger auf die Zeile 
springe in der ich UDR beschreibe steht nach dem beschreiben immernoch 
0x00 drin?.


Jetzt wollte ich einmal fragen ob jemand vielleicht etwas an meine Code 
auffällt was daran schuld sein könnte, ich bin leider noch etwas 
unbeholfen...

PS: Ich hatte das ganze auch mal mit einem festen Zahlenwert (12) statt 
dem String versucht kam aber auch nichts bei raus.
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
#define   F_CPU 8000000
5
#define   Baud_Multip_H 0
6
#define   Baud_Multip_L 51    // BAUD 9600
7
#define   Prellzeit 100
8
9
#define Debug 1  
10
11
12
int  Senden(unsigned char Zeichensatz[255],int Datenlange)
13
{
14
  int Senden_erfolgreich = 0;  
15
  
16
  UCSRB  |=  (1 << TXEN);    // Senden aktivieren
17
  
18
  
19
  for (int Durchlauf = 0;   Durchlauf <= Datenlange;  Durchlauf++)
20
  {
21
    while (!( UCSRA & (1 << UDRE)) )  // UDRE gecleart? "DATA REGISTER EMPTY" (Senden Abgeschlossen!)
22
    {  /*  warten */  }
23
    
24
    if(Debug == 1)  {PORTB  |=  (1 << PORTB1);}          // Senden starten sig
25
    UDR  =  Zeichensatz[Durchlauf];  
26
    if(Debug == 1)  {PORTB  &=  ~(1 << PORTB1);}        // Senden abgeschlossen sig
27
    
28
    
29
    
30
    
31
    while (!( UCSRA & (1 << TXC)) )
32
    {  /*  warten */  }
33
  
34
    if (    ( UCSRA & (1 << UDRE))   &&    ( UCSRA & (1 << TXC))  )
35
    {
36
      Senden_erfolgreich = 1;    // wenn Buffer leer und gesendet war Senden okay
37
    }
38
  
39
    
40
    UCSRA &= ~(1 << TXC);    // Transmit Flag löschen
41
    
42
  }
43
  
44
  UCSRB  &=  ~(1 << TXEN);    // Senden deaktivieren
45
  
46
  
47
  return Senden_erfolgreich;
48
}
49
50
51
52
53
54
int main(void)
55
{
56
  int Prellen = 0;
57
  
58
  PORTB  =  (1 << PORTB0);      // Pull UP
59
  DDRB  =  (1 << PORTB1);
60
  UBRRL  =  Baud_Multip_L;      // Baudrate
61
  UBRRH  &=  0b11110000;        // Register Löschen
62
  
63
  // Settings Register  
64
  
65
  UCSRC  |=  (1 << UCSZ0) | (1 << UCSZ1) ;
66
  
67
    while (1) 
68
    {
69
    
70
    if (  !(PORTB  &  (1 << PORTB0)))            // Taster Da?
71
    {
72
      Prellen = 0;
73
      
74
      while (Prellen < Prellzeit)              // Entprellen
75
      {  
76
        if ((PORTB  &  (1 << PORTB0)))    {  Prellen++;    }  
77
        else                {  Prellen = 0;  }  
78
      }
79
      
80
      
81
    Senden("Hallo!"  ,  6  );  
82
      
83
  }
84
  
85
    }
86
}

von conundrum (Gast)


Lesenswert?

PORTD1 ist nirgendwo als Ausgang definiert. Aber wenn D1 ein Eingang 
ist, dann müsste er hochohmig sein und nicht 0.

Wie hast du das LOW gemessen? Mit Multimeter und Oszi kriegst du 0 
angezeigt, aber das ist nicht unbedingt ein Ausgang auf Low, ohne Pullup 
kann das auch ein Eingang sein. Ein Logiktester zeigt den wahren 
Zustand.

Bin mir nicht ganz sicher, aber es ist einen Versuch wert.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Maximilian G. schrieb:
> Jetzt wollte ich einmal fragen ob jemand vielleicht etwas an meine Code
> auffällt was daran schuld sein könnte, ich bin leider noch etwas
> unbeholfen...

 Wenn etwas nicht klappt, dann macht man den Code so kurz wie nur
 irgendwie möglich und schmeisst alles unnötige raus...

 Irgendwelche Taster auf Prellen abfragen kann man später, wenn
 überhaupt - hat sowieso nichts mit deinem Problem zu tun, kann
 aber sehr wohl selbst Probleme verursachen.
 Ich habe gerade keinen 2313 zur Hand aber folgender Code läuft
 im Simulator ohne Probleme:
1
int main(void)
2
{
3
  int Prellen = 0;
4
  
5
  PORTB  =  (1 << PORTB0);      // Pull UP
6
  DDRB  =  (1 << PORTB1);
7
  UBRRL  =  Baud_Multip_L;      // Baudrate
8
  UBRRH  &=  0b11110000;        // Register Löschen
9
  
10
  // Settings Register  (Das braucht man aber normalerweise nicht, das ist schon Init Value)
11
  UCSRC  |=  (1 << UCSZ0) | (1 << UCSZ1) ;
12
  
13
    Senden("Hallo!"  ,  6  );  
14
}

Maximilian G. schrieb:
> Eine weitere komische Sache ist wenn ich im Debugger auf die Zeile
> springe in der ich UDR beschreibe steht nach dem beschreiben immernoch
> 0x00 drin?.

 Da machst du etwas falsch.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

conundrum schrieb:
> PORTD1 ist nirgendwo als Ausgang definiert.

 Egal, hiermit wird das schon richtig gemacht:
1
  UCSRB  |=  (1 << TXEN);    // Senden aktivieren

von S. Landolt (Gast)


Lesenswert?

Eingänge werden mit PIN abgefragt, also zweimal PINB statt PORTB.

von S. Landolt (Gast)


Lesenswert?

> noch etwas unbeholfen...

Ein Kopieren des Aufrufs von Senden vor die while-Schleife hätte 
gezeigt, dass das Problem nicht beim USART liegt.

von holm (Gast)


Lesenswert?

Wartest Du auf PD1 auf ein Signal während Du PB1 programmierst?

Gruß,
Holm

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

S. Landolt schrieb:
> Ein Kopieren des Aufrufs von Senden vor die while-Schleife hätte
> gezeigt, dass das Problem nicht beim USART liegt.

 Genau.
 Oder die (falsche) Abfrage vorerst ganz rausschmeissen.

von Maximilian G. (chainex)


Lesenswert?

S. Landolt schrieb:
> Eingänge werden mit PIN abgefragt, also zweimal PINB statt PORTB.

Danke mal wieder ein Anfängerfehler. :(

Habs nun geändert mal schauen wie es sich nun verhält... wenn es das 
gewesen wäre wäre das schon sehr peinlich.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Maximilian G. schrieb:
> Habs nun geändert mal schauen wie es sich nun verhält... wenn es das
> gewesen wäre wäre das schon sehr peinlich.

 Tja, dann fang schon mal an, dich zu schämen...

: Bearbeitet durch User
von Karl B. (gustav)


Angehängte Dateien:

Lesenswert?

Hi,
je nachdem welche inc. Datei Du nimmst,
gibt es Unterschiede.
also mit der "tn2313def.inc" fahre ich ganz gut.

Die nimmt dann auch das Adressenincrement.
Spart Code.

Quarz/Takt/Baudrate
weißt Du wie abändern, brauche ich nicht drauf einzugehen.

ciao
gustav

: Bearbeitet durch User
von c-hater (Gast)


Lesenswert?

Karl B. schrieb:

> je nachdem welche inc. Datei Du nimmst,
> gibt es Unterschiede.

Logisch. Deswegen nimmt man der Einfachheit halber schlicht die Richtige 
für das Target. Das Verfahren hat sich gut bewährt. ;o)

> also mit der "tn2313def.inc" fahre ich ganz gut.

Ist aber eigentlich die falsche für einen Tiny2313A. Stört allerdings 
nicht weiter, solange man nicht die zusätzlichen Features des 2313A 
benutzen will.

> Die nimmt dann auch das Adressenincrement.

???

Die beiden Includes unterscheiden sich nur sehr wenig, eigentlich 
praktisch nur dadurch, dass die zusätzlichen Features des 2313A halt nur 
in dessen Include auftauchen.

Auf jeden Fall gibt es aber keine Unterschiede, die irgendwas mit 
irgendeinem Adressincrement, welches irgenwer oder irgendwas "nimmt" 
oder "nicht nimmt", zu tun haben könnten...

von Karl B. (gustav)


Lesenswert?

Hi,
ist im Codeschnipsel auch nicht drin.
Was ich meinte:
Der lpm
nimmt dann nicht x+ y+ z+
print_0:
lpm
lpm  temp, z+  ; Inhalt des vom Z-Pointer adressierten ....

dann meckert der Assembliervorgang an:
 Error
no such instruction
oder instruction unknown bei
Benutzung von der "falschen" inc.

was mehr nervt, sind Synonyme
UCSRA
UCSRB
statt UCS
und so fort. Das "B" gibts nicht bei der anderen.
"For compatibility purposes you may use ...instead of..."

wie gesagt,
ich nehme jetzt "tn2313def.inc"
anstelle von "2313def.inc"
Und für"A" "Extrawurst" ok.

ciao
gustav

: Bearbeitet durch User
von Maximilian G. (chainex)


Lesenswert?

Also es funktioniert jetzt...

Mich wundert allerdings immernoch warum das im Debugger nicht erkannt 
wird (bzw funktioniert...).

Trotzdem vielen Dank ans Forum!

Gruß Max

von c-hater (Gast)


Lesenswert?

Karl B. schrieb:

> Was ich meinte:
> Der lpm
> nimmt dann nicht x+ y+ z+

lpm nimmt bei einem Tiny2313 und auch bei einem Tiny2313A niemals x+ 
oder y+, ganz egal mit welchem Include. Die lpm-Instruktion kann nur 
zwei Adressierungsarten, nämlich indirekt und indirekt mit 
postincrement. Und sie kann das beides ausschließlich mit dem 
Z-Register, also lpm reg,Z oder lpm reg,Z+. Auch das ist völlig 
unabhängig vom Include, funktioniert also sowohl beim 2313 als auch beim 
2313A gleichermaßen.

> print_0:
> lpm
> lpm  temp, z+  ; Inhalt des vom Z-Pointer adressierten ....
>
> dann meckert der Assembliervorgang an:
>  Error
> no such instruction
> oder instruction unknown bei
> Benutzung von der "falschen" inc.

Ja, wenn man ein Include von einem Target verwendet, was überhaupt keine 
lpm-Instruktion kennt, dann kann sowas passieren. Eben deswegen benutzt 
man sinnvollerweise das RICHTIGE für das Target.

> wie gesagt,
> ich nehme jetzt "tn2313def.inc"
> anstelle von "2313def.inc"

2313def.inc ist auch nicht für den Tiny2313 und schon garnicht für den 
Tiny2313A. Die ist für den ATS902313...

von Bernd (Gast)


Lesenswert?

Der TO postet C-Quelltext für AVR.
Dann kommt irgendwann Karl Gustav mit Assembler um die Ecke und faselt 
was von Adressenincrement.

Finde den Fehler.

von c-hater (Gast)


Lesenswert?

Bernd schrieb:

> Der TO postet C-Quelltext für AVR.
> Dann kommt irgendwann Karl Gustav mit Assembler um die Ecke und faselt
> was von Adressenincrement.
>
> Finde den Fehler.

Es gibt keinen. Auch in C muß man das richtige Include wählen, wenn was 
Sinnvolles und Funktionierendes rauskommen soll. Nur die Methode, wie 
man das konkret tut, ist üblicherweise eine andere...

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

c-hater schrieb:
> Auch in C muß man das richtige Include wählen

Ist doch alles da:

Maximilian G. schrieb:
> #include <avr/io.h>
> #include <avr/interrupt.h>

Wobei interrupt.h im Moment noch nicht gebraucht wird. Mehr brauchts 
unter C nicht, das richtige Device stellt man im Projekt ein.

von c-hater (Gast)


Lesenswert?

Matthias S. schrieb:

> Ist doch alles da:

Nö.

> das richtige Device stellt man im Projekt ein.

Eben.

Ob das tatsächlich geschehen ist, geht aus dem geposteten Zeug nicht 
hervor...

Er wäre nicht der erste C-Dengler, dem nicht klar ist, dass das getan 
werden muss und wie man das genau tut...

von Karl B. (gustav)


Lesenswert?

Maximilian G. schrieb:
> Mich wundert allerdings immernoch warum das im Debugger nicht erkannt
> wird (bzw funktioniert...).

Tja,
siehe oben.
#define Debug 1

was passiert da im Einzelnen?

ciao
gustav

von Maximilian Gaus (Gast)


Lesenswert?

Karl B. schrieb:
> Maximilian G. schrieb:
> Mich wundert allerdings immernoch warum das im Debugger nicht erkannt
> wird (bzw funktioniert...).
>
> Tja,
> siehe oben.
> #define Debug 1
> was passiert da im Einzelnen?
>
> ciao
> gustav

Wie meinen?
Der Gedanke war das oszi mit dem ausgang zu triggern. Um zu sehen ob pd 
sendet...

von Karl B. (gustav)


Angehängte Dateien:

Lesenswert?

Maximilian G. schrieb:
> Code
> läuft im Simulator Debugger einwandfrei durch.

Also ich verstehe das so:
Debugger Simulatoren können ( normalerweise) nicht auf Ereignisse von 
außen reagieren.
Ist doch keine Hardware mit echten Interfacen.
Ebensowenig auf Interrupts.
Die Simulatoren dienen bei mir in erstere Linie dazu, Syntaxschnitzer 
herauszufinden.

Oder die Zeitschleifen in Echtzeit laufen lassen.
Da hängt sich der Debugger meistens auf.
Stack overflow

(Er rattert immer noch.
Aber irgendwann crashed der.)

ciao
gustav

: Bearbeitet durch User
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.