Forum: Mikrocontroller und Digitale Elektronik U(S)ART funktioniert nicht richtig


von Treter_Peter (Gast)


Lesenswert?

Hallo zusammen,

Ich möchte eine Kommunikation mit meinen ATmega328P zum Pc hin 
realisieren.
Dazu habe ich das 'mysmartUSB MK||' Programmiergerät von der Interface 
Schnittstelle Pin7 und Pin8 (RxD, TxD) mit dem Atmega über Kreuz 
verbunden.
(RxD->TxD)
Außerdem verwende ich einen externen Quarz 4Mhz, den ich auch mit 22p 
Kondensatoren entsprechend dem Tutorial verbunden habe.
Die Fuse bits sollten entsprechen gesetzt sein. zur Kontrolle:
LowFuse:01110111 alles andere ist unverändert. Zum Programmieren 
verwende ich das AVRProgTool, was mit dem Programmer geliefert wurde.

Ich habe kein Oszi. Allerdings hatte ich Testweise ein 0,5 sek Takt auf 
eine LED gegeben, der nach der Umstellung vom Internen 8Mhz takt auf den 
ext. 4Mhz
entsprechen jetzt 1 sek ist.

Das Problem ist nun, das ich zwar über UART Schnittstelle ein Zeichen 
sende, es kommt aber nur die Dezimalzahl 128 und ein/0 vor und nach dem 
Zeichen, an.
Ich verwende das Hterm am Pc, um die empfangen daten mir an zu schauen.
Ich musste die Registerbezeichnung aus dem Tutorial etwas anpassen und 
ich denke das ich da irgentwo was vergessen habe.Hier noch der 
Quellcode:
1
#include <avr/io.h>
2
#include <stdlib.h>
3
/* 
4
  UART-Init: 
5
Berechnung des Wertes für das Baudratenregister 
6
aus Taktrate und gewünschter Baudrate
7
*/
8
 
9
#ifndef F_CPU
10
11
#warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 4000000"
12
#define F_CPU 4000000UL  // Systemtakt in Hz - Definition als unsigned long beachten 
13
                         // Ohne ergeben sich unten Fehler in der Berechnung
14
#endif
15
 
16
#define BAUD 9600UL      // Baudrate
17
 
18
// Berechnungen
19
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
20
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
21
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.
22
 
23
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
24
  #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch! 
25
#endif 
26
27
//UART-Schnittstelle Initialisieren
28
void uart_init(void)
29
{
30
  UBRR0H = UBRR_VAL >> 8;
31
  UBRR0L = UBRR_VAL & 0xFF;
32
  
33
  UCSR0B |= (1<<TXEN0);  // UART TX einschalten
34
  UCSR0C |= (1<<UCSZ00) | (1<<UCSZ01); // UART 8-Bit Modus
35
}
36
37
38
//Atmega328P
39
int uart_putc(unsigned char c)
40
{
41
  while (!(UCSR0A & (1<<UDRE0)))  /* warten bis Senden moeglich */
42
  {
43
  }
44
  
45
  UDR0 = c;                      /* sende Zeichen */
46
  return 0;
47
}
48
49
//Hauptprogramm
50
int main(void)
51
{
52
  //Einmalig abgearbeite Kommandos
53
  DDRC |= (1<<PC5);        //Definiert PortC Pin 5 als Ausgang
54
  DDRB &= ~(1<<PB0);        //Definiert PortB Pin 0 als Eingang
55
  uart_init();  //UART-Initialisierung aufrufen
56
57
  //Lokale Variablen
58
  uint8_t Flanke = 0;
59
  char y;
60
  
61
  //Zyklisches Programm
62
    while(1)
63
    {
64
    if(PINB & (1<<PINB0)){
65
      if(Flanke==0){
66
        y = 6 + '0';
67
        uart_putc('x');
68
        Flanke = 1;
69
      }      
70
    }else{
71
      Flanke=0;
72
     } 
73
74
         
75
    }
76
}

von Karl H. (kbuchegg)


Lesenswert?

> #ifndef F_CPU
>
> #warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 4000000"
> #define F_CPU 4000000UL  // Systemtakt in Hz - Definition als
>                         // Ohne ergeben sich unten Fehler
> #endif


Mach da mal ein einfaches

#define F_CPU 4000000UL  // Systemtakt in Hz - Definition als

draus. Also ohne diese ganze Absicherung. Denn wenn in deinen 
Projekteinstellungen noch immer 8Mhz drinnen steht, dann werden die 4Mhz 
hier nicht wirksam und die ganze Berechnung der Konstanten ist dann 
falsch.


Diese sog. 'Absicherung' ist in den meisten Fällen kontraproduktiv. Wenn 
F_CPU in den Projekteinstellungen nicht gesetzt ist, dann sollte man das 
durchaus als Fehler werten und an der Quelle beheben. Derartige 
Default-Sicherungsnetze erweisen sich ein ums andere mal als 
kontraproduktiv.

von Treter_Peter (Gast)


Lesenswert?

Hm, das kann auch nicht die Ursache sein. Hab den errechneten Wert mal 
Manuel ins Ubbr geschrieben.

von hilmar (Gast)


Lesenswert?

1
    while(1)
2
    {
3
    if(PINB & (1<<PINB0)){
4
      if(Flanke==0){
5
        y = 6 + '0';
6
        uart_putc('x');
7
        Flanke = 1;
8
      }      
9
    }else{
10
      Flanke=0;
11
     } 
12
13
         
14
    }

