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 :)
hast du ubbrh gesetzt? mit einem externen quarz probiert? manchmal ist der interne oszillator zu ungenau für u(s)art...
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 :)
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.
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
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
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!
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
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.
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 :)
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);
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).
... und bei einem schnellen Blick aufs Programm nicht mehr nachvollziehbar. Hier fehlt die Tranzparenz.
@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 :)
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.