Hallo Zusammen, ich versuche bei einem Atmega168PA den USART im Master SPI Mode zu nutzen. Nach Datenblatt muss man zur Konfiguration das Register UCSR0C verwenden. Um die Data Order, die Clock Phase und die Clock Polarity einzustellen muss man in diesem Register die Bits 0, 1 und 2 setzten (UDORD0, UCPHA0 und UCPOL0). Laut Datenblatt sind Bits 3, 4 und 5 ohne Funktion. Bit 6 und 7 ist UMSEL00 und UMSEL01 um den USART in den Master SPI Mode zu bringen. Die iom168pa.h sagt zu diesem Register ab folgendes: #define UCSR0C _SFR_MEM8(0xC2) #define UCPOL0 0 #define UCSZ00 1 #define UCSZ01 2 #define USBS0 3 #define UPM00 4 #define UPM01 5 #define UMSEL00 6 #define UMSEL01 7 Das aktuelle Datenblatt (http://www.atmel.com/devices/ATMEGA168PA.aspx) sagt also was anderes, als die aktuelle iom168pa.h (AVR Studio 7). Was ist hier los? Wie soll ich denn nun UCPHA und UDORD0 einstellen?
Die Defines, die in deiner Beschreibung stehen, gehören zum USART im seriellen Modus. Suche doch in der h-Datei mal nach UDORD und UCPHA. ich wette, die sind auch da. Nachtrag: scheinbar doch nicht :-(. Du kannst diese entweder in deinem Programm ergänzen oder statt z. B. UDORD das UCSZ01 nutzen.
:
Bearbeitet durch User
Die Bits sind identisch. Wenn man im Datenblatt nach UCSZ01 sucht, findet man ganz am Ende UDORD als alternative Bezeichnung. Blöd gemacht...
Kann das sein, dass beim ATmega die "Baud rate" im Datenblatt nicht wie angebene 1 bit / sekunde, sondern 2 byte / sekunde ist? Ich habe eine LED am MOSI und SCK Ausgang und mein interner OSC ist 128 kHZ. Ich schaffe es bei einer Baudrate von 1 aber nicht, das die LED für jedes Bit eine Sekunde an ist, sondern sie blinkt viel schneller. Es sieht aus als würden alle 16 bit in einer Sekunde geschickt...
Baudrate ist bit / sekunde. Einstellbar mit einem 16 bit register namens UBRR0. Wenn ich da bei 128 kHZ eine 63999 reinschreibe, müsste mit 1 bit /s übertragen werden. Jetzt habe ich gerade gesehen: Der Maximalwert ist 4095 laut Datenblatt. Also ist meine Datenrate 15,6 bit /s und alles stimmt. So langsam kann der uC nicht :D :D
Hi >Kann das sein, dass beim ATmega die "Baud rate" im Datenblatt nicht wie >angebene 1 bit / sekunde, sondern 2 byte / sekunde ist? Nein. >Ich schaffe es bei einer Baudrate von 1 aber nicht, das die LED für >jedes Bit eine Sekunde an ist, sondern sie blinkt viel schneller. Wie hast du das berechnet? MfG Spess
Wieso ist der TXD des USART eigentlich wenn keine Daten gesendet werden auf HIGH? Kann man das Umstellen oder ist das eigentlich egal?
Hi >Wieso ist der TXD des USART eigentlich wenn keine Daten gesendet werden >auf HIGH? Meinst du USART- oder SPI-Mode? MfG Spess
Im USART-Mode ist es so (gewesen), damit der Empfänger erkennen kann, dass da wer auf der anderen Seite hängt. Im SPI-Modus sollte das nur so sein, wenn der Chipselect auf low liegt und du den Mastermode nutzt.
:
Bearbeitet durch User
Ich bin im SPI Modus, aber der USART hat garkeine Chipselect. Datenblatt: SS Not supported by USART in MSPIM Aber mein TXD ist auf HIGH wenn der Sendebuffer leer ist.
Ah, da nur der Master-SPI-Mode unterstützt wird, gibt es natürlich keinen ChipSelect. Damit ist das normal, da MOSI (Master Out Slave In) nicht abgeschaltet werden muss. Die Slaves müssen ihren MISO (Master In Slave Out) abschalten, wenn diese nicht angewählt sind, um gegeneinander Treiben der Slaveausgänge zu vermeiden.
Ich habe den ATmega168PA auf 128kHz/8= 16 kHz (interner Teiler) laufen. Ich kann also in Ruhe den Bits zuschauen (per LED). Aus dem Datenblatt habe ich diesen Code genommen und bearbeitet:
1 | unsigned char USART_Receive( void ) |
2 | {
|
3 | nSEL_LOW(); |
4 | |
5 | /* Wait for empty transmit buffer */
|
6 | while ( !( UCSR0A & (1<<UDRE0)) ); |
7 | /* Put data into buffer, sends the data */
|
8 | UDRn = data; |
9 | /* Wait for empty transmit buffer */
|
10 | while ( !( UCSR0A & (1<<UDRE0)) ); |
11 | |
12 | nSEL_HIGH(); |
13 | }
|
An nSEL hängt eine LED, die nicht ausgeht, obwohl die Daten noch gesendet werden. Das bedeutet, dass UDRE0 niemals 0 wird, obwohl im Datenblatt steht • Bit 5 – UDREn: USART Data Register Empty The UDREn Flag indicates if the transmit buffer (UDRn) is ready to receive new data. If UDREn is one, the buffer is empty, and therefore ready to be written. The UDREn Flag can generate a Data Register Empty interrupt (see description of the UDRIE bit). UDREn is set after a reset to indicate that the Transmitter is ready. Wieso wird UDRE0 nicht 0, obwohl die Daten noch gesendet werden?
Hi >Wieso wird UDRE0 nicht 0, obwohl die Daten noch gesendet werden? Ersetze doch mal das unsinnige zweite >while ( !( UCSR0A & (1<<UDRE0)) ); durch while ( !(UCSR0A & (1<<RXC0)) ); aus dem Datenblatt. MfG Spess
>Ersetze doch mal das unsinnige zweite >while ( !( UCSR0A & (1<<UDRE0)) ); >durch >while ( !(UCSR0A & (1<<RXC0)) ); >aus dem Datenblatt. Mein Receiver ist ausgeschaltet. Ich will lediglich wissen, wann der TX buffer leer ist. Und da finde ich das garnicht so unsinnig.
>Ich will lediglich wissen, wann der TX buffer leer ist. Und da finde ich >das garnicht so unsinnig. Bei SPI über USART hat der TX Buffer zwei Bytes. Wenn du nur eins schreibst ist UDRE0 sofort wieder bereit Daten aufzunehmen. D.h. du ziehst die CS Leitung schon hoch bevor fertig gesendet wurde. Deswegen warten ob ein Byte empfangen wurde. Denn dann ist das senden sicher beendet.
>Bei SPI über USART hat der TX Buffer zwei Bytes.
Laut Datenblatt Seite 191 stimmt das nicht. Der Buffer hat nur 1 Byte.
Außerdem habe ich schon 2 Byte reingeschrieben, und er sendet nur das 1.
Byte.
>Laut Datenblatt Seite 191 stimmt das nicht. Der Buffer hat nur 1 Byte. The USART in MSPIM mode includes (double) buffering of the transmitter. Das steht bei mir im Datenblatt. >Außerdem habe ich schon 2 Byte reingeschrieben, und er sendet nur das 1. >Byte. Wer weiß was du da schon wieder falsch gemacht hast;)
Hi
>Laut Datenblatt Seite 191 stimmt das nicht. Der Buffer hat nur 1 Byte.
Ein Byte im Schieberegister und ein Byte im Puffer. Macht 2 Byte. Der
Receiver hat incl. Schieberegister drei Byte.
MfG Spess
>Außerdem habe ich schon 2 Byte reingeschrieben, und er sendet nur das 1. >Byte.
1 | UDR0 = 0b0000000010101010; |
Das Schreiben von 16 Bit in UDR0 führt bei mir dazu, dass die LED (die ja sonst dauer an ist) 4 Mal an und aus geht (10101010). Es wird nur das niedrigere Byte gesendet?! >Wer weiß was du da schon wieder falsch gemacht hast;) Sag du es mir!
...weil ich es so machen muss:
1 | UDR0 = ((data & 0b1111111100000000)>>8); |
2 | UDR0 = (data & 0b0000000011111111); |
Jetzt klappt es und jetzt klappt auch
1 | /* Wait for empty transmit buffer */
|
2 | while ( !(UCSR0A & (1<<UDRE0)) ); |
Wobei ich sagen muss, dass ich nicht so ganz verstehe, wie innerhalb von einem Takt plötzlich das UDR0 Register (was ja definitiv nur 8 bit hat) wieder leer ist und ich die nächsten 8 bit reinschreiben kann.
Hi >Sag du es mir! >UDR0 = 0b0000000010101010; UDR0 ist 8 Bit breit. Also kannst du mit einer Zuweisung nur 8 Bit übergeben. Der Rest verschwindet im Nirwana. Also mit UDR0 = 0b10101010; ... UDR0 = 0b00000000; sendest du zwei Byte. MfG Spess
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.