Forum: Mikrocontroller und Digitale Elektronik Atmega8, UART@19,2 kHz


von Tom (Gast)


Lesenswert?

Hallo miteinander :)

Ich versuche meinen Atmega dazu zu überreden mit meinem Handy über den
UART kommunizieren zu lassen.

Ich kann mittels Hyperterm + einem MAX232 perfekt auf das Handy
zugreifen, ich schicke also z.B.: atd+4399999, das handy piepst und
meldet über UART zurück: NO CARRIER

Nun würde ich das ganze mit einem Atmega8 versuchen.

Dazu habe ich Pin2 (RXD) des Atmega8 mit TXD des Handies verbunden
(über 1kOhm). Ebenso Pin3 (TXD) mit RXD des Handies.

Bezüglich Code habe ich mir die UCR Register folgendermassen überlegt:
* UCSRA = 0x02;
* UCSRB = 0x08;
* UCSRC = 0x06;
* UBRRL = 25;

im Detail:
UCSRA - nur das Bit U2X ist gesetzt (Verdoppelung des Taktes)
UCSRB - TXEN ist gesetzt (ich will vorerst nur mal was senden)
UCSRC - 8N1 (selbe Einstellung wie in Windows Hyperterm)
mit UBRRL = 25 und einem Takt von 4MHz (interner Osz.) sollte ich also
auf die 19,2kHz kommen.
Nur es wird wahrscheinlich genau nichts übertragen. Auch der PC ist
noch angesteckt, ich sollte also sehen, ob da was kommt, aber das Handy
piepst nicht einmal. Zum schreiben verwende ich die folgenden Funktionen
aus dem Tutorial:

int uart_putchar(char c)
{
  if (c == '\n')
    uart_putchar('\r');
  loop_until_bit_is_set(UCSRA, UDRE);
  UDR = c;
  return 0;
}

void uart_puts(const char *s)
{
  char c;

  while ((c = *s++) != '\0')
    uart_putchar(c);
}


Weiss vielleicht jemand was ich denn hier falsch mache? Ich verzweifle
nämlich bald einmal :(
Danke für jegliche Hilfestellung :)

von marcel (Gast)


Lesenswert?

hast du ubbrh gesetzt? mit einem externen quarz probiert? manchmal ist
der interne oszillator zu ungenau für u(s)art...

von Tom (Gast)


Lesenswert?

auf was muss ich ubrrh setzen ?

mit einem externen quarz würd ichs nur im notfall probieren wollen
(obwohl ich eh grad 4 MHz herumliegen hätte). ausserdem ist im
Datasheet ja bei 4MHz ein Fehler von 0,2% oder so angegegeben .. das
sollt doch ausreichen, oder ?

weisst du zufällig was der unterschied zwischen synchronem und
asynchronem transfer ist ?

ich kenn das nur so:
synchron: ich sende was, und der uC macht erst weiter wenn das zeugs
weg ist.
asynchron: ich sende was, der uC macht sofort weiter und springt dann
dafür wenn er fertig ist in eine Routine.
Ist das sowas - oder hat das hier eine andere bedeutung ?

anyway, danke mal für deine Antwort :)

von marcel (Gast)


Lesenswert?

also ubbrrh (ein b oder ein r streichen - wer denkt sich diese namen aus
;)) auf 0 setzen, wenn dort ein falscher wert drin steht, dann geht's
nicht (auch nach einem reset den wert setzen)

der interne rc-oszillator hat auch einen fehler und der kommt noch dazu
(auch wenn der kallibriert werden kann).

AFAIK:
synchron und asynchron bezieht sich auf den bus. du hast an dem uart
noch eine takt-leitung dran, im asynchronen modus wird die nicht
genommen und ein interner taktgeber gibt den takt für die bits an.
im synchronen modus gibt das signal am XCK-Pin den takt vor.

von marcel (Gast)


Lesenswert?

das mit dem ubbrrh hängt mit dem ursel bit in dem control register
zusammen (hab nur das mega16 datenblatt hier -> schau mal bei ucsrc
nach)

das mit dem, synchronen und asynchronen modus steht auch im datenblatt

von dave (Gast)


Lesenswert?

Wenn du bit 7 (URSEL (Uart Register SELect, logische Namen)) setzt, dann
kannste an UCSRC kommen, sonst erwischte UBBRH.

Wenn ich das so ansehe hat marcel Recht... du hast in UBBRH 6
reingeschrieben.. du musst 6+128 reinschreiben.. nimm bitte die
Schreibweise: UCSRC = (1<<URSEL)+ oder |....

dave

von marcel (Gast)


Lesenswert?

lad dir avr studio runter und probier den code im simulator.
dann musst du zwar die funktion der interrupt flags per hand emulieren,
mir ist dabei auch der "fehler" mit dem ubbrh aufgefallen
(hatte das selbe problem)

mögen die register mit dir sein!

von Tom (Gast)


Angehängte Dateien:

Lesenswert?

