Forum: Mikrocontroller und Digitale Elektronik Uart als Spi macht Probleme


von etler (Gast)


Lesenswert?

Hallo,

ich möchte meine Uart1 Schnittstelle von meinem Atmega324p als Spi 
Schnittstelle laufen lassen (nur senden). Allerdings funktioniert das 
nicht (kein Clock-Signal). Ich finde allerdings keinen Fehler im Code, 
könnt ihr mal einen Blick drüber werfen.

Vielen Dank

An PD4 soll mein Clock-Signal erscheinen
1
void SPI_USART_Init()
2
{
3
  UBRR1 = 0;
4
  /* Setting the XCKn port pin as output, enables master mode. */
5
  
6
  DDRD |= (1 << PD4);
7
  //XCK1_DDR |= (1<<XCK1);
8
  /* Set MSPI mode of operation and SPI data mode 0. */
9
  UCSR1C = (1<<UMSEL11)|(1<<UMSEL10)|(0<<UCPHA1)|(0<<UCPOL1);
10
  /* Enable receiver and transmitter. */
11
  UCSR1B = (1<<RXEN1)|(1<<TXEN1);
12
  /* Set baud rate. */
13
  /* IMPORTANT: The Baud Rate must be set after the transmitter is enabled
14
  */
15
  UBRR1 = 10;
16
}
17
18
19
unsigned char SPI_Transfer (unsigned char c)
20
{
21
  while (!(UCSR1A & (1<<UDRE1)));
22
23
  UDR1 = c;
24
  
25
  while (!(UCSR1A & (1<<RXC1)));
26
  
27
  return UDR1;
28
}

Der Aufruf
1
SPI_USART_Init();
2
.
3
.
4
.
5
ReData = SPI_Transfer("110");

von Bastler07 (Gast)


Lesenswert?

keine hinweise?
ich brauch spi um einen ic seriell mit daten zu versorgen...
alternavtive Tipps?

von Naja (Gast)


Lesenswert?

unsigned char c und "110", wie passt das zusammen ?!

von Bastler07 (Gast)


Lesenswert?

Guter Einwand,
jetzt wo du es sagst, habe einfach gedacht
unsig. char hat 8 bit, also 0-255

aber dann will er das doch sicher als ascii, also wäre meine 110 ein n

aber rechnet er das überhaupt um


Ich will nur die Möglichkeit haben eine 10bit Zahl an den IC über SPI zu 
schicken, was übergebe ich dann als char?

von holger (Gast)


Lesenswert?

>aber dann will er das doch sicher als ascii, also wäre meine 110 ein n

SPI kennt kein ASCII.

>aber rechnet er das überhaupt um

Nein. Du sendest so nur Müll.

>Ich will nur die Möglichkeit haben eine 10bit Zahl an den IC über SPI zu
>schicken, was übergebe ich dann als char?

Da 10 bit nicht in ein char passen geht es so nicht.

von Thomas (Gast)


Lesenswert?

Moin,

welcher IC hängt den an dem SPI ? Wahrscheinlich ein DAC oder so. 10Bit 
kannst Du nicht direkt übertragen, als ASCII schon garnicht. Du mußt das 
auf zwei Übertragungen aufteilen. Das wie hängt wiederum vom angehängten 
IC ab.

Die Angabe "110" beschreibt eher einen String, sollte auch eine 
Fehlermeldung beim Compiler geben. Der Aufruf sollte eher so aussehen

ReData = SPI_Transfer(110);

   oder

ReData = SPI_Transfer(0xD0);


Bye

von J.-u. G. (juwe)


Lesenswert?

Im Datenbaltt des 324p steht (Kapitel USART in SPI Mode):

>The TXCn Flag can be used to check that the Transmitter has completed all 
>transfers, and the RXCn Flag can be used to check that there are no unread
>data in the receive buffer. Note that the TXCn Flag must be cleared before
>each transmission (before UDRn is written) if it is used for this purpose.

demzufolge solltes Du
1
UCSR1A |= (1 << TXC1);
vor
1
UDR1 = c;
einfügen.

von etler (Gast)


Lesenswert?

Danke erstmal, ich habe die Tipps eingebaut

schon richtig, ich möchte einen DA ansteuern. Nun kommt auch ein Signal 
am Clockeingang, allerdings gibt er mir eine falsche 
Eins-Null-Kombination am seriellen Dateneingang des DAs. Es handelt sich 
dabei um genau das gleiche Signal wie das vom Clock.

Woran liegt das?


