Forum: Mikrocontroller und Digitale Elektronik MCP4921 Problem


von Marco G. (grmg2010)


Lesenswert?

Moin,

ich teste gerade den MCP4921. Um eine Rampe zu erzeugen, lasse ich einen 
Counter bis 4095 zählen und übergebe das Ergebnis dem Chip. 
Merkwürdigerweise habe ich große Sprünge in den Werten, manchmal um 1V 
nach oben oder kleinere (0,1V-0,2V nach unten). Auch würde ich erwarten, 
dass ich bei einem eingegeben Wert von 2047 ca. Vref/2 erreichen müsste. 
Ich bekomme aber bereits an der Stelle fast voll Vref (Vref = VCC = 5V).

Ich lasse mir die Werte des Counters auch anzeigen, um sie zu 
kontrollieren.
Hier mal mein Code:
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <stdlib.h>
4
#include "avr.h"
5
#include "mcp4921.h"
6
#include "UART.h"
7
#include "SPI.h"
8
9
char buffer1[15], buffer2[15], buffer3[15];
10
int counter = 0;
11
int counter_high = 0;
12
int test = 0;
13
14
int main(void)
15
{  
16
17
  avr_init();
18
  UART_Init();
19
  
20
    while(1)
21
    {
22
  
23
    counter++;
24
    counter_high = (counter >> 8);// | 0b00110000;
25
    test = counter_high | 0b00110000;
26
    
27
      MCP4921_setdata(test,counter);
28
    _delay_ms(50);
29
    
30
    
31
    if (counter >= 4095)
32
    {
33
      counter = 0;
34
    }
35
    
36
    itoa(counter_high, buffer1, 2);
37
    itoa(counter, buffer3, 2);
38
    itoa(test, buffer2,2);
39
    uart_puts("Input: ");
40
    Send_UART_Char(buffer3);
41
    uart_puts("counter_high: ");
42
    Send_UART_Char(buffer1);
43
    uart_puts("test: ");
44
    Send_UART_Char(buffer2);
45
    Send_UART_Char("    ");
46
    _delay_ms(100);
47
    }
48
}

Vielleicht fällt jemanden etwas an dem Code auf, was die Sprünge und die 
nicht zusammenpassenden Werte (Input -> Voltage)erklären könnten.

Gruß

von Günther V. (guvi)


Lesenswert?

Hallo Marco,

ich setze den MCP4921 / MCP4922 auch ein, ohne Probleme. Bin mir nicht 
sicher, ob das Problem am Code liegt, bin nur im Assembler tätig.
Markierst Du mit der Zeile

"counter_high = (counter >> 8);// | 0b00110000;"

das obere Halbbyte aus, um das Highbyte fix auf B'0011xxxx' zu setzen ?
Damit sendest Du dann gesamt 16 Bits '0011xxxx xxxxxxxx', wobei die 
12mal 'x'
der eigentliche 12Bit-Wert ist.

Müßte es vielleicht (counter >> 15) lauten ?

Wie gesagt, kenne die Syntax nicht wirklich.

Hier könnte das Problem liegen. Kannst Du die beiden Bytes, die Du via 
SPI zum MCP4921 schickts vorab nochmals ausgeben und kontrollieren ?

Außerdem fällt mir noch der Hardwarepin LDAC# ein, der sollte für Deinen 
Versuch dauerhaft auf GND sein, da sonst der Ausgang abgeschaltet wird.

Gruß, Günther

von Marco G. (grmg2010)


Lesenswert?

Hallo Günther,

nein mit der Zeile verschiebe ich alle Bits die größer als 2^8 sind um 
acht Stellen nach rechts, sodass sie wieder bei 2^0 starten. Das brauche 
ich, um die Daten zu übertragen.

Marco G. schrieb:
> test = counter_high | 0b00110000;

Mit dieser Zeile ver-oder dann das Ergebnis, sodass es immer wie folgt 
aussieht: 0b0011xxxx. Die x stellen dabei die ober vier Bit der zwölf 
Datenbits dar.

Die Zwischenwerte gebe ich auch aus, und die stimmen mit meiner 
Erwartung auch überein.

Der /LDAC Pin liegt bei mir auch dauerhaft auf GND, daran sollte es also 
nicht liegen.

von Michael L. (michaelx)


Lesenswert?

Hi Marco.

Wo ist denn der Code für die Funktion MCP4921_setdata? Ohne den kann man 
nicht wirklich sagen, was falsch läuft.

