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---------------------
Das wird so nicht klappen, weil du ja innerhalb der 1. Schreiboperation das CS bedienen müsstest. Du müsstest entweder eine Software-SPI realisieren, oder 8 Bit schicken, dann die ports auf normale I/O umschalten und noch 2 Bits manuell hinterher klappern.
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?
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.
Steht leider nicht so eindeutig im Datenblatt. So wie ich sein erstes Posting verstehe, macht er das ja schon so, aber der Chip reagiert nicht.
Naja, aus den Ausführungen unter "digital Interface" (Seite21) würde ich das aber so herauslesen.
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.
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.
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.
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!
Ist ja wieder mal ein typisches Beispiel dafür das die ATMEL AVR nur zum Spielen geeignet sind. Für sinnvolle Anwendungen muss mann dann doch andere µC verwenden. DUCKUNDWEG
@ 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 ;-)
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.