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.
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
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.
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
unsignedcharUSART_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!
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