Aber ich wage man einen Schuss ins Blaue: Du hast Parameter von 
MCP4921_setdata vertauscht.

von Marco G. (grmg2010)


Lesenswert?

Die Funktion sollte richtig sein. Zumindest wenn ich den Wert einmal 
(vor der while schleife auf 2048 setze, bekomme ich ca. 2.5V als 
Ausgabe. Das stimmt also soweit. Trotzdem hier noch einmal der Code:
1
void MCP4921_setdata(int byte1, int byte2)
2
{
3
  SS_low();
4
  SPI_MasterTransit(byte1);
5
  SPI_MasterTransit(byte2);
6
  _delay_us(1);
7
  SS_high();
8
  //MCP4921_latchdata();
9
  
10
}

von Michael L. (michaelx)


Lesenswert?

Marco G. schrieb:
> Die Funktion sollte richtig sein. Zumindest wenn ich den Wert einmal
> (vor der while schleife auf 2048 setze, bekomme ich ca. 2.5V als
> Ausgabe. Das stimmt also soweit. Trotzdem hier noch einmal der Code:
>
1
> void MCP4921_setdata(int byte1, int byte2)
2
> {
3
>   SS_low();
4
>   SPI_MasterTransit(byte1);
5
>   SPI_MasterTransit(byte2);
6
>   _delay_us(1);
7
>   SS_high();
8
>   //MCP4921_latchdata();
9
> 
10
> }
11
>

Kann sein, dass ich total blind bin, aber ich glaube, dass ich mit 
meinem "Schuss ins Blaue" richtig lag.

von Marco G. (grmg2010)


Lesenswert?

Zum Test habe ich die gesendeten Bytes  mal umgedreht. Dann bekomme ich 
kein Ergebnis, ich denke meine Senderichtung stimmt schon. Ich lasse 
mich aber auch gerne etwas bessern belehren wenn noch irgendjemand Idee 
hat, oder eine Verbesserung des Codes weiß.

: Bearbeitet durch User
von Marco G. (grmg2010)


Lesenswert?

Meine Sendereihenfolge ist richtig, das Problem war die Zuordnung der 
Flanken bei der Datenübernahme. Der MCP4921 erwartet eine steigende 
Flanke, mein uC sendete mit fallender Flanke.
Jetzt funktioniert die Kommunikation mit dem Chip, das einzige "Problem" 
ist noch, dass der ausgegebene Wert immer um ca. 0,1V höher als der 
erwartete/errechnete Wert ist. Vermutlich liegt dies aber an dem Aufbau 
auf einem Steckbrett. Oder könnte das noch andere Gründe haben?

Gruß

von Michael L. (michaelx)


Lesenswert?

Marco G. schrieb:
> Meine Sendereihenfolge ist richtig,

Hm ja, ich war wohl zu sehr abgelenkt (Frau hat mich von der Seite 
zugetextet), als ich einen kurzen Blick ins Datasheet geworfen habe. Das 
MSB wird zuerst gesendet, und das LSB zuletzt.

Möglich wären noch Timing-Probleme. Nutzt du Hardware-SPI oder wird das 
Protokoll in Software emuliert? Davon unabhängig kannst du auch 
versuchen, den SPI-Takt reduzieren. Oder sende immer die gleichen Wert, 
und schaue ob die Spannung dann auch springt. Wenn Oszi vorhanden, dann 
SPI-Daten prüfen. (Trigger auf die fallende Flanke von /CS.)

Mehr fällt mir grad nich ein, hoffe, die Ideen bringen dich irgendwie 
weiter.

Grüße.

von Marco G. (grmg2010)


Lesenswert?

Ist doch nicht so schlimm ;)
Ich habe ja auch eine gewisse Zeit gebraucht um festzustellen, dass das 
Hauptproblem dabei die Flanken waren. Auf dem Scope sah alles gut aus, 
nur hat die Datenübernahme im Chip anders begonnen. da ich dort nicht 
reinsehen kann, ist mir das auch nicht aufgefallen.

Ich nutze "richtiges" hardware-Spi, mit der niedrigsten möglichen 
Frequenz (Fcpu/16 = 8MHz/16 = 500kHz).

Die springende Spannung hat sich durch eine Änderungen gegeben, wenn ch 
einen Zähler als Eingabewert nutze kann ich eine Rampe erzeugen, das 
einzige Problem ist im Moment ein Offset von 0,1V. Dieser erscheint mir 
etwas zu hoch.

von Michael L. (michaelx)


Lesenswert?

Na, dann weiter viel Erfolg. :-)

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.