Kann es sein, daß du immer nur den Buchstaben 'x' ausgibst und alles 
andere, was hier steht, für die Katz ist?

Ich vermute, du meinst:
1
uart_putc(y);

Vermute ich richtig?

von Sebastian W. (sebastian_w29)


Lesenswert?

Ich würde erst mal laut Table 19-10 UBRR0H auf 0 und UBRR0L fest auf 25 
setzen.

Welche Daten GENAU kommen im hterm an, und mit welchem Timing? Framing 
errors?

Für solche Fälle wäre natürlich Oszi und/oder Saleae sehr hilfreich.

LG, Sebastian

von Treter_Peter (Gast)


Lesenswert?

hilmar schrieb:
> Kann es sein, daß du immer nur den Buchstaben 'x' ausgibst und alles
> andere, was hier steht, für die Katz ist?

Diese ganzen if- abfragen sind dafür, das nur einmal die daten gesendet 
werden wenn ich den schalter betätige. Der Flankenmerker ist dafür, das 
das zeichen wirklich nur 1 mal pro schaltimpuls gesendet wird.


Sebastian W. schrieb:
> Ich würde erst mal laut Table 19-10 UBRR0H auf 0 und UBRR0L fest auf 25
> setzen.
>
> Welche Daten GENAU kommen im hterm an, und mit welchem Timing? Framing
> errors?

Hab mehrere Baud-raten probiert auch mit Manuel direkt schreiben. Welche 
Tabelle meinst du, die im Datenblatt?
Genau kommt an: /0 128 /0 (Dezimal)
eigentlich sollte genau 1 Zeichen (das 'x')ankommen. Timing, Framing? 
was meinst du damit? Ich sende das zeichen mit dem Schalter doch genau 1 
mal. Das funktioniert auch. Ich sehe den Schaltimpuls und empfange auch 
nur 1 mal etwas.

von spontan (Gast)


Lesenswert?

Tja, die If-Abfragen sind gut gemeint, aber recht sinnlos um einen 
Schalter zu entprellen.
Bei einem idealen Schalter ist es so in Ordnung.

Aber es ist genau das Wesen des Prellens, wenn der Schalter schließt, 
öffnet, schließt ...

Du erkennst bei jedem Prellen einen Tastendruck.

von Treter_Peter (Gast)


Lesenswert?

spontan schrieb:
> Tja, die If-Abfragen sind gut gemeint, aber recht sinnlos um einen
> Schalter zu entprellen.
> Bei einem idealen Schalter ist es so in Ordnung.
>
> Aber es ist genau das Wesen des Prellens, wenn der Schalter schließt,
> öffnet, schließt ...
>
> Du erkennst bei jedem Prellen einen Tastendruck.

Ich weiß, es geht dabei ja auch nur darum, das nicht andauernt das 
Zeichen gesendet wird. Ist doch nur nen Versuchsaufbau.
Ist aber gut gemeint, Danke :-)
DAs wesetliche Problem ist nur, das das X nicht so ankommt ;)

von spontan (Gast)


Lesenswert?

Was sendest Du eigentlich?

Nicht 0x36, sondern 0x78. Was willst Du senden?

Stimmen die Übertragungsparameter?

von Treter_Peter (Gast)


Lesenswert?

spontan schrieb:
> Was sendest Du eigentlich?
1
 uart_putc('x');

Ich sende das ASCII-Zeichen 'x' als unsigned char. Das sollte auch genau 
so ankommen.

LG

von Sebastian W. (sebastian_w29)


Lesenswert?

Seltsam.

Du sendest 0x78, also 01111000. Also sollte auf dem TX-Pin 
...HHHLLLLHHHHLHHHH... gesendet werden, also nach dem Ruhe-High ein 
low-Pegel von 4*104us, dann ein high-Pegel von 4*104us, dann ein 
low-Pegel von 1*104us, dann ein high-Pegel von mindestens 1*104us (der 
dann aber Ruhe-High bleibt wenn keine weiteren Zeichen folgen).

Du empfängst /0 128 /0, also drei Zeichen. Was du mit /0 meinst ist mir 
nicht ganz klar. Meinst du 0? Wenn der PC drei Zeichen empfängt muss er 
ja zumindest drei Mal ein Startbit erkennen.  Eine 0 ist bei 9600 Baud 
ohne Parity ein low-Pegel von 9*104us, eine 128 ein low-Pegel von 
8*104us. Der Atmega scheint zu langsam zu senden. Dann müsste aber auf 
jeden Fall die erste empfangene 0 einen Framing-Error melden weil das 
Stop-Bit fehlt (im hterm gibt es da die Checkbox "Show errors", um 
Framing- und Parity-Fehler anzuzeigen), und die zweite 0 passt auch 
nicht ganz zu dieser Hypothese.

Ich würde an deiner Stelle wohl den TX-Ausgang mal (auf eigene Gefahr) 
über einen Spannungsteiler an den Mikrofoneingang deines PC hängen und 
mir das gesendete Signal mit Audacity anschauen. Bei 9600 Baud sollten 
44kHz Samplingrate ja reichen um einen Eindruck zu bekommen. Eventuell 
kann dein Soundchip ja 48kHz, 96kHz oder sogar 192kHz. Oder du 
reduzierst die Baudrate erst mal.

LG, Sebastian

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.