sooo .. erstmal ein herzliches Danke an alle, die geantwortet haben.

Habe jetzt mal den Code etwas leserlicher geschrieben (es hat sich nur
mal das uart init geändert):

void UARTinit(void)
{
  UCSRA |= (1<<U2X);
  UCSRB |= (1<<TXEN);
  UCSRC |= (1<<URSEL);
  UCSRC |= (1<<UCSZ1) | (1<<UCSZ0); // write Character Size into UCSRC

  UCSRC &= ~(1<<URSEL); // now select the UBRRH
  UBRRH = 0x0; // write 0
  UBRRL = 25;
}

allerdings dürfte da immer noch was nicht so ganz stimmen. im simulator
wird nämlich immer das UBRRH mitgesetzt. Weiss vielleicht jemand woran
das liegt?
Ich mache es ja folgendermaßen:
UCSRC |= (1<<URSEL); - selektiere das UCSRC Register
UCSRC |= (1<<UCSZ1) | (1<<UCSZ0); - Character Size setzen
UCSRC &= ~(1<<URSEL); - UBRRH selektieren
UBRRH = 0x0; - 0 schreiben (sind ja nur 4 Bits).

aber irgendwie ändert sich das UCSRC auch mit?!? Was wäre denn die
Korrekte schreibweise?

Ich habe mir erlaubt mal das .elf anzuhängen - Plattform ist ein
Atmega8

von marcel (Gast)


Lesenswert?

ich glaub der simulator kann das nicht unterscheiden, weil die daten die
selbe adresse haben.
dann steht da noch im datenblatt, dass das lesen aus ubrrh "etwas
schwieriger" sei... also proggen und probieren (es sieht korrekt aus),
...

häng den atmega am besten über den max (bzw. einpaar zdioden) mit einem
(null)modem kabel an den computer und schau mit hyperterminal o.Ä. nach
was ankommt.

von Tom (Gast)


Lesenswert?

verdammt ... blödes ubrrh ...

der uC hängt eh wie auch das handy am MAX232 (über 1kOhm) .. nur es
kommt eben rein gar nichts am PC an.

--PC -- MAX232 --- Handy
               --- uC

wobei der uC direkt mit dem Handy verbunden ist ...

Ich werd jetzt wohl mal das handy abstecken und schauen was passiert :)

von Tom (Gast)


Lesenswert?

nachtrag: danke marcel, für deine bemühungen :)

von Werner B. (Gast)


Lesenswert?

Zu was willst Du denn dazu-verodern?
Ich weiss nicht welcher schrott vorher drinstand, das mach keinen
sinn.
Im simulator steht immer null drin, in real life ???


void UARTinit(void)
{
  UCSRA |= (1<<U2X);
  UCSRB |= (1<<TXEN);
  UCSRC |= (1<<URSEL);

von Tom (Gast)


Lesenswert?

da muss ich jetzt aber mal wiedersprechen ...
bspsweise UCSRA: da ist das UDRE standardmässig auf 1 (lt. Datenblatt).
Ebenso im Simulator, dort ist standardmässig UCSRA = 0x20 (was dem
obigen entspricht).

von Werner B. (Gast)


Lesenswert?

... und bei einem schnellen Blick aufs Programm nicht mehr
nachvollziehbar. Hier fehlt die Tranzparenz.

von Tom (Gast)


Lesenswert?

@Werner B.: sollte ich deiner meinung nach also immer nur = statt |=
verwenden?
Das bezüglich der Transparenz stimmt natürlich. Man kann ja das DB
nicht auswendig kennen:)


Bzgl. Anderem: Es funktioniert mittlerweile. Anscheinend hatte ich
einen Denkfehler mit TXD und RXD, dann noch ein paar kleinere Dinge und
mittlerweile wählt mein Atmel meine Rufnummer :)

Einen herzlichen Dank derweil mal an alle die mitgeholfen haben, es
geht sicher bald wieder weiter :)

von Werner B. (Gast)


Lesenswert?

Nicht immer, aber wenn es der nachvollziehbarkeit des codes dient.
Warscheinlich bist Du es selbst der ihn irgenwann einmal ändern muss.

Code möglicht selbstdokumentierend schreiben. Das ist auch der vorteil
wenn man die macros verwendet (1<<irgendwas) statt nur z.B. 64.
Ebenso für UBRR den wert die formel als macro unter Verwendung der
baudrate (BAUDRATE/16)-1; (Irgendwie muss bei Dir noch der U2X
berücksichtigt werden). Der compiler/präprozessor kann das ausrechnen
und mit einem blick in den sourcecode weiss man was eingestellt wird
bzw werden soll ohne lange zurückrechnen zu müssen.

von Tom (Gast)


Lesenswert?

hmm .. ja . .diesbezüglich hast natürlich recht :)
Musste mich erstmal an die Schreibweise gewöhnen - meine C Zeiten sind
halt doch schon länger vorbei ...
Doku ist sowieso selbstverständlich :)

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.