Forum: Compiler & IDEs 24bit wert in 3 bytes aufteilen


von Oliver F. (ollif)


Lesenswert?

Hallo,

ich möchte einen LTC2756 18 Bit DAC über SPI an einem Atmega32 
ansteuern.

Initialisieren funktioniert Ausgabe von Werten mittels Byteweiser 
Übergabe
funktioniert auch (high mid Low)

Wenn ich die untenaufgeführte Funktion in einer Schleife von 0 bis 2^18 
-1 aufrufe geht alles gut bis zu dem Wert 65536.

Hier springt meine Spannung wieder auf 0.

Welchen Fehler mache ich hier?
1
uint16_t SPIWrite24(uint32_t Data)
2
{
3
4
  uint16_t b1=Data&0xff;
5
  uint16_t b2=(Data>>8)&0xff;
6
  uint16_t b3=(Data>>16)&0xff;
7
  uint16_t b4=(Data>>24)&0xff;
8
  
9
10
  SPDR = b2;              
11
  while(!(SPSR & (1<<SPIF)));          
12
  
13
  SPDR = b3;              
14
  while(!(SPSR & (1<<SPIF)));          
15
  
16
  SPDR = b4;              
17
  while(!(SPSR & (1<<SPIF)));        
18
19
  return SPDR;
20
}



Vielen Dank im Vorraus.


Gruß

Oliver

von Wolfgang (Gast)


Lesenswert?

Oliver F. schrieb:
> Wenn ich die untenaufgeführte Funktion in einer Schleife von 0 bis 2^18
> -1 aufrufe geht alles gut bis zu dem Wert 65536.

Und wie sehen Schleife und zugehörige Variablendeklarationen aus?

von lambda (Gast)


Lesenswert?

Wie sieht der Parameter aus, den du der Funktion übergibst? Aktuell 
sendest du nämlich nur 2. bis 4. Byte deines 32-Bit-Parameters und das 
auch in der vermutlich falschen Reihenfolge.
Dass der Chip noch einen Controllcode zusammen mit dem DAC-Wert möchte 
beachtest du in deiner Schleife?

Es würde übrigends reichen, für b1 bis b4 uint8_t zu nehmen, dann kannst 
du dir auch das &0xFF sparen um auf 8 Bit zu kürzen.

von Oliver F. (ollif)


Lesenswert?

HAllo

schon mal Danke,


hier ist ein weitere Code Auschnitt:

Ich durchalaufe hier die Tabelle von 0 -71 was bis zum wert 61860 auch 
funktionier dann fangt die Spannung wieder bei O an bei 131072 passiert 
das wieder.

Es muss irgendwie an der Konvertierung liegen
1
//Wertetabelle Steuerspannung
2
3
volatile uint32_t cvs[] = {  4096, 4340, 4598, 4871, 5161, 5468, 5793, 6138, 6502, 6889, 7299, 7733,
4
      8192, 8679, 9195, 9742, 10322, 10935, 11586, 12275, 13004, 13778, 14597, 15465,
5
      16384,17358, 18390, 19484, 20644, 21870, 23171, 24550, 26008, 27555, 29194, 30930,
6
      32768, 34715, 36779, 38968, 41288, 43739, 46341, 49100, 52016, 55110, 58387, 61860,
7
      65536, 69429, 73558, 77936, 82576, 87478, 92682, 98200, 104032, 110219, 116773, 123719,
8
      131072, 138858, 147116, 155871, 165151, 174955, 185363, 196399, 208064, 220437, 233545, 247438,
9
      262143};
