Forum: Compiler & IDEs Problem mit AD7945BN DAC Ansteuerung


von Patrick B. (p51d)


Lesenswert?

Hallo miteinander.

Ich versuche seit neustem einen DAC von einem MCU aus anzusteuern. Das 
ganze sollte später zu Ausbildungszwecke eingesetzt werden.

Doch mein Problem ist folgendes:
1) Ich weiss nicht, ob der DAC die Daten richtig übernimmt
2) Das Ausgangssignal (inkrementierte Variable) ist nicht linear, 
sondern irgenwie exponential.

Damit ihr nicht alzulange suchen müsst, ist hier noch das Datenblatt:
http://pdf1.alldatasheet.com/datasheet-pdf/view/48370/AD/AD7945BN.html

Verwendete Komponenten:
- ATMega644P mit 20MHz
- AD7945BN
- TL084CN (OpAmp)

Und hier der C-Code:
1
// Einbinden von bestehenden Modulen
2
#include <avr/io.h>                                       // AVR Standart IO Register Definitionen
3
#include <avr/iom644.h>                                   // ATMega644 Register Definitionen
4
#include <avr/iomxx4.h>                                   // ATMegaXX4 Register Definitionen
5
#include <avr/interrupt.h>                                // Interrupt Register Definitionen
6
7
//------------------------------------------------------------------------------
8
// Definitionen
9
#define X_select    (PORTB &= (~(1<<0)))
10
#define Y_select    (PORTB &= (~(1<<1)))
11
#define no_select    ((PORTB |= (1<<0)) & (PORTB |= (1<<1)))
12
#define F_CPU 8000000
13
#define BAUDRATE 19200
14
15
//------------------------------------------------------------------------------
16
// Variablen
17
static volatile int SysCount = 0;                         // Nutz-Counter
18
19
//------------------------------------------------------------------------------
20
// Funktionen
21
void SysInit(){
22
  DDRA = 0xFF;                                            // IO Definieren
23
  DDRB = 0x1B;
24
  DDRC = 0x0F;
25
  PORTC = 0xF0;                                           // Pull up einschalten
26
  DDRD = 0xF0;
27
  
28
  UBRR0H = ((F_CPU/(BAUDRATE*8L)-1) >> 8);                // calc Baud
29
    UBRR0L = (uint8_t)(F_CPU/(BAUDRATE*8L)-1);            // 
30
  UCSR0A |= (1<<U2X0);                                    // RS232 Settings: double speed
31
  UCSR0B |= (1<<RXCIE0)|(1<<TXCIE0)|(1<<RXEN0)|(1<<TXEN0);    // Complete Interrupts, RX und TX einschalten
32
  UCSR0C |= (1<<UCSZ01)|(1<<UCSZ00);                      // Asynchron, 8-Bit
33
  
34
  TCCR2A |= (1<<WGM21);                                   // Timer2 löst mit 2.5MHz Interrupt aus
35
  TCCR2B |= (1<<CS21);
36
  TIMSK2 |= (1<<OCIE2A);
37
  OCR2A = 20;
38
  
39
  no_select;
40
  sei();                                                  // Global Interrupts einschalten
41
}
42
void DAC_Output(uint16_t val){                            // converts 12Bit to the DA Converter
43
  if(val & (1<<8)){                                       // PortC0 (MSB) bis PortC3, Rest PortA (PortA0 LSB)
44
    PORTC |= (1<<3);
45
  }
46
  else{
47
    PORTC &= (~(1<<3));
48
  }
49
  if(val & (1<<9)){
50
    PORTC |= (1<<2);
51
  }
52
  else{
53
    PORTC &= (~(1<<2));
54
  }
55
  if(val & (1<<10)){
56
    PORTC |= (1<<1);
57
  }
58
  else{
59
    PORTC &= (~(1<<1));
60
  }
61
  if(val & (1<<11)){
62
    PORTC |= (1<<0);
63
  }
64
  else{
65
    PORTC &= (~(1<<0));
66
  }
67
  PORTA = val;
68
}
69
//------------------------------------------------------------------------------
70
// INTERRUPS
71
ISR(TIMER2_COMPA_vect){                                   // Mit 2.5MHz SysCount erhöhen
72
  SysCount ++;
73
  if(SysCount == 255){
74
    SysCount = 0;
75
  }
76
}
77
//------------------------------------------------------------------------------
78
// Hauptfunktion (wird beim Start ausgeführt) 
79
int main(void){
80
  uint16_t i = 0;
81
  SysInit();                                              // Systeminitialisierung
82
  while(1){
83
    X_select;                                             // X DAC wählen
84
    DAC_Output(i);
85
    if(i == 0xFFF){
86
      i = 0;
87
    }
88
    i ++;
89
    no_select;                                            // Kein DAC gewählt
90
  }
91
return 0;
92
}
93
//------------------------------------------------------------------------------

