Forum: Mikrocontroller und Digitale Elektronik SPI 16 bits zu 11bits


von Alexander S. (alex130)


Lesenswert?

Ich hoffe ich bekomme keine krititk da ich extra dafür ein neues Thread 
eröffne aber ich komme da nicht weiter und denke mir es würde anderen 
auch helfen. Also ich versuche mein Problem oder meine Wissenlücke mal 
zu schildern:
ich versuche einen TLC7620 anzusprechen das ist ein 8 bit DAC aber man 
muss 11 bit übertragen (3 bit für Parameter) von einem ATMEGA 8 in C 
habe spi soweit verstanden aber komme da einfach nicht weiter? Vielen 
dank im voraus für konstruktive vorschläge.

von Ziff (Gast)


Lesenswert?

Das Schluesselwort heisst Soft SPI. Ist nicht weiter schwierig, man muss 
die Pin per Software anteuern. Gemaess Datenblatt.

von Alexander S. (alex130)


Lesenswert?

Gibts da vielleicht ein Beispiel in C will nicht copy und past machen 
aber zum verstehen würde es mir helfen? Weil auf die Idee bin ich auch 
schon gekommen aber nicht so richtig was gefunden und wenn war es nicht 
grade so nach vollziebar.

von Alexander S. (alex130)


Lesenswert?

Habe schon mal sowas versucht aber habe auch andere gefragt aber die 
sagten versuchs besser mit der SPI Schnittstelle von ATmega8 Hier der 
Code oder verstehe ich da was falsch?

#include <avr/io.h>
#include <util/delay.h>

#define DAC_PORT PORTC
#define DAC_LOAD 1
#define DAC_CLOCK 0
#define schiebeum 5

void dac_data(unsigned char temp1);
void dac_enable(void);

void dac_data(unsigned char temp1)
{

   unsigned char a1dac=0x00;
   a1dac = a1dac & 0x04;
   unsigned char a0dac=0x00;
   a0dac = a0dac & 0x04;
   unsigned char rngdac=0x00;
   rngdac = rngdac & 0x04;

   unsigned char d7dac=temp1<<2;
   d7dac = d7dac & 0x04;
   unsigned char d6dac=temp1<<1;
   d6dac = d6dac & 0x04;
   unsigned char d5dac=temp1;
   d5dac = d5dac & 0x04;
   unsigned char d4dac=temp1>>1;
   d4dac = d4dac & 0x04;
   unsigned char d3dac=temp1>>2;
   d3dac = d3dac & 0x04;
   unsigned char d2dac=temp1>>3;
   d2dac = d2dac & 0x04;
   unsigned char d1dac=temp1>>4;
   d1dac = d1dac & 0x04;
   unsigned char d0dac=temp1>>5;
   d0dac = d0dac & 0x04;

DAC_PORT |= (1<<DAC_LOAD);


//a1
   DAC_PORT &= 0x04;
   DAC_PORT |= a1dac;
   dac_enable();

//a0
   DAC_PORT &= 0x04;
   DAC_PORT |= a0dac;
   dac_enable();

//rng
   DAC_PORT &= 0x04;
   DAC_PORT |= rngdac;
   dac_enable();


//d7
   DAC_PORT &= 0x04;
   DAC_PORT |= d7dac;
   dac_enable();

//d6
   DAC_PORT &= 0x04;
   DAC_PORT |= d6dac;
   dac_enable();

//d5
   DAC_PORT &= 0x04;
   DAC_PORT |= d5dac;
   dac_enable();

//d4
   DAC_PORT &= 0x04;
   DAC_PORT |= d4dac;
   dac_enable();

//d3
   DAC_PORT &= 0x04;
   DAC_PORT |= d3dac;
   dac_enable();


//d2
   DAC_PORT &= 0x04;
   DAC_PORT |= d2dac;
   dac_enable();

//d1
   DAC_PORT &= 0x04;
   DAC_PORT |= d1dac;
   dac_enable();

//d0
   DAC_PORT &= 0x04;
   DAC_PORT |= d0dac;
   dac_enable();

//DAC_PORT &= (1<<DAC_LOAD);

}


void dac_enable(void)
{
   DAC_PORT |= 0x01;
    _delay_us(150);  // nicht zu knapp warten, sonst drohen
Kompatbilitätsprobleme!
   DAC_PORT &= ~0x01;
}




int main(void)
{

DDRC=0x07;
PORTC=0x00;
dac_data(1);


while (1)
{


}

  return 0;
}

danke für jede hilfe!

von Ziff (Gast)


Lesenswert?

