Problem mit USCRnC Register

Gast #4322079
Lesenswert?

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?
#4322102
Lesenswert?

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.
Gast #4322450
Lesenswert?

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...
Gast #4322463
Lesenswert?

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
Gast #4322465
Lesenswert?

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
#4323035
Lesenswert?

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.
Gast #4327206
Lesenswert?

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?
Gast #4327235
Lesenswert?

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
Gast #4327251
Lesenswert?

>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.
Gast #4327277
Lesenswert?

>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.
Gast #4328573
Lesenswert?

>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.
Gast #4328606
Lesenswert?

>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;)
Gast #4328682
Lesenswert?

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
Gast #4329100
Lesenswert?

>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!
Gast #4329105
Lesenswert?

...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.
Gast #4329107
Lesenswert?

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

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