Ich hoffe, ihr könnt mir ein wenig weiterhelfen, denn ich versuche 
mitlerweile schon seit mehreren Tagen bei diesem Problem auf einen 
grünen Zweig zu kommen.

MFG
P. Berger

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


Lesenswert?

Wie ist die Beschaltung des DAC?
Wo werden CS und WR angesteuert?

BTW:
So wäre die Umwandlung etwas leserlicher
1
void DAC_Output(uint16_t val){           // converts 12Bit to the DA Converter
2
  PORTC &= 0xF0;
3
  if(val & (1<<8))  PORTC |= (1<<3);     // PortC0 (MSB) bis PortC3, Rest PortA (PortA0 LSB)
4
  if(val & (1<<9))  PORTC |= (1<<2);
5
  if(val & (1<<10)) PORTC |= (1<<1);
6
  if(val & (1<<11)) PORTC |= (1<<0);
7
  PORTA = val;
8
}

von Patrick B. (p51d)


Angehängte Dateien:

Lesenswert?

Laut Datenblatt sind die Zeiten folgende:
tDS  35  20ns   min Data Setup Time
tDH  10  10ns   min Data Hold Time
tCS  60  40ns   min Chip Select Setup Time
tCH  0   0ns    min Chip Select Hold Time
tWR  60  40ns   min Write Pulsewidth

Mit X_select wird einer der beiden DAC's angewält, und dann mit no 
select wieder "befreit".

CS und WR sind über den Selben Pin am MCU angeschlossen, da die Zeiten 
die gleichen sind.
Meine Vermutung war bis jetzt, das tDS und tDH zu kurz sind.

im Anhang ist das Schema.

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


Lesenswert?

> Meine Vermutung war bis jetzt, das tDS und tDH zu kurz sind.
Das Problem dürfte woanders liegen.

> im Anhang ist das Schema.
Die Versorgung über X7 sieht eigenartig aus...
+5V und -5V ohne Masseanschluss, wie geht das?

von Patrick B. (p51d)


Lesenswert?

sry, dies ist nicht mehr das aktuelle Schema.

Die Speisung ist -5V, GND und +5V, ansonsten hat sich nichts geändert.

Ich habe mitlerweile auch noch Verlangsamung der Ausgabe versucht, aber 
ohne Erfolg.

Wenn ich eine Zahl bis 1000 anlege, ändert sich die Spannung am ausgang 
des DAC's fast um nichts, bei 2000 etwas mehr, bei 3000 wieder etwas 
mehr, und bei 4000 extrem.
ABER die Ausgangsspannung ist NIE 0V oder 5V.
Ich bin mitlerweile echt ratlos. Und der DAC ist auch nicht 
logarythmisch...

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


Lesenswert?

> Wenn ich eine Zahl bis 1000 anlege
Hast du das direkt an den 12 Eingangspins des ADCs gemessen?

> ABER die Ausgangsspannung ist NIE 0V oder 5V.
5V wird sie mit einem TL084 bei 5V Versorgung gar nie nicht werden 
können...

von Patrick B. (p51d)


Lesenswert?

Lothar Miller schrieb:
>> Wenn ich eine Zahl bis 1000 anlege
> Hast du das direkt an den 12 Eingangspins des ADCs gemessen?

Ja habe ich. Ich habe jeweils die Zahl 
1,2,4,8,16,32,64,128,256,512,1024,2048 ausgegeben, und nur an den Pins 
D0 bis D11 ein High gehabt, bei allen anderen Low.

>> ABER die Ausgangsspannung ist NIE 0V oder 5V.
> 5V wird sie mit einem TL084 bei 5V Versorgung gar nie nicht werden
> können...

stimmt, aber 0 sollte es werden. Ich werde wahrscheinlich bei der 
definitiven Variante Rail to Rail verwenden, die kommen schon näher an 
die Versorgungsspannung
Aber das was ich meinte mit nie 0 und nie 5V war direkt am DAC-Ausgang 
gemessen.

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


Lesenswert?

> Aber das was ich meinte mit nie 0 und nie 5V war direkt am DAC-Ausgang
> gemessen.
Dort wirst du solche Spannungen auch nie finden. Denn der Pin 2 des ADCs 
heißt AGND und laut Beispielschaltung gehört der an den +Eingang vom 
OpAmp. Das wäre der Pin 10 des TL084. Wie ist das in deinem Schaltplan?

Kurzer Rede tiefer Sinn:
Mindestens beim Opamp U7c ist + und -Eingang vertauscht.
Die anderen darfst du dir selber anschauen... :-o

Die von dir verwendeten Schaltsymbole machen das Lesen der Schaltung zum 
Knobelspiel. Ich habe hier gerade 4 Fenster offen, um diesen (in meinen 
Schaltplänen offensichtlichen) Schaltungsfehler zu sehen... :-/

> Aber das was ich meinte mit nie 0 und nie 5V war direkt am DAC-Ausgang
> gemessen.
Und wenn der OpAmp dann also richtig angeschlossen ist, und damit am 
+Eingang AGND liegt, dann muß der -Eingang sich so ziemlich in der 
unmittelbaren Nähe dieser AGND-Spannung sein, solange der OpAmp regelt. 
Im "normalen" Betrieb wird also am Pin 1 des ADCs 0V zu messen sein.

von Patrick B. (p51d)


Lesenswert?

Lothar Miller schrieb:
>> Aber das was ich meinte mit nie 0 und nie 5V war direkt am DAC-Ausgang
>> gemessen.
> Und wenn der OpAmp dann also richtig angeschlossen ist, und damit am
> +Eingang AGND liegt, dann muß der -Eingang sich so ziemlich in der
> unmittelbaren Nähe dieser AGND-Spannung sein, solange der OpAmp regelt.
> Im "normalen" Betrieb wird also am Pin 1 des ADCs 0V zu messen sein.

Soviel zur Theorie...
Ich habe die Änderungen gemacht, und leider läufts immer noch nicht.

Mit dem KO zwischen AGND und IOUT1 gemessen habe ich dort bei einer 
hochzählenden Variable ~650mV abnehmend, und dann wieder auf 650mV 
schnell ansteigend.

Am IOUT1 gegen Masse gemessen wird die Spannung von 3.8V auf 4.2V 
ansteigen (etwas linearer als bis jetzt, aber immer noch nicht so wie es 
sein sollte) und dann auch nicht schnell genug wieder auf 3.8V.

Am ersten Ausgang des OpAmps habe ich eine Spannung von etwa 
kontinuierlich 3.2V mit unschönem Brumm.

Befor ich diesen Entwurf ohne etwas dazugelehrnt zu haben endgültig auf 
den Müll werfe, werde ich es noch mit einem anderem Prozessor und einem 
anderen Opamp versuchen... mal schauen.

von Patrick B. (p51d)


Lesenswert?

ok, fehler gefunden:

AGND muss auch auf Masse sein, sonst funktioniert das irgendwie nicht

aber Danke für die Hilfe

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


Lesenswert?

> AGND muss auch auf Masse sein
Ja, wie der Name schon nahelegt: AGND = Analog Ground

Das wäre nicht passiert, wenn das Schaltplansymbol so aussähe, wie das 
vom FT232. Dort sind die Pinnamen und die Pinnummern angegeben.

von Jack (Gast)


Lesenswert?

Hallo,

wenn man in einer Funktion auf einem Mikrocontroller was gerechnet hat,
und dabei einen wert Analog ausgeben will, denn weist man den Wert dem
PORT zu.
zb.
1
DDRC=0xff;
2
PORTC=Wert;
so, und wenn die Bits an den PINS fackeln denn kann man sie anhand einen
DAC wieder herstellen
Frage:
1-ist das Richtig
2-Soll man beim Testen die Test Schaltung von dem DAC "die im Datenblatt
als Test Circuit bezeichnet" aufbauen, reicht das "Erfahrung nach !!"

Danke im Voraus

mfg

von Jack (Gast)


Lesenswert?

...OPS,
der PORTC sollte seine 8 PINS, 8bits werte übergeben, die an dem DAC 
[B1...B8] angeschlossen werden.

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.