Möchte gerne einen Funktionsgenerator IC AD9850 seriell ansteuern. Das Modul erwartet einen 40-Bit Wert (siehe Anhang). Ich lese also in meinem C Programm einen Long Datentyp für die Frequenz ein, welcher 32Bit besitzt. long Freq = 4; Gebe ich also '4 Hz' ein müsste Freq folgendermaßen ausschauen: 0000 0000 0000 0000 0000 0000 0000 0100 Nun muss ich dem Modul seine 40-Bit Information übermitteln. Also zuerst die 32 Stellen long Freq (LSB bis MSB), danach noch Phase usw. Die 40Bit sollen am PB0 des AVR ankommen. Doch wie zerlege ich die Zahl '4' binär und gebe sie nacheinander am PB0 aus? Bei Arduino gibt es einen Befehl "Shiftout" der das erledigt, aber darum lerne ich lieber mit AVR ;) Vielen Dank!!
Walter schrieb: > Bei Arduino gibt es einen Befehl "Shiftout" der das erledigt, aber darum > lerne ich lieber mit AVR ;) Dann binde doch die Arduino Library ein und rufe "Shiftout" auf ;-)
Ja ich weiß wie man Bits setzt, löscht, verschiebt etc. Aber verstehe echt nicht wie ich das auf das Beispiel bezogen umsetzten soll. Wenn ich jetzt '4' senden möchte: clk PORTB &= ~ (1<<PB0); // 1 clk PORTB &= ~ (1<<PB0); // 2 clk PORTB |= (1<<PB0); // 4 clk PORTB &= ~ (1<<PB0); // 8 clk PORTB &= ~ (1<<PB0); // 16 usw. Bis das Register des Moduls voll ist.. Das ist natürlich Quatsch, aber vastehe nicht wie ich sonst '4' senden übermitteln soll? Ich weiß, dass man Shiftoperatoren >> braucht, aber wie?
void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val) { uint8_t i; for (i = 0; i < 8; i++) { if (bitOrder == LSBFIRST) digitalWrite(dataPin, !!(val & (1 << i))); else digitalWrite(dataPin, !!(val & (1 << (7 - i)))); digitalWrite(clockPin, HIGH); digitalWrite(clockPin, LOW); } } Wie ist das zu verstehen?
Walter schrieb: > Ja ich weiß wie man Bits setzt, löscht, verschiebt etc. Nein, weißt du nicht. Maximal hast du Code gesehen, wo sowas gemacht wird, verstanden hast du es aber offensichtlich nicht. > Aber verstehe echt nicht wie ich das auf das Beispiel bezogen umsetzten > soll. Tja, man muß etwas eben wirklich verstehen, um es sinnvoll einsetzen zu können. Da hilft nur eins: Lernen, bis du es wirklich verstanden hast. Nein, mit Copy&Paste von Code alleine lernt man exakt garnix, höchstens, wie man eine Copy&Paste-Operation durchführt. Das aber können auch Affen leisten, wenn man es ihnen ein paarmal zeigt...
!!(val & (1 << i))); ist mir unklar.. val (=meine Frequenz z.B '400') wird mit 1 &verknüpft das immer um i Stellen weitergeschoben wird. Was haben die beiden !! auf sich? Ich kenne nur != ...ungleich
Walter schrieb: > !!(val & (1 << i))); ist mir unklar.. val & (1 << i) Angenommen val ist 10 Binär ist das 0000 1010 i ist 0 Dann ist val & (1 << i(0)) = 0000 0000 i++ val & (1 << i(1)) = 0000 0010 i++ val & (1 << i(2)) = 0000 0000 i++ val & (1 << i(3)) = 0000 1000 i++ val & (1 << i(4)) = 0000 0000 i++ val & (1 << i(5)) = 0000 0000 i++ val & (1 << i(6)) = 0000 0000 i++ val & (1 << i(7)) = 0000 0000 Die Ergebnisse sind also nacheinander 0, 2, 0, 8, 0, 0, 0, 0 Auf Datapin soll eine 0 oder 1 ausgegeben werden. Nullen hast du genug aber statt 1en hast du 2 und 8. !(val & (1 << i))) macht aus 0 eine 1 und aus !0, nicht 0 also irgendwas, eine 0. Also wenn das Ergebnis 0 ist, macht es daraus eine 1 wenn es !0 ist, eine 0 Jetzt sind die Ergebnisse der Reihe nach 1, 0, 1, 0, 1, 1, 1, 1 Negiert man das jetzt zweimal !!(val & (1 << i))) Wird daraus 0, 1, 0, 1, 0, 0, 0, 0 Und da wo vorher 2 und 8 stand, steht jetzt 1. So wie man es braucht. Schiebeergebnis: 0, 2, 0, 8, 0, 0, 0, 0 1. Negation: 1, 0, 1, 0, 1, 1, 1, 1 2. Negation: 0, 1, 0, 1, 0, 0, 0, 0 mfg.
:
Bearbeitet durch User
Der shiftoperator in C hat auch eine ausserst schrottige Schreibweise. Etwas vom idiotischten, das ich je sah.
короткое троль schrieb: > Der shiftoperator in C hat auch eine ausserst schrottige Schreibweise. > Etwas vom idiotischten, das ich je sah. Es ist so wie es ist und optisch und syntaktisch doch klar ! Was soll also dein Einschrieb ?
Vielen Dank für die Hilfe!! Bitmanipulation ist mir jetzt um einiges klarer geworden =) Das Modul gibt jetzt auch schon brav einen Sinus aus, aber leider noch nicht die Frequenz die ich einstelle. Kleine Werte --> sehr hohe Frequenzen Hohe Werte --> niedrige Frequenzen Wo liegt der Fehler, weshalb es genau umgekehrt funktioniert? ------------------------------------------------------------------- FUNKTIONIERENDER ARDUINO CODE ------------------------------------------------------------------- //AD9850 DDS test #define DDS_CLOCK 125000000 #define CLOCK 8 //pin connections for DDS #define LOAD 9 #define DATA 10 #define RESET 11 void setup() { pinMode (DATA, OUTPUT); pinMode (CLOCK, OUTPUT); pinMode (LOAD, OUTPUT); pinMode (RESET, OUTPUT); AD9850_init(); AD9850_reset(); SetFrequency(10000000); } void loop() { } void SetFrequency(unsigned long frequency) { unsigned long tuning_word = (frequency * pow(2, 32)) / DDS_CLOCK; digitalWrite (LOAD, LOW); shiftOut(DATA, CLOCK, LSBFIRST, tuning_word); shiftOut(DATA, CLOCK, LSBFIRST, tuning_word >> 8); shiftOut(DATA, CLOCK, LSBFIRST, tuning_word >> 16); shiftOut(DATA, CLOCK, LSBFIRST, tuning_word >> 24); shiftOut(DATA, CLOCK, LSBFIRST, 0x0); digitalWrite (LOAD, HIGH); } void AD9850_init() { digitalWrite(RESET, LOW); digitalWrite(CLOCK, LOW); digitalWrite(LOAD, LOW); digitalWrite(DATA, LOW); } void AD9850_reset() { //reset sequence is: // CLOCK & LOAD = LOW // Pulse RESET high for a few uS (use 5 uS here) // Pulse CLOCK high for a few uS (use 5 uS here) // Set DATA to ZERO and pulse LOAD for a few uS (use 5 uS here) // data sheet diagrams show only RESET and CLOCK being used to reset the device, but I see no output unless I also // toggle the LOAD line here. digitalWrite(CLOCK, LOW); digitalWrite(LOAD, LOW); digitalWrite(RESET, LOW); delay(5); digitalWrite(RESET, HIGH); //pulse RESET delay(5); digitalWrite(RESET, LOW); delay(5); digitalWrite(CLOCK, LOW); delay(5); digitalWrite(CLOCK, HIGH); //pulse CLOCK delay(5); digitalWrite(CLOCK, LOW); delay(5); digitalWrite(DATA, LOW); //make sure DATA pin is LOW digitalWrite(LOAD, LOW); delay(5); digitalWrite(LOAD, HIGH); //pulse LOAD delay(5); digitalWrite(LOAD, LOW); // Chip is RESET now }
-------------------------------------------------------------- MEIN CODE -------------------------------------------------------------- #include <math.h> #include <avr/io.h> #include <util/delay.h> #include "mylcd.h" #include "font6x8.h" #define DDS_CLOCK 125000000 void AD9850_init() //ALLE LEITUNGEN AUF LOW { PORTB &= ~(1<<PB0); //CLK PORTB &= ~(1<<PB1); //LOAD PORTB &= ~(1<<PB2); //DATA PORTB &= ~(1<<PB3); //RST } void AD9850_reset() { PORTB &= ~(1<<PB0); //CLK LOW PORTB &= ~(1<<PB1); //LOAD LOW PORTB &= ~(1<<PB3); //RST IMPULS _delay_us(5); PORTB |= (1<<PB3); _delay_us(5); PORTB &= ~(1<<PB3); PORTB &= ~(1<<PB0); //CLK IMPULS _delay_us(5); PORTB |= (1<<PB0); _delay_us(5); PORTB &= ~(1<<PB0); PORTB &= ~(1<<PB2); //DATA AUF LOW PORTB &= ~(1<<PB1); //LOAD IMPULS _delay_us(5); PORTB |= (1<<PB1); _delay_us(5); PORTB &= ~(1<<PB1); } void AD9850_Set_Frequency(uint16_t frequency) { PORTB &= ~(1<<PB1); //LOAD uint16_t tuning_word = (frequency * pow(2, 32)) / DDS_CLOCK; //BERECHNUNG int i = 0 ; for(i=0;i<8;i++) //ERSATZ FÜR SHIFTOUT { if((tuning_word & !!(1 << i)) == 1) { PORTB|=(1<<PB2); //DATA } else { PORTB &= ~ (1<<PB2); } PORTB |= (1<<PB0); //CLK IMPULS PORTB &=~ (1<<PB0); } i=0; for(i=0;i<8;i++) { if(((tuning_word>>8) & !!(1 << i)) == 1) { PORTB|=(1<<PB2); //DATA } else { PORTB &= ~ (1<<PB2); } PORTB |= (1<<PB0); //CLK IMPULS PORTB &=~ (1<<PB0); } i=0; for(i=0;i<8;i++) { if(((tuning_word>>16) & !!(1 << i)) == 1) { PORTB|=(1<<PB2); //DATA } else { PORTB &= ~ (1<<PB2); } PORTB |= (1<<PB0); //CLK IMPULS PORTB &=~ (1<<PB0); } i=0; for(i=0;i<8;i++) { if(((tuning_word>>24) & !!(1 << i)) == 1) { PORTB|=(1<<PB2); //DATA } else { PORTB &= ~ (1<<PB2); } PORTB |= (1<<PB0); //CLK IMPULS PORTB &=~ (1<<PB0); } i=0; for(i=0;i<8;i++) { if(((0x0) & !!(1 << i)) == 1) { PORTB|=(1<<PB2); //DATA } else { PORTB &= ~ (1<<PB2); } PORTB |= (1<<PB0); //CLK IMPULS PORTB &=~ (1<<PB0); } i=0; PORTB |= (1<<PB1); //LOAD } int main (void) { DDRB=0b1111111; //GESAMTEN PORT ALS AUSGANG AD9850_init(); AD9850_reset(); AD9850_Set_Frequency(1=0); }
1. Benutz code Tags 2. Überleg mal was du da machst! 2.1 Du benutzt uint16 obwohl du 24-32Bit shiftest? Nimm uint32 2.2 Die for-schleifen lassen sich zusammenfassen! Ungetestet am Handy ges geschrieben: [c] void AD9850_Set_Frequency(uint32_t frequency) { PORTB &= ~(1<<PB1); //LOAD uint32_t tuning_word = (frequency * pow(2, 32)) / DDS_CLOCK; //BERECHNUNG int i = 0 ; for(i=0;i<32;i++) //ERSATZ FÜR SHIFTOUT { if((tuning_word & !!(1 << i)) == 1) { PORTB|=(1<<PB2); //DATA } else { PORTB &= ~ (1<<PB2); } PORTB |= (1<<PB0); //CLK IMPULS PORTB &=~ (1<<PB0); } i=0; PORTB &= ~ (1<<PB2); for(i=0;i<8;i++) { PORTB |= (1<<PB0); //CLK IMPULS PORTB &=~ (1<<PB0); } PORTB |= (1<<PB1); //LOAD }
Walter schrieb: > Die 40Bit sollen am PB0 des AVR ankommen. > Doch wie zerlege ich die Zahl '4' binär und gebe sie nacheinander am PB0 > aus? Bist du wirklich so ungelenkig, daß du sowas nicht aus eigener Kraft hinbekommst? void SageZahl(long Z) { long M; M = 1; while (M) { if (Z&M) SageNeEins(); else SageNeNull(); M = M<<1); } } Das läuft überall, egal ob AVR oder was anderes. Den Rest, also Optimierungen aller Art überlasse bitte dem jeweiligen Compiler. W.S.
Leider keine Lösung dafür im Internet/Buch gefunden: frequenz = frequenz >>=1; was macht dieser Ausdruck ">>=" , kenne nur ">>" ?
Ich schrub auch manchmal unter meinem Namen (Walter), aber das geht jetzt nicht mehr, der Name ist jetzt verbrannt :-(
Walter schrieb: > frequenz = frequenz >>=1; So wie du es da benutzt ist es falsch. >>= ist so zu verstehen wie |= oder &= (die du ja mehrmals nutzt.) frequenz = frequenz >> 1; //oder kurz frequenz >>= 1; Aber nicht gemischt!
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.