Ich habe meinen ATMega 328 an einen PCF8591 angeschlossen, der als DAC
arbeiten soll. Die ADC Funktion benötige ich momentan nicht.
Mein Programm habe ich nach der Anleitung unter
http://www.mikrocontroller.net/articles/AVR_TWI geschrieben.
Prescaler habe ich auf 1 gesetzt und mein µC läuft mit 8 MHz. TWBR
Register habe ich auf 255 gesetzt. Damit komme ich auf eine SCL-Frequenz
von ca. 15kHz mit der entsprechenden Formel im Datenblatt.
Zum Test lasse ich in einer Endloschleife Werte von 0-255 ausgeben und
würde also eine Rampe erwarten. Der Output sieht zwar entfernt nach
Rampe aus, aber es werden viele Werte übersprungen. Wenn ich den CPU
Takt auf 1MHz setze, sieht die Rampe deutlich besser aus, aber immer
noch werden Werte übersprungen.
Hat irgendjemand eine Idee, woran es liegen könnte?
Ich sehe das in Deinem Schaltpan die Abblockkondensatoren fehlen.
Ausserdem ist die Last an dem Ausgang des DAC viel zu hoch.
...und in Deinem Sourcecode vermisse ich das volatile von der im
interrupt genutzten Variable !
So kann das ja nix werden.
Falls der Post grade heißen sollte "schick doch Schaltplan und Code mit
du Pappnase", will ich dem mal nachkommen.:-)
Abblockkondensatoren habe ich drin. Die Last am DAC Ausgang ist der
OSzilloskopeingang. Pullup Widerstände am I2C Bus sind momentan 1k. Ich
hatte auch schon 10k und 100k ausprobiert, aber das hat nichts
verändert. Zum Schaltplan...es sind nur auf dem Breadboard die I2C Pins
des µC mit dem DAC verbunden. Gespeist wird das Ganze von einem
Labornetzteil.
void ERROR(int pin)
{
PORTD = pin;
}
void SendValue(int value)
{
TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN); //TWSTA = TWI START
Condition Bit
while (!(TWCR & (1<<TWINT))); //Warten bis TWINT wieder im
TWCR gesetzt ist, dann kanns weiter gehen
if ((TWSR & 0xF8) != TW_START)
ERROR(_BV(PORTD7));
//Fehlerbehandlung
TWDR = 0x90; //Slave Adresse senden 1 0 0 1 0 0 0 0
TWCR = (1<<TWINT) | (1<<TWEN); //Senden des Paketes
while (!(TWCR & (1<<TWINT))); //Warten bis TWINT wieder im TWCR
gesetzt ist, dann kanns weiter gehen
if ((TWSR & 0xF8) != TW_MT_SLA_ACK) //Fehlerbehandlung
ERROR(_BV(PORTD6));
TWDR = 0x40; //Control Byte 0 1 0 0 0 0 0 0 0x40 Analog out
anschalten, Rest egal
TWCR = (1<<TWINT) | (1<<TWEN); //Senden des Paketes
while (!(TWCR & (1<<TWINT))); //Warten bis TWINT wieder im TWCR
gesetzt ist, dann kanns weiter gehen
if ((TWSR & 0xF8) != TW_MT_DATA_ACK) //Fehlerbehandlung
ERROR(_BV(PORTD5));
TWDR = value; //Daten Byte setzen
TWCR = (1<<TWINT) | (1<<TWEN); //Senden des Paketes
while (!(TWCR & (1<<TWINT))); //Warten bis TWINT wieder im TWCR
gesetzt ist, dann kanns weiter gehen
if ((TWSR & 0xF8) != TW_MT_DATA_ACK) //Fehlerbehandlung
ERROR(PORTD4);
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO); // Senden des Stop
if ((TWSR & 0xF8) != TW_MT_DATA_ACK) //Fehlerbehandlung
ERROR(_BV(PORTD3));
}
int main(void)
{
DDRD = 0xff;
PORTD = 0;
TWBR = 0xff;
while(1)
{
for(int i = 0; i <255;++i)
{
SendValue(i);
}
}
}
Mach doch einfach mal nen Überschlag:
I2C max 100kHz, für 8 Bit Daten brauche ich 20 Zyklen (Start, Adresse,
ACK, Daten, ACK, Stop), also kann ich maximal 100k / 20 = 5kSamples
erreichen im best Case.
Das ist nicht das Problem. Ich habe die I2C Frequenz auf 15kHz und
trotzdem sehe ich anstatt 255 Treppenstufen nur 9 Stufen imt dem oben
geposteten Code. Bei 120kHz sinds dann nur noch 2-3 Treppenstufen.
Im Endeffekt bräuchte ich eine I2C Frequenz von ca. 220kHz, weil ich ca.
8k Daten pro Sekunde schicken muss. Meine Frage ist eben, wieso schon
bei so niedriger Frequenz der DAC anscheinend nicht mehr mitkommt.
Kurze Frage:
Nachdem Du den Stop-Befehl gesendet hast, erfolgt m.W. eine Abfrage, ob
diese Bedingung erfüllt wurde, die hier wohl fehlt.
Ich kenne diese Vorgehensweise bei PIC-Controllern(Sprut.de), wo
entweder durch Interrupt oder Polling abgefragt wurde, ob der Controller
dies auch schon durchgeführt hatte, um die nächsten Aktionen auf dem Bus
durchführen zu können.
Beim Start machst Du dieses, aber beim Stop ist es nicht drinnen (oder
Ich übersehe es).
I2C is da auch iwie das maximal dämliche für ;)
Weil langsam und Protokolloverhead.
Nimm nen 74HC595, den kannste mit maximalen SPI Takt des AVRs bespaßen.
Sebastian H. schrieb:> Kurze Frage:>> Nachdem Du den Stop-Befehl gesendet hast, erfolgt m.W. eine Abfrage, ob> diese Bedingung erfüllt wurde, die hier wohl fehlt.>> Ich kenne diese Vorgehensweise bei PIC-Controllern(Sprut.de), wo> entweder durch Interrupt oder Polling abgefragt wurde, ob der Controller> dies auch schon durchgeführt hatte, um die nächsten Aktionen auf dem Bus> durchführen zu können.>> Beim Start machst Du dieses, aber beim Stop ist es nicht drinnen (oder> Ich übersehe es).
Ja irgendsowas vermute ich auch. Der o.g. Artikel von
Mikorcontroller.net sagt dazu allerdings etwas anderes:
"Nachdem bis hierhin alles funktioniert hat (angenommen), muss nun nur
noch ein STOP gesendet werden. Dies erfolgt analog zu den obigen
Ausführungen durch Schreiben eines speziellen Wertes in TWCR. Nach dem
Löschen von TWINT wird dieses gesendet. Allerdings wird danach TWINT
nicht automatisch wieder gesetzt, wie es zuvor immer der Fall war."
Ich habe auch schonmal ein delay von ein paar ms nach dem Stop
eingebaut, aber das hat auch nichts verbessert, aber ich werde das
nachher nochmal versuchen.
Martin Wende schrieb:> I2C is da auch iwie das maximal dämliche für ;)> Weil langsam und Protokolloverhead.> Nimm nen 74HC595, den kannste mit maximalen SPI Takt des AVRs bespaßen.
Hmmm...ich muss das Datenblatt nochmal genauer anschauen, aber inwiefern
kann ich den 74HC595 denn als DAC verwenden?
Versuche einmal, das Stop-Bit und den Interrupt abzufragen.
Folgendes steht im Datenblatt dazu( und wird hier auch erklärt
Beitrag "Re: "I2C-Stopp" wird nicht ausgeführt (HW-TWI, AVR)"):
1)Writing the TWSTO bit to one in Master mode will generate a STOP
condition on the 2-wire
Serial Bus.When the STOP condition is executed on the bus, the TWSTO bit
is cleared automatically.
2)TWINT: TWI Interrupt Flag
This bit is set by hardware when the TWI has finished its current job
and expects application
software response.
Wenn Du jetzt Stop sendest erhälst Du TWINT = 1, wenn Stop erfolgreich
durchgeführt wurde. So lange würde Ich warten, denn es kann ja sein,
dass dein Slave trotz delay etwas länger gebraucht hatte, der Master
dieses jedoch dafür "Taub" war.
R2R DAC duckundwech
Um ehrlich zu sein hab ich die Nummer verwechselt, also deinen IC fürn
Portaxpander gehalten mit dem du schon R2R DAC machst.
Im Datenblatt steht tatsächlich nix zur maximalen Samplingrate fürn DAC.
Nur fürn ADC und die is bei 11kHz und "Max sampling rate given by
I2C-bus speed".
Tolle Aussage...
Guck dir mal den MCP4706A0T an.
Der kann 400kHz und 3,4MHz I2C und kanns chnell genug samplen.
Oder den MCP4902, der wird dann per SPI angesteuert.
Hi
>Im Datenblatt steht tatsächlich nix zur maximalen Samplingrate fürn DAC.
Selbstverständlich. Im Aktuellen Datenblatt von NXP, S.18:
DAC conversion frequency - - 11.1 kHz
Allerdings würde ich die Übertragung wie im Datenblatt machen:
Adressierung-Controlbyte-Datenbyte-Datenbyte-.....
MfG spess
Hallo,
ich meine, ich hätte vor gut 10 Jahren mit dem PCF8591 7 KHz geschafft.
Viel mehr ist wohl nicht drin. Es ist ja auch ein Oldtimer.
Gruss Klaus.
Spess53 schrieb:>> DAC conversion frequency - - 11.1 kHz>> Allerdings würde ich die Übertragung wie im Datenblatt machen:>> Adressierung-Controlbyte-Datenbyte-Datenbyte-.....>
Mist, ich habe das Datenblatt jetzt gefühlte 100 mal durchgesehen, aber
das trotzdem überlesen. Würde ja für mich grade noch so reichen, weil
das Signal am Ausgang nur 8kHz haben muss.
Ich tippe momentan eher darauf, dass mein Exemplar defekt ist. Ich habe
grade mal den Prescaler auf 4 gesetzt, das TWBR auf 255 und nach jedem
Durchlauf 0,1 Sekunde delay eingebaut. Und trotzdem waren keine 255
Stufen vorhanden. Manchmal gings auch wieder bergab, dann waren wieder
Sprünge drin. Sehr seltsam das Ganze.
Die ganzen ACK Signale kommen ja vom DAC. Insofern würde ich erwarten,
dass er dann auch was tut für sein Geld.:-)
Martin Wende schrieb:> R2R DAC duckundwech>> Um ehrlich zu sein hab ich die Nummer verwechselt, also deinen IC fürn> Portaxpander gehalten mit dem du schon R2R DAC machst.> Im Datenblatt steht tatsächlich nix zur maximalen Samplingrate fürn DAC.> Nur fürn ADC und die is bei 11kHz und "Max sampling rate given by> I2C-bus speed".> Tolle Aussage...>> Guck dir mal den MCP4706A0T an.> Der kann 400kHz und 3,4MHz I2C und kanns chnell genug samplen.>> Oder den MCP4902, der wird dann per SPI angesteuert.
Den MCP4706A0T hatte ich auch schon im Visier, aber SOT/MSOT versuche
ich zu vermeiden.
Den MCP4902 habe ich auch zu Hause, den werde ich morgen mal
ausprobieren. Ich habe den PCF8591 bevorzugt, weil die SPI Pins ja auch
vom ISP verwendet werden. Das Boardlayout wäre angenehmer geworden, wenn
ich SPI Pins nicht für den DAC gebraucht hätte, aber daran solls nicht
scheitern.:-)
Soooo...jetzt hab ich endlich herausgefunden wo das Problem lag. Ich
hatte PIN Ext offen gelassen. Ich hatte das Datenblatt so interpretiert,
dass Ext nur für den A/D Betrieb relevant ist. Wenn ich ihn auf Masse
lege funktioniert alles wunderbar. Vielleicht hilft der Thread jemandem
diesen Fehler nicht zu begehen.