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
> 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
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
> 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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.