Atmega8, UART@19,2 kHz

Gast #168698
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 :)
Gast #168700
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 :)
Gast #168701
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.
Gast #168702
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
Gast #168703
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
Gast #168704
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!
Gast #168705
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
Angehängte Dateien:
Gast #168706
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.
Gast #168707
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 :)
Gast #168709
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);
Gast #168710
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).
Gast #168712
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 :)
Gast #168713
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.
Gast #168714
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 :)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren