mikrocontroller.net

Forum: Compiler & IDEs Problem mit AD7945BN DAC Ansteuerung


Autor: Patrick B. (p51d)
Datum:

Bewertung
0 lesenswert
nicht 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/48...

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

Und hier der C-Code:
// Einbinden von bestehenden Modulen
#include <avr/io.h>                                       // AVR Standart IO Register Definitionen
#include <avr/iom644.h>                                   // ATMega644 Register Definitionen
#include <avr/iomxx4.h>                                   // ATMegaXX4 Register Definitionen
#include <avr/interrupt.h>                                // Interrupt Register Definitionen

//------------------------------------------------------------------------------
// Definitionen
#define X_select    (PORTB &= (~(1<<0)))
#define Y_select    (PORTB &= (~(1<<1)))
#define no_select    ((PORTB |= (1<<0)) & (PORTB |= (1<<1)))
#define F_CPU 8000000
#define BAUDRATE 19200

//------------------------------------------------------------------------------
// Variablen
static volatile int SysCount = 0;                         // Nutz-Counter

//------------------------------------------------------------------------------
// Funktionen
void SysInit(){
  DDRA = 0xFF;                                            // IO Definieren
  DDRB = 0x1B;
  DDRC = 0x0F;
  PORTC = 0xF0;                                           // Pull up einschalten
  DDRD = 0xF0;
  
  UBRR0H = ((F_CPU/(BAUDRATE*8L)-1) >> 8);                // calc Baud
    UBRR0L = (uint8_t)(F_CPU/(BAUDRATE*8L)-1);            // 
  UCSR0A |= (1<<U2X0);                                    // RS232 Settings: double speed
  UCSR0B |= (1<<RXCIE0)|(1<<TXCIE0)|(1<<RXEN0)|(1<<TXEN0);    // Complete Interrupts, RX und TX einschalten
  UCSR0C |= (1<<UCSZ01)|(1<<UCSZ00);                      // Asynchron, 8-Bit
  
  TCCR2A |= (1<<WGM21);                                   // Timer2 löst mit 2.5MHz Interrupt aus
  TCCR2B |= (1<<CS21);
  TIMSK2 |= (1<<OCIE2A);
  OCR2A = 20;
  
  no_select;
  sei();                                                  // Global Interrupts einschalten
}
void DAC_Output(uint16_t val){                            // converts 12Bit to the DA Converter
  if(val & (1<<8)){                                       // PortC0 (MSB) bis PortC3, Rest PortA (PortA0 LSB)
    PORTC |= (1<<3);
  }
  else{
    PORTC &= (~(1<<3));
  }
  if(val & (1<<9)){
    PORTC |= (1<<2);
  }
  else{
    PORTC &= (~(1<<2));
  }
  if(val & (1<<10)){
    PORTC |= (1<<1);
  }
  else{
    PORTC &= (~(1<<1));
  }
  if(val & (1<<11)){
    PORTC |= (1<<0);
  }
  else{
    PORTC &= (~(1<<0));
  }
  PORTA = val;
}
//------------------------------------------------------------------------------
// INTERRUPS
ISR(TIMER2_COMPA_vect){                                   // Mit 2.5MHz SysCount erhöhen
  SysCount ++;
  if(SysCount == 255){
    SysCount = 0;
  }
}
//------------------------------------------------------------------------------
// Hauptfunktion (wird beim Start ausgeführt) 
int main(void){
  uint16_t i = 0;
  SysInit();                                              // Systeminitialisierung
  while(1){
    X_select;                                             // X DAC wählen
    DAC_Output(i);
    if(i == 0xFFF){
      i = 0;
    }
    i ++;
    no_select;                                            // Kein DAC gewählt
  }
return 0;
}
//------------------------------------------------------------------------------

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

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie ist die Beschaltung des DAC?
Wo werden CS und WR angesteuert?

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

Autor: Patrick B. (p51d)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Patrick B. (p51d)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Patrick B. (p51d)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Patrick B. (p51d)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Patrick B. (p51d)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok, fehler gefunden:

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

aber Danke für die Hilfe

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Jack (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.
DDRC=0xff;
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

Autor: Jack (Gast)
Datum:

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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.