10
11
12
//initialisierung DA
13
void DAC_init()
14
{
15
  //Span input register range set to unipolar 0V to Vref
16
  
17
  PORTB &= ~(1 << DD_SS);
18
  PORTB |= (1 << DD_SS);
19
  PORTB &= ~(1 << DD_SS);
20
  SPIWrite8(32);//command: 
21
  SPIWrite8(0);
22
  SPIWrite8(0); //span  0V to Vref
23
  SPIWrite8(0);
24
  
25
  PORTB &= ~(1 << DD_SS);
26
  PORTB |= (1 << DD_SS);
27
  PORTB &= ~(1 << DD_SS);
28
  
29
  //Code input Register code Set to mid scale (Vref/2)
30
  
31
  PORTB &= ~(1 << DD_SS);
32
  PORTB |= (1 << DD_SS);
33
  PORTB &= ~(1 << DD_SS);
34
  SPIWrite8(48);
35
  SPIWrite8(128);
36
  SPIWrite8(0);
37
  SPIWrite8(0);
38
  
39
  PORTB &= ~(1 << DD_SS);
40
  PORTB |= (1 << DD_SS);
41
  PORTB &= ~(1 << DD_SS);
42
  
43
  //update code and range
44
  
45
  PORTB &= ~(1 << DD_SS);
46
  PORTB |= (1 << DD_SS);
47
  PORTB &= ~(1 << DD_SS);
48
  SPIWrite8(64);
49
  SPIWrite24(0);
50
  
51
  PORTB &= ~(1 << DD_SS);
52
  PORTB |= (1 << DD_SS);
53
  PORTB &= ~(1 << DD_SS);
54
  
55
  //
56
}
57
58
59
void DACWrite(uint32_t data)
60
{
61
  //Write Data
62
  
63
  PORTB &= ~(1 << DD_SS);
64
  PORTB |= (1 << DD_SS);
65
  PORTB &= ~(1 << DD_SS);
66
  SPIWrite8(48);
67
  SPIWrite24(data);
68
  
69
  PORTB &= ~(1 << DD_SS);
70
  PORTB |= (1 << DD_SS);
71
  PORTB &= ~(1 << DD_SS);
72
  
73
  //update code and range
74
  
75
  PORTB &= ~(1 << DD_SS);
76
  PORTB |= (1 << DD_SS);
77
  PORTB &= ~(1 << DD_SS);
78
  SPIWrite8(64);
79
  SPIWrite24(0);
80
  
81
  PORTB &= ~(1 << DD_SS);
82
  PORTB |= (1 << DD_SS);
83
  PORTB &= ~(1 << DD_SS);
84
  
85
}
86
87
int main(void)
88
{
89
90
  SPI_init();
91
92
  DAC_init();
93
94
95
96
  // Durchläuft Steuerspannung für 72 Tasten 6 Oktaven
97
98
  for (int i = 0;i<72;i++)
99
  {
100
    DACWrite(cvs[i]);
101
    Lcd4_Clear();
102
    Lcd4_Set_Cursor(1,0);
103
    fprintf(stderr, "i =%d \n",i);
104
      
105
    Lcd4_Set_Cursor(2,0);
106
    fprintf(stderr, "i = %ld \n", cvs[i]);
107
      
108
    _delay_ms(500);
109
  }
110
111
112
113
}


Gruß

Danke

von lambda (Gast)


Lesenswert?

Also soweit ich das beim überfliegen sehe schreibst du erst den 
Steuercode 48 = 0011 0000 als 8 Bit Wert, soweit korrekt. Allerdings 
macht deine Funktion SPIWrite24() für mich wenig Sinn. Die sollte doch 
eigentlich den Parameter passend aufbereiten und dann raussenden?
Von den restlichen 24 Bit die nach dem Steuercode zu senden sind, sind 
die ersten 18 der Wert für den DAC und danach folgen noch 6 Bit 
Don't-care. Du sendest allerdings die niederwertigsten 8 Bit garnicht 
welche in b1 liegen. Danach folgt dann in der falschen Reihenfolge der 
Rest, das heißt die letzten 6 Bit von b4 werden vom DAC dann auch 
ignoriert.

Dass da überhaupt etwas sinnvolles rauskommt ist finde ich echt 
erstaunlich. Ich würde dir empfehlen erstmal den Code dahingehend zu 
bearbeiten, dass der Wert korrekt rausgesendet wird, vermutlich erledigt 
sich dadurch dann auch das von dir beobachtete Fehlverhalten.

Nachdem deine Eingangswerte maximal 18 Bit haben würde ich in der 
Funktion SPIWrite24() die Daten erstmal um 6 nach links shiften und dann 
die unteren 3 Byte beginnend mit dem höchstwertigsten versenden.

Also sowas wie
Data = Data << 6;
 while(!(SPSR & (1<<SPIF)));
SPDR = (Data >> 16);
 while(!(SPSR & (1<<SPIF)));
SPDR = (Data >> 8);
 while(!(SPSR & (1<<SPIF)));
SPDR = Data&0xFF;

von Wolfgang (Gast)


Lesenswert?

Oliver F. schrieb:
> Es muss irgendwie an der Konvertierung liegen

Tut es wohl auch.

Deine Konstanten sollten vom Datentyp unsigned /long/ sein, also z.B. 
165151UL

von Oliver F. (ollif)


Lesenswert?

Hallo Lambda,

Das war es!

Jetzt klappt es.

Vielen Dank jetzt kann ich weiter an meinem Synthesizer werkeln.


Gruß

Oliver

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.