SPI 16 bits zu 11bits

OP #661208
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.
OP #661244
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!
OP #661258
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?
Persönliche Seite #661271
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.
OP #661293
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
OP #661306
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
Gast #661378
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
OP #661413
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
Gast #661422
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
Angehängte Dateien:
Persönliche Seite #661467
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!
OP #661612
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

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