Digitales Potentiometer (Poti) AD8400 erwartet 10bit von ATMEGA128 über SPI

Gast #978016
Lesenswert?
• ▲
▼
Liebe Forenleser und uC-Anwender

Habe eine Frage betreffend Digitalem Potentiometer von Analog Device 
(AD8400) und ATMEGA 128.
Der ATMEGA128 läuft mit einem clock von 16Mhz und ist auf einem Display 
3000 2.1" montiert.
(Link Display 3000: http://www.display3000.com/)

Das Problem sieht wie folgt aus:

Der Digitale Potentiometer von Analog Device (AD8400) erwartet eine 
10bit-Nachricht um den Poti einzustellen.
(Link zu AD8400: 
http://www.analog.com/en/digital-to-analog-converters/digital-potentiometers/ad8400/products/product.html)
Die ersten 2bits definieren die Adresse des RDAC-Speicher und da es nur 
einen einzigen gibt also folgendermassen A1=A0=0.
Alle nächsten 8bits (von der 10bit Nachricht) sind die Einstellungswerte 
von 0-255.
Programmiert wird der AD8400 über SPI, zu finden auf dem ATMEL 128 bei 
den Pins CLK (PB1), SS (PB0) und MOSI (PB2).
Da aber der SPI nur eine 8bit-Nachricht (SPSR) ausgeben kann, habe ich 
die Nachricht in 2x8bit aufgeteilt.
In der ersten 8bit-Nachricht sind lauter NULLEN und in der 
2ten-8bit-Nachricht der einzustellende Wert.
Leider übernimmt mir der Digitale Potentiometer die Einstellungen nicht 
und ich weiss nicht wieso.
Hat jemand von euch eine Idee oder einen anderen Lösungsvorschlag?

------------------code---------------------
#include <avr/io.h>
#include <avr/wdt.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <stdlib.h>

/**************************/
// Variablen
/**************************/

unsigned char poti_init = 0; //
unsigned char poti_adress = 0b00;//0 in 8Bit
//unsigned char poti_data = 0b11001100;//127 in 8Bit
//unsigned char poti_adress = 0;//0 in 8Bit
unsigned char poti_data = 25; //127 in 8Bit


void SPI_MasterInit(void)
{
  /*Set SS(PB0), SCK(PB1) and MOSI(PB2) output, all others input */
  DDRB = (1<<DDB0) | (1<<DDB1) | (1<<DDB2);

  /*Enable SPI, Data Order, Master Select, set clock rate fck/16 */
  SPCR = (1<<SPE) | (1<<DORD) | (1<<MSTR);


}

void SPI_MasterTransmitDelete(unsigned char poti_init)
{
  //PORTB |= (1<<PB0); // CS (oder SS hier bei ATMEG128) auf High setzen
  PORTB &= ~ (1<<PB0); // CS (oder SS hier bei ATMEG128) auf Low setzen
  /*---------------------*/
  /*Start 1. transmission*/
  SPDR = poti_init;
  /*Wait for 1. transmission complete*/
  while (!(SPSR & (1<<SPIF)))
    {
    ;
  }
  /*1. transmission finished*/

  //PORTB |= (1<<PB0); // CS (oder SS hier bei ATMEG128) auf High setzen
  //PORTB &= ~ (1<<PB0); // CS (oder SS hier bei ATMEG128) auf Low 
setzen
  /*---------------------*/
  /*Start 2. transmission*/
  SPDR = poti_init;
  /*Wait for 2. transmission complete*/
  while (!(SPSR & (1<<SPIF)))
    {
    ;
  }
  /*2. transmission finished*/
  /*---------------------*/
  /*Start 3. transmission*/
  SPDR = poti_init;
  /*Wait for 3. transmission complete*/
  while (!(SPSR & (1<<SPIF)))
    {
    ;
  }
  /*3. transmission finished*/
  /*---------------------*/
  PORTB |= (1<<PB0); // CS (oder SS hier bei ATMEG128) auf High setzen
  //PORTB &= ~ (1<<PB0); // CS (oder SS hier bei ATMEG128) auf Low 
setzen
}

void SPI_MasterTransmit(unsigned char poti_adress, unsigned char 
poti_data)
{
  //PORTB |= (1<<PB0); // CS (oder SS hier bei ATMEG128) auf High setzen
  PORTB &= ~ (1<<PB0); // CS (oder SS hier bei ATMEG128) auf Low setzen

  /*Start transmission*/
  //SPDR = poti_adress;

  /*Wait for transmission complete*/
  /*while (!(SPSR & (1<<SPIF)))
    {
    ;
  }*/
  //PORTB |= (1<<PB0); // CS (oder SS hier bei ATMEG128) auf High setzen

  //PORTB &= ~ (1<<PB0); // CS (oder SS hier bei ATMEG128) auf Low 
setzen

  SPDR = poti_data;
  while (!(SPSR & (1<<SPIF)))
    {
    ;
  }

  PORTB |= (1<<PB0); // CS (oder SS hier bei ATMEG128) auf High setzen
  //PORTB &= ~ (1<<PB0); // CS (oder SS hier bei ATMEG128) auf Low 
setzen
}

int main(void)
{
  SPI_MasterInit();
  //SPI_MasterTransmitDelete(poti_init);
  //_delay_ms(1);
  //sei();
  SPI_MasterTransmitDelete(poti_init);
  _delay_ms(2000);
  SPI_MasterTransmit(poti_adress, poti_data);

  /*while(1){

  _delay_ms(10);
  }*/
  return 0;
}
------------------code---------------------
Angehängte Dateien:
Gast #978117
Lesenswert?
• ▲
▼
Hallo Christian

Danke für die Infos.

Verstehe jedoch deine erste Bemerkung nicht ganz oder interpretiere sie 
falsch: "Das wird so nicht klappen, weil du ja innerhalb der 1. 
Schreiboperation das CS bedienen müsstest."

Über die 2. Idee hatte ich bereits nachgedacht, würde dies jedoch anders 
realisieren.
Ich würde die ersten 2bit (A1=A0=0) über GPIO senden.
Danach das SPI "Enablen" und die 8bit Daten über SPI senden.
Dies bedeutet jedoch die ganzen Signale (clock, CS, Data) 
Softwaretechnisch zu realisieren, was nach meinem Wissensstand (Bin 
nicht der Profiprogrammierer!) zeitaufwändig wäre.

Die andere Variante (1. Variante) mit der Software-SPI hört sich 
verlockend an.
Wie müsste ich dies realisieren oder könntest du mir einen Anhaltspunkt 
(Buch, Website, Link) angeben?
Gast #978126
Lesenswert?
• ▲
▼
So wie ich Datenblatt verstanden habe, ist das ein echtes SPI.

Das heißt:
Du kannst soviel Bits da durch schieben, wie du willst. Sobald das CS 
auch HIGH geht, sind die letzten 10Bits gültig. Das ist SPI.

Also muss es gehen, wenn du:

- CS auf LOW legst,
- zwei Addressbits als unteren zwei von acht Bit ausgibst (MSB first),
- acht Datenbits ausgibst (MSB fisrt),
- CS auf HIGH ziehst.

Dann muss das laut SPI gehen.
Gast #978279
Lesenswert?
• ▲
▼
Les mal im Datenblatt deines Atmel.

Viele µC, ich weiß nicht ob es dein Atmel auch kann, können auch auf 
exotische Bitzahlen auf der SPI eingestellt werden. Es lässt sich dort 
also einstellen das zb 10 Bit gesendet werden.
#978317
Lesenswert?
• ▲
▼
Ralph wrote:
> Viele µC, ich weiß nicht ob es dein Atmel auch kann, können auch auf
> exotische Bitzahlen auf der SPI eingestellt werden.

Hast Du dafür vielleicht zufällig ein Beispiel?
Ich kenne keinen Controller bei dem das mit der Hardware-SPI möglich 
ist.
Gast #978375
Lesenswert?
• ▲
▼
zb XC866 von Infineon, ist ein 8052 compatibler 8 Bitter.
Datenbreite auf SPI kann von 2 - 8 Bit eingestellt werden.
Für diesen Fall müsste erst mit 2 Bit Einstellung das Kommando/Adresse 
und danach mit 8 Bit das Datenbyte gesendet werden.

Bei 32 Bit µC wäre es der TMS 470 von TI ist ein ARM7TDMI derivat.
Hier lassen sich 3 bis 16 Bit einstellen.
#978658
Lesenswert?
• ▲
▼
Hallo Fabian

Das sollte doch kein Problem sein. schick einfach 2 Byte. Zuerst Die 
Adresse und als nächstes die Daten. Die ersten 6 Bits der Daten sollten 
eigentlich aus dem Register des AD8400 rausgeschoben werden.


MOSI   X   X   X   X   X   X  A1  A0  D7  D6  D5  D4  D3  D2  D1  D0

CS  1  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   1

falls nicht: software SPI!
#978890
Lesenswert?
• ▲
▼
@ Ralph (Gast)

>Ist ja wieder mal ein typisches Beispiel dafür das die ATMEL AVR nur zum
>Spielen geeignet sind.

Das mal wieder ein typische Beispiel dafür, dass einige Entwickler von 
ICs nicht gerafft haben, dass SPI byteorientiert arbeitet. Die TLC59xx 
LED Treiber fallen mir da spontan ein. Sechzehn einfache FlopFlops a 6 
Transistoren hätten dort das Problem der 7 Bit/Digit gelöst. Wieviel 
Quadratmikrometer hätten diese 96 Transistoren gekostet? Um wieviel wäre 
IC dadurch teurer geworden?

MFG
Falk

P.S. Ich hab den virtuellen Smily schon gesehen ;-)
Gast #979735
Lesenswert?
• ▲
▼
An Alle

Es funktioniert jetzt.
Habe den Poti durch einen neuen AD8400 ersetzt sowie den Code nochmals 
von Anfang an neu geschrieben.
Jetzt funktioniert alles wie es soll.
Es werden wie von Markus betont die ersten 6bits herausgeschoben.

Besten Dank und nochmals herzlichen Dank für Eure beispiellose Hilfe.

Antwort schreiben

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.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.