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?
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.
короткое троль 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
}
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.
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!