CS=0;
for (i=0;i<11;i++){
 if ((Data && 0x01)==0x01) { DO=1; } else (DO=0;}
 SCLK=1;
 data >>= 1;
 {
CS=0;

So etwa. Kommt nun drauf an, of MSB first, oder LSB first.

von Ziff (Gast)


Lesenswert?

Hab was vergessen :

CS=0;
for (i=0;i<11;i++){
 if ((Data && 0x01)==0x01) { DO=1; } else (DO=0;}
 SCLK=1;
 data >>= 1;
 SCLK=0;
 {
CS=0;

von Ziff (Gast)


Lesenswert?

CS an Schluss wieder hoch : CS=1;

von Alexander S. (alex130)


Lesenswert?

Scheinst ja eine menge darüber zu wissen danke erst mal.
Die Pins wären da ja frei wähl paar so weit ich das verstehe CS wäre das 
Load bit data wäre für die Daten SCKL für die Clock. aber wie mache ich 
das mit dem Clock signal dies ist laut datenblatt bei 1 MHZ für den DAC 
tue ich da mit delay arbeiten da der Atmega8 an einen 3686000 MHZ quarz 
angeschlossen ist?

Aber nochmal kurz zum Hardware SPI ne andere Idee wenn ich nun 16 bit 
zum DAC schicke und nach 16 bits haufhöre schreibt der da die 5 bit am 
anfang wieder rein oder bei einem solchen fall da verhalten undefiniert?

von Simon K. (simon) Benutzerseite


Lesenswert?

Übrigens: Nur weil der Wandler 11Bits erwartet, heißt das nicht 
unbedingt, dass man exakt 11 Bits senden muss. Das ist ein Trugschluss!

Stell dir vor du hast ein 11-Bittiges Schieberegister und schiebst 
16Bits herein. Na, welche Bits liegen jetzt an den Ausgängen?

Meistens* läuft es so, dass die 11 letzten Bits, die du hineingeschoben 
hast bei einer fallenden/steigenden Flanke von CS die für das 
On-Chip-Processing relevanten Daten sind.
Sprich: Die Bits, die du zuerst hineingeschoben hast, sind schon wieder 
"herausgefallen".

*Ich weiß nicht, ob das bei deinem Baustein auch der Fall ist, aber ich 
könnte es mir sehr gut vorstellen.

PS: Sieh es erstmal andersherum: Wie sollte der Chip reagieren, wenn du 
mehr Bits vor dem CS hineinschiebst? In Rauch aufgehen? Wohl kaum.

von Alexander S. (alex130)


Lesenswert?

Das habe ich ausprobiert aber die reaktion war nahe null wenn ich 16 
bits reingeschoben habe mit ensprechender +5 Bitverschiebung.
Siehe Code Master_Transmit

#include <avr/io.h>
#include <stdint.h>
#define DD_MOSI PB3
#define DD_SCK  PB5
#define DD_LOAD PB0

void SPI_MasterInit(void)
{

/* Set MOSI and SCK output, all others input */
DDRB = (1<<DD_MOSI)|(1<<DD_SCK);
/* Enable SPI, Master, set clock rate fck/64 */
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR1);
}



void SPI_MasterTransmit(char cData)
{

/* Start transmission */
SPDR = 15;
/* Wait for transmission complete */
while(!(SPSR & (1<<SPIF)))
;

/* Start transmission */
SPDR = cData;
/* Wait for transmission complete */
while(!(SPSR & (1<<SPIF)))
;



}

int main(void)
{
SPI_MasterInit();
SPI_MasterTransmit(200);
   for(;;)
        ;
   return 0;
}

PS.: will hier keinen verärgern mit zuviel dummen fragen hoffe ihr nehmt 
mir das nich übel. Danke für jede hilfe

von Ziff (Gast)


Lesenswert?

Wenn der DAC 1MBit als maximum vorsieht, kann das SPI auch langsamer 
sein. Der genannte Code wird 1MBit kaum ueberbieten, Im Loop 
wohlgemerkt.

von Alexander S. (alex130)


Lesenswert?

Wenn ich nochmal vom Hardware SPI ausgehe und noch mal von vorne anfange 
habe mir auf seite 3 unten die Zeichnung genommen und das versucht 
nachzubauen.
Habe folgendes verbunden:

- 5 Volt spannungsquelle angeschlossen an vdd und gnd ist ein extra 
Spannungswandler mit verbindung mu mit gnd

- ref angeschlossen Spannungsquelle

- Data mit Mosi verbunden von mc

- CLK mit SCK verbunden von mc

- LOAD mit PIN2 verbunden von mc (ist im Quelltext nicht berücksichtigt 
habe aber dies auch mit bedacht in anderen Quelltext den ich jetzt nicht 
zur hand habe da auf Arbeit)

Liegt vielleicht dort der Fehler hier das Datenblatt dazu.

http://www.datasheetcatalog.com/datasheets_pdf/T/L/C/5/TLC5620.shtml

danke für jede Hilfe

von Jörg X. (Gast)


Lesenswert?

Ich lese das Datasheet so, dass du da einfach zwei Bytes reinschieben 
kannst, MSB zuerst:
1
void dac_put_data(uint8_t channel, uint8_t data)
2
{
3
  spi_put_byte(channel<<1);
4
  spi_put_byte(data);
5
  CLR_LOAD();
6
  _delay_us(0.3); /* min. 250ns warten, 
7
    klappt so aber nur MIT aktivierter Optimierung */
8
  SET_LOAD();
9
}
Und LDAC einfach (erst mal) auf low lassen. Und das SPI auf "Mode 1" (s. 
AVR-Datenblatt) initialiseren.

hth. Jörg

von Alexander S. (alex130)


Lesenswert?

Danke für deine Funktion sieht sehr interresant aus ich nehme die jetzt 
mal auseinander:

mit dac_channel meinst du einen der 4 Ausgänge des DAC
Frage 1.
Schiebe ich durch "spi_put_byte(channel<<1); " nur eine bestimmte anzahl 
von Bits aus der Channel Variablen raus also in dem vom DAC nur 3 Bits?

Frage 2.
"spi_put_byte(data);" ist der Parameterwert für den Ausgang des Kanals
oder?

Frage 3.
CLR_LOAD() setzte ich das Load bit auf 0 warte 0,3 us und setzte es dann 
wieder mit SET_LOAD(); aber im Datenblatt steht doch das während der 
übertragung der Load auf High sein soll und danach erst wieder auf Low?

Frage 4.
das ganze ist jetzt Hardware SPI oder?


Sorry meine Fragen aber versuche es zu verstehen und nicht einfach zu 
kopieren. Danke für deine Hilfe
mfg Alex

von Jörg X. (Gast)


Angehängte Dateien:

Lesenswert?

> spi_put_byte(channel<<1);
bedeutet dass die Nummer des DAC-Ausgange gesendet wird, aber nicht so:
> 0b 0 0 0 0 0 0 n n
sondern so
> 0b 0 0 0 0 0 n n 0
also einer (2er-)Stelle verschoben, weil das LSB ("Least Sigificant 
Byte") eine andere Bedeutung hat ("RNG"), damit man "Kanal 0" bis Kanal 
3 schreiben kann, z.B. für Arrays ;)

Ich häng dir mal an, was ich inzwischen zusammengetippt hab -> du musst 
aber auf jeden Fall die #defines in der .h-Datei überprüfen/ausfüllen

hth. Jörg

von Simon K. (simon) Benutzerseite


Lesenswert?

Alexander Schreiber wrote:
> Das habe ich ausprobiert aber die reaktion war nahe null wenn ich 16
> bits reingeschoben habe mit ensprechender +5 Bitverschiebung.

Ja, das würde mich nicht wundern:
1
 #include <avr/io.h>
2
 #include <stdint.h>
3
 #define DD_MOSI PB3
4
 #define DD_SCK  PB5
5
 #define DD_LOAD PB0
6
 
7
 void SPI_MasterInit(void)
8
 {
9
 
10
 /* Set MOSI and SCK output, all others input */
11
 DDRB = (1<<DD_MOSI)|(1<<DD_SCK);
12
 /* Enable SPI, Master, set clock rate fck/64 */
13
 SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR1);
14
 }
15
 
16
 
17
 
18
 void SPI_MasterTransmit(char cData)
19
 {
20
 
21
 /* Start transmission */
22
 SPDR = 15;
23
 /* Wait for transmission complete */
24
 while(!(SPSR & (1<<SPIF)))
25
 ;
26
 
27
 /* Start transmission */
28
 SPDR = cData;
29
 /* Wait for transmission complete */
30
 while(!(SPSR & (1<<SPIF)))
31
 ;
32
 
33
 
34
 
35
 }
36
 
37
 int main(void)
38
 {
39
 SPI_MasterInit();
40
 SPI_MasterTransmit(200);
41
    for(;;)
42
         ;
43
    return 0;
44
 }

Du musst im Master-Mode den /SS-Pin als Ausgang setzen. Außerdem hast du 
(vermute ich?) vergessen den LOAD-Ausgang als Ausgang zu setzen. Den 
Rest habe ich garnicht erst überprüft.
Btw, du steuerst den LOAD-Ausgang ja auch garnicht an!

von Alexander S. (alex130)


Lesenswert?

zu Simon Küppers:
will nicht fresch sein aber muss mal sagen richtig lesen aber trotzdem 
danke ich überlese auch manchmal sachen!

Autor: Alexander Schreiber (alex130)
Datum: 24.09.2007 13:50
- LOAD mit PIN2 verbunden von mc (ist im Quelltext nicht berücksichtigt
habe aber dies auch mit bedacht in anderen Quelltext den ich jetzt nicht
zur hand habe da auf Arbeit)

Mal eine zwichenfrage kommt von jemanden der mir geantwortet hat zu 
fällig jemand aus dresden?
PS danke  Jörg X. für deine mühe und deine Geduld bisher

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.