der neue Code:
1
void SPI_USART_Init()
2
{
3
  UBRR1 = 0;
4
  /* Setting the XCKn port pin as output, enables master mode. */
5
  
6
  DDRD |= (1 << PD4);
7
  //XCK1_DDR |= (1<<XCK1);
8
  /* Set MSPI mode of operation and SPI data mode 0. */
9
  UCSR1C = (1<<UMSEL11)|(1<<UMSEL10)|(0<<UCPHA1)|(0<<UCPOL1);
10
  /* Enable receiver and transmitter. */
11
  UCSR1B = (1<<RXEN1)|(1<<TXEN1);
12
  /* Set baud rate. */
13
  /* IMPORTANT: The Baud Rate must be set after the transmitter is enabled
14
  */
15
  UBRR1 = 6;
16
}
17
18
19
unsigned char SPI2_MasterTransfer (unsigned char c)
20
{
21
  while (!(UCSR1A & (1<<UDRE1)));
22
  
23
  UCSR1A |= (1 << TXC1);
24
25
  UDR1 = c;
26
  
27
  //while (!(UCSR1A & (1<<RXC1)));  
28
29
  return UDR1;
30
}
31
32
33
//Der Aufruf
34
35
SPI_USART_Init();
36
.
37
.
38
.
39
ReData = SPI_Transfer(110);

von spess53 (Gast)


Lesenswert?

Hi

>allerdings gibt er mir eine falsche
>Eins-Null-Kombination am seriellen Dateneingang des DAs.

Vielleicht verlangt der DAC einen andern SPI-Mode? Vergleiche mal das 
Timing deines DACs mit den SPI-Modes im Datenblatt vom AVR.

MfG Spess

von etler (Gast)


Lesenswert?

danke, es muss (1<<UCPHA1) sein

wobei das ja eigentlich nicht dafür entscheidend ist, dass der AVR mir 
schon die falsche Kombination ausgibt

von spess53 (Gast)


Lesenswert?

Hi

Was meinst du mit 'falsche Kombination'?

MfG Spess

von etler (Gast)


Lesenswert?

ich habe mich übrigens oben verschrieben...
Der DA-Chip braucht 16bit an seriellen Daten

dazu rufe ich einfach meinen 8bit Befehl doppelt auf
1
ReData = SPI_Transfer(110);
2
ReData = SPI_Transfer(110);

nun ist eine 110 binär ja eine 1101110, also sollten meine seriellen 
Daten ja 11011101101110 (2mal 110 binär) sein.

Allerdings bekomme ich als seriellen Datenstrom
101010101010101

und das ist genau das gleiche, wie das Signal vom Clock

von ZiZi (Gast)


Lesenswert?

>dazu rufe ich einfach meinen 8bit Befehl doppelt auf

Und was passiert mit dem SPI CS zwischen den beiden Aufrufen?
2  8 bits muss nicht unbedingt gleich 1  16 sein...
Ausserdem muss dann das Byte-Ordering beachtet werden.
Schau mal, ob Dein Controller nicht die SPI Wortlaenge
umschalten kann (kenne den AVR nicht genau genug).

(hat allerdings nicht direkt mit Deinem Clock-Problem zu tun,
aber vielleicht mit dem, das Du als nächstes haben wirst...;-))

ZiZi.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

etler schrieb:
> nun ist eine 110 binär ja eine 1101110,
Das stimmt eigentlich schon noch...
> sollten meine seriellen Daten ja 11011101101110 (2mal 110 binär) sein.
Aber das nicht mehr. Denn du überträgst 8 Bits. Damit werden für 110 die 
Bits
01101110 übertragen. Und damit für 110, 110 die Bits 0110111001101110. 
Merkst du was? Nein?
Ich schreibe unsere Zahlen mal untereinander:
1101110  -- deine 110
01101110 -- meine 110
und damit auch:
11011101101110    -- deine 110, 110
0110111001101110  -- und meine...

etler schrieb:
> Der DA-Chip braucht 16bit an seriellen Daten
> dazu rufe ich einfach meinen 8bit Befehl doppelt auf
Und: passt das zum Datenblatt?

etler schrieb:
> schon richtig, ich möchte einen DA ansteuern.
Arg geheim, welcher das ist...   :-/

von etler (Gast)


Lesenswert?

ZiZi schrieb:
> Und was passiert mit dem SPI CS zwischen den beiden Aufrufen?
> 2  8 bits muss nicht unbedingt gleich 1  16 sein...
> Ausserdem muss dann das Byte-Ordering beachtet werden.
> Schau mal, ob Dein Controller nicht die SPI Wortlaenge
> umschalten kann (kenne den AVR nicht genau genug).

Stimmt, dazu habe ich im Datenblatt folgendes gefunden.
"16-bit data transfer can be achieved by writing two data bytes to UDRn. 
A UART transmit complete
interrupt will then signal that the 16-bit value has been shifted out."

also kann ich meine 16bit in meiner Transfer-Funktion nacheinander in 
UDR1 schreiben
1
unsigned char SPI2_MasterTransfer (unsigned char c1,unsigned char c2)
2
{
3
  while (!(UCSR1A & (1<<UDRE1)));
4
  
5
  UCSR1A |= (1 << TXC1);
6
7
  UDR1 = c1;
8
  UDR1 = c2;
9
  
10
  //while (!(UCSR1A & (1<<RXC1)));  
11
12
  return UDR1;
13
}
14
15
//Aufruf
16
ReData = SPI_Transfer(110,110);


Lothar Miller schrieb:
> und damit auch:
> 11011101101110    -- deine 110, 110
> 0110111001101110  -- und meine...
Natürlich, beim kopieren aus dem Rechner ist die erste 0 verloren 
gegangen.

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
Noch kein Account? Hier anmelden.