Forum: Mikrocontroller und Digitale Elektronik DAC 8534 an Atmega 8 funkt nicht, in C


von Werner (Gast)


Lesenswert?

Hallo,
ich brauche Hilfe weil ich leider nicht weiß was ich falsch mache und 
was ich noch ändern kann bzw. muss damit es endlich funktioniert.
Ich verwende einen Atmega 8 mit 18432000 MHz.

Ich möchte einen 4 Kanal D/A Wandler von Texas Instruments betreiben.
Dazu schrieb ich mal dieses kleine Testprogramm in C.
Mit dem Timerinterupt simuliere ich einfach eine Abtastung die ich 
später brauche.
Sonst ist der DAC das einzige SPI Gerät (vorläufig).

Type: DAC 8534
Das Datenblatt findet man hier:
http://focus.ti.com/docs/prod/folders/print/dac8534.html

Anschluss:
PIN 3,4,12 auf 5 Volt
PIN 5,6,13,14,15,16 auf 0 V (GND) (16 - LDAC Software mäßig)

PIN 11 auf MOSI, Atmega
PIN 10 auf SCK, Atmega
PIN 9 auf PC0, Atmega (9 - Sync_nicht)

An den Ausgängen messe ich mit dem Voltmeter.


Es toggelt brav die LED aber sonst tut sich nicht das was sich tun soll.


Mein Programm:

#include <avr/io.h>    // Ein/Ausgangsbelegung, Definitionen
#include <math.h>      // Mathematikpaket
#include <stdint.h>    // AVR Integer
#include <avr/interrupt.h>  // Interrupt Routinen, Definitionen


#ifndef F_CPU
#define F_CPU 18432000
#endif


#define DAC_KANAL 1 // DAC Bitnr., Kanal auswählen, für Bitshift DAC8534


// Module definieren
void SPI_schreiben2(uint16_t DAC_Wert, uint8_t kanal);  // DAC 8534
ISR(TIMER1_COMPA_vect);        // Interruptroutine


int main (void) {

  // Ein-/Ausgänge initialisieren

  // Datenrichtung Ausgang
  DDRD |= (1 << DDD3);      // LED
  DDRC |= (1 << DDC0);      // Sync_nicht, DAC 8534
  PORTC |= (1 << PC0);      // Sync_nicht ein


  // Timer, 16 bit, Compare Match Modus, Vorteiler 1024

  TCCR1B |= (1 << WGM12) | (1 << CS10) | (1 << CS12);
  OCR1A = 18000;  // Vergleichsregister (1 s bei Vorteiler 1024)
  TIMSK |= (1 << OCIE1A); // enable OutputCompareA Interrupt


  // SPI, Atmega als Master
  // MOSI und SCK Ausgang, alle anderen als Eingänge

  DDRB |= (1 << DDB3) | (1 << DDB5); // SPI Ausgänge aktivieren
  DDRB |= (1 << DDB2);    //
  PORTB |= (1 << PB2);    //

  // Enable SPI, Master, Vorteiler 32

  SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR1);
  SPSR = (1 << SPI2X);

  sei();    // Interrupts global aktivieren


  while(1) {
    ;
  }
  return 0;
}



ISR(TIMER1_COMPA_vect) {

                     // Wert, Kanal
  SPI_schreiben2(16000,0);
  SPI_schreiben2(32000,1);
  SPI_schreiben2(48000,2);
  SPI_schreiben2(64000,3);


  PORTD ^= (1 << PD3);   // LED toggeln
}



void SPI_schreiben2(uint16_t DAC_Wert, uint8_t kanal) { // DAC8534

  unsigned char Daten1, Daten2, Daten3;
  PORTC &= ~(1 << PC0);  // Sync_nicht aus


  // aufspalten in 8 Bit Zeichen
  Daten1 =  DAC_Wert;         //
  Daten2 = (DAC_Wert >> 8);    //

  Daten3 = (kanal << DAC_KANAL);    //
  Daten3 |= (1 << 4);  // LD0 auf 1 (DAC-Kanal aktualisieren)


        // Übertragung starten

  SPDR = Daten3;
  while(!(SPSR & (1 << SPIF))) {
    ;      // warten bis Daten übertragen
  }

  SPDR = Daten2;
  while(!(SPSR & (1 << SPIF))) {
    ;      // warten bis Daten übertragen
  }

  SPDR = Daten1;
  while(!(SPSR & (1 << SPIF))) {
    ;      // warten bis Daten übertragen
  }

  PORTC |= (1 << PC0);  // Sync_nicht ein
}





Dann würde ich noch gerne wissen wie PIN PB2 am Atmega mit der SPI 
Funktion zusammenhängt. Was hat dieser für eine Funktion wie muss man 
ihn wann setzen und warum?


Ich bitte um Hilfe, vielen Dank
Werner

von Magnus Müller (Gast)


Lesenswert?

> Es toggelt brav die LED aber sonst tut sich nicht das was sich tun soll.

Es wäre nett wenn Du uns mitteilen könntest, WAS(!) sich tun sollte.

Ich persönlich möchte mir nicht unbedingt den (fehlerbehafteten) Code 
von vorne bis hinten durchlesen müssen, nur um herauszubekommen, was 
DU(!) womöglich von dem Programm erwartest.

Nix für Ungut...
Magnetus

von Werner (Gast)


Lesenswert?

Alle Sekunden wird diese Routine aufgerufen:

ISR(TIMER1_COMPA_vect) {

                     // Wert, Kanal
  SPI_schreiben2(16000,0);
  SPI_schreiben2(32000,1);
  SPI_schreiben2(48000,2);
  SPI_schreiben2(64000,3);


  PORTD ^= (1 << PD3);   // LED toggeln
}
Das LED nehme ich immer damit ich weiß ob er im Programm stecken bleibt 
oder nicht.


Es sollte jeweils die entsprechende Spannung am DAC Ausgang anliegen.
Kanal 0 sollten ungefähr 1.25 Volt sein, Kanal 2 2.5, ....
Integerwert der in der Klammer steht sollt jeweils als Spg ausgegeben 
werden wobei das Maximum bei 16 Bit natürlich 65535 ist und bei mir 5 
Volt wäre.


bei einem anderen Texas Instruments DAC mit 13 Bit hat mein Programm 
funktioniert, wenn gleich natürlich weniger Bits über den SPI Bus 
übertragen werden und dort ein Chip Select nötig war also eine etwas 
andere Ansteuerung.

Muss aber wegen der Genauigkeit der Anwendung einen 16 Bit Wandler 
verwenden, weil damit später eine Präzisionsstromquelle gesteuert wird.

Ich hoffe das ist eine ausreichende Erklärung

Werner

von Magnus Müller (Gast)


Lesenswert?

> Dann würde ich noch gerne wissen wie PIN PB2 am Atmega mit der SPI
> Funktion zusammenhängt. Was hat dieser für eine Funktion wie muss man
> ihn wann setzen und warum?

PB2(/SS) benötigst du hier nicht. Die Frage kannst du dir selbst 
beantworten indem du ein bisschen mehr Zeit in das Lesen des 
Datenblattes (AVR) verbringst.

Ausserdem verwendest du den falschen SPI-Mode. Aktuell arbeitest du mit 
Mode 0, für den DAC benötigst du aber Mode 1 (CPOL = 1).

Gruß,
Magnetus

von Werner (Gast)


Lesenswert?

Vielen vielen Dank.
Mit dem CPOL funkt es jetzt.

Habs schon entdeckt was PB2 macht:
PB2 muss man auf high setzen damit der SPI Bus aktiviert wird, am ende 
der Routine kann man ihn wieder auf low setzen (oder immer auf high 
lassen). Andernfalls bleibt man in der Routine stecken.
Anscheinend ist es ein Enable befehl für den Atmega8.
Das steht so nicht drin im Datenblatt und trotzdem funkt es nur so !!!

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.