PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : 18F4550 C Compiler - Wie rechne ich mit großen Zahlen?



BigBearRN
06.02.2009, 16:49
Hallo Leute

Bin neu hier im Forum, beschäftige mich aber seit ca. einem
Monat mit meinen 18F4550 ;)

Jetzt habe ich folgendes Problem:

Ich habe ein Programm geschrieben mit dem ich über eine
PS/2 Tastatur eine Frequenz eingeben kann und diese auf einer LCD Anzeige
und einem Lautsprecher ausgebe.
Das einlesen der Tastatur funzt wunderbar
ebenso das Ausgeben auf der LCD anzeige
Aber der Lautsprecher...
Naja der macht was er will...
Ich gebe 100Hz ein und er summt mit ca 10kHz vor sich hin...
Dann gebe ich 1kHz ein und aufeinmal brummt er mit ca 300Hz...
Ich vermute das das Problem bei den Werten liegt
Die liegen ja zwischen 20.000 und 1*10^-6...
Ich habe versucht das Problem wie folgt zu lösen
(ist natürlich nur ein kleines Codesegment ;) ):

float freq=0.0f;
long delay=0;
int diff=1;
...
freq=freq+(1/diff); //so addiere ich die Zahlen die ich eingebe
diff=diff*10; //beim nächsten Schritt wäre diff 10 -> freq ware 1.1f danach 1.11f usw..
//und so gebe ich dann den Sound aus:
delay=freq*(diff/10);
freq=1/delay;
delay_ms(200);
lcd_gotoxy(1,4);
printf(lcd_putc,"%u Hz",freq);
// Hier wird der Frequenzgenerator gestartet
sound:
output_high(pin_c0);
delay_us(delay);
output_low(pin_c0);
delay_us(delay);
if(!input(pin_e1)==0){goto sound;}

So das ist mein Code...
Nochmal mein Problem:
Der Lautsprecher gibt nicht die Frequenz aus, die ich mit der Tastatur eingebe..
Ich vermute es liegt daran, das der PIC die Werte nicht handlen kann (Division durch 1.xxxxx oder Multiplikation mit 10000..)

Also wenn jemand weiter weis:
BITTE POSTEN :)

Ich bin über jede Hilfe dankbar!

MFG BigBearRN

the_Ghost666
06.02.2009, 21:43
Moin,
Ich muss gestehen, dass ich noch nicht mit dem Pic18 gearbeitet habe, nur die 16er aber mit dem CCS compiler.
Welchen Compiler benutzt du? Den C18?
Mein erster Tip ist: schau nach, ob die delay_us routine überhaupt floating point verarbeiten kann, denn das machst du ja bei ner Teilung von 1/irgendwas. Ich glaube, dass nur ganzzahlen, vielleicht sogar nur 8bit unterstützt werden.
Dann versuche ich gerade den Code zu verstehen. Die letzte Zeile ist ein Abbruch wenn ne Taste gedrückt wird oder? Ich würde dir raten statt ner IF und dann Goto geschichte eine While-Schleife zu nehmen, wenn schon C, dann auch richtig.
float freq=0.0f; was macht das f da hinten dran? Ist wohl für die Syntax des Compilers wichtig, oder?
Was du am Anfang mit dem Freq machst, versteh ich nicht ganz, ebenso was diff genau tut und warum du es immer verzehnfachst, soll das für die 10er potenzen sein?
Ich würde dir empfehlen mal die software in nem Simulator laufen zu lassen, z.B. in MPLAB, um dann den Code genau zu betrachten, was da eigentlich passiert.
Die Long könnte wohl irgendwann überlaufen, aber die float... das dauert ne Weile..

BigBearRN
07.02.2009, 09:32
Hei

Erstmal: Danke für deine Hilfe :)

Also ich bin mir nicht sicher, aber ich glaube ich verwende den C32.
Ich glaube nicht, das die delay routine floating point zahlen verarbeiten kann, der Lautsprecher gibt aber trotzdem einen Ton aus - nur nicht den den ich will.
Und jap die letzte Zeile beschreibt die Abbruchbedinung ;)
Ich habe nur deswegen goto verwendet weil das - glaube ich zumindest - weniger ASM Befehle benötigt
Das 0.0f beschreibt meines Wissens nach das es eine fp Zahl ist.
Ich hab das nur bei einem Freund gesehen und bin das auch so von C# gewöhnt - kann seine das kein "f" nötig ist
und zu der Zeile
freq=freq+(1/diff)
freq ist am Anfang 0.
Wenn ich jetzt die Zahl eins Drücke steht in freq folgendes:
freq=0+(1/1);
freq ist also 1.0f
diff=1*10
diff ist also 10
Drücke ich dann die 2:
freq=1+(2/10)
freq ist also 1.2f
diff ist 100.
Drücke ich dann auch noch die 3:
freq=1.2f+(3/100)
freq ist also 1.23f
usw..
Damit verhindere ich nur im gegensatz zu Integer das ich Zahlen über 254 habe (meiner Erfahrung nach schafft der PIC nicht mehr)
und mit
delay=freq*(diff/10)
schreibe ich die Richtige frequenz nach delay
in delay steht dann also
delay=123
ich weis, die Namen der Variablen sind verwirrend.. :roll:
und mit freq=1/delay schreibe ich dann die Periodendauer nach freq
(wobei ich noch die halbe Frequnz am Lautsprecher ausgebe da ich nur die
halbe Periodendauer als delay verwenden darf um die richtige Frequenz zu erhalten - ist im Moment aber egal)
Aber ich glaube mit Werten bis max. 22 000 werde ich eine long int nicht zum Überlaufen bringen ;)
Und ich weis nicht genau wie ich das mit dem Simulator machen soll
Weil ich ja nicht definieren kann wann ein Signal an einem Eingang anliegt oder?

MFG BigBearRN

the_Ghost666
07.02.2009, 12:52
Der C32 sagt mir garnichts, es gibt nen C30, aber der ist eigentlich für die dsPICs und die PIC24er, wenn ich mich nicht täusche, wie kompatibel der ist weiß ich nicht, aber normalerweise PIC18-> C18

Das wäre eine Erklärung, denn wenn du der delay Funktion einen falschen Wert gibst, nimmt die sich vielleicht nur die Mantisse oder den Exponenten, dann kommt natürlich nur nonsens raus. Schau doch mal in die Anleitung zum Compiler, da müsste die Nutzung der Funktion doch beschrieben werden, sonst im Header-File über das du die Delay Geschichte eingebunden hast.
Warum der PIC Zahlen über 254 nicht schaffen sollte, ist mir schleiferhaft, der müsste dann doch einfach ne 2.55e002 draus machen. Zahlen über 255 müssen aus mehreren Bytes zusammengesetzt werden, aber das macht der Compiler für dich, wenn du das als INT deklarierst. Die Division dürfte auch keine Probleme machen, sonst ist der Compiler Müll.
Also wenn du nur PC-Programmierung gewöhnt bist: im Controller sind meist Zahlen etwas kleiner, weil die Ressourcen begrenzt sind, aber selbst INT dürfte keine Probleme mit 22 000 haben.
Der Simulator kann sehr wohl Eingänge simulieren, entweder aus ner Datei gelesen, wo drin steht, wann er was schalten soll, oder indem du Ports asynchron definierst, dann feuern die wenn du den Button drückst.

Für MPLAB: Unter Debugger MPLAB Sim wählen, dann kannst du durch Doppelklicken im Code rote Breakpoints setzen, bis dahin läuft er und stoppt dann erstmal bis du ihn weiterlaufen lässt. Unter Debugger dann auf Stimulus, New Workbook, jetzt bei PIN/SFR den Pin oder das Register auswählen, was du stimulieren möchtest, mit Action kannst du auswählen was passiert, wenn du den Knopf am Anfang der Zeile drückst, dauerhaft setzen, toggle für Umschalten und Pulse für eine begrenzte Zeit low oder high. Für Pulse musst d noch ne Zeit angeben. Abspeichern und den Code laufen lassen, (Run oder F9), dann den Fire-Button drücken und schauen was passiert. Probier mal eine einfache IF-Abfrage zu machen, die regelmäßig prüft, ob die Taste gedrückt ist, und mach in die Abfrage irgend eine Anweisung, auf die du einen Breakpoint setzt. Dann kannst du das wunderbar testen.
Du hast sogar einen LogicAnalyser, unter View, SimulatorLogic Analyser. Da einen Pin angeben (über Channel) und Trigger auf Now oder eine Programm-Counter stelle setzen. Laufen lassen und danach anschauen, was ausgegeben wurde.

PS.
Das kann so auch nicht hinhauen. Wenn du ne Frequenz von 1.23 eingibst, und das dann nach delay schreibst mit delay= 1.23*(1000/10) = 123, dann hast du doch keine Frequenz von 1,23Hz! 123µs Periodendauer entsprechen 8,13kHz!

TDK
07.02.2009, 13:07
Pah... hättest mal im JAVA unterricht aufgepasst XD
Int - 2 byte - 16 bit - wertbereich 65xxx - das is von - 32xxx bis +32xxx
wollt ich nur mal so erwähnen :-P
immer kompliziert arbeiten wenns auch einfach geht... (255 is im übrigen der wertebereich von byte^^ :-P)

the_Ghost666
07.02.2009, 14:24
Ging das an mich oder BigBearRN?

Nochmal zu deinem Code,
Du machst zwar so ne Berechnung in Delay, aber freq= 1/delay bringt garnichts, weil es nirgendwo genutzt wird und die Delay-Funktion nur mit dem Parameter Delay gestartet wird, wo dann eben deine 123 drinstehen.
Wenn du noch ein -> delay=1/delay einfügst, DANN hast du ne Periodendauer in delay stehen. Diese noch /2 wegen des Pegelwechsels und damit kannst du dann die Delay-Funktion beschicken. Aber wie gesagt, ich bezweifel, dass diese floats verarbeiten kann.

TDK
07.02.2009, 15:10
an bigbear natürlich^^

BigBearRN
10.02.2009, 13:37
Heii

Soo hab mich jetzt noch mal rengesetzt und siehe da es funzt :)

also mein projekt für jeden der sich dafür interessiert:
(ach ja, ihr braucht dafür ne PS/2 Tastatur ;) )

the_Ghost666
10.02.2009, 15:02
Moin ,habs mal gerade runtergeladen und festgestellt, dass ich den CCS nochmal installieren muss, deswegen findet er ein paar files nicht.
Aber ein gut gemeinter Rat, setzt dich noch diese Woche hin und kommentier den Quellcode. In 4 Wochen, weißt du selber nicht mehr, was da genau passiert ist und für mich ist es sehr schwer zu lesen was das genau bedeuten soll, vor allem solche Sachen: if(a[0]&&!a[1]&&a[2]&&a[3]&&!a[4]&&a[5]&&!a[6]&&a[7])
Da steh ich dann da und überlege erstmal, was das soll. Es sind wohl die kodierten Bits aus der Codes.txt gemeint oder? Selbstsprechende Variablen, bzw aussagekräftige Namen sind ein muss, das hast du ja auch bei frequ und co so durchgezogen.

BigBearRN
10.02.2009, 15:42
Ich weis ich bin da recht chaotisch ;)
aber ich überarbeite den Quelltext ja noch damit er übersichtlicher wird

MFG

the_Ghost666
10.02.2009, 15:59
Noch ein dringend gemeinter Rat: Du nutzt integer Variablen für Bit-Werte von nur zwei Zuständen. Damit hast du pro Element in dem Array 15 Bits verschenkt! Bool statt Int bringt etwas Vorteil, aber bool wird auch nur als Byte abgelegt. Besser ist, wenn du es in eine Binärzahl umrechnest und als Int nimmst, dann kann man es wenigstens lesen, und du brauchst nurnoch ein Int. Aber vor allem würden diese kryptischen if(a[0]&&!a[1]&&a[2]&&a[3]&&!a[4]&&a[5]&&!a[6]&&a[7]) verschwinden, dann könntest du einfach if(a == 3535) schreiben.
Weiterhin lohnt es sich bei deiner verzweigten Geschichte eine Switch-Anweisung zu nutzen, statt 5 If-Abfragen.
Und zu guter letzt: Nach wie vor benutzt man Goto in Hochsprachen eigentlich nicht. Das geht auch alles mit while und break bzw. exit.

BigBearRN
12.02.2009, 08:37
Danke für den Tipp

Das war von Anfang an meine Idee aber ich weis nicht, wie ich das machen kann.
Ich habe mir auch gedacht das einfach als bitfolge zu speichern und dann den Zahlenwert zu vergleichen..
Aber wie gesagt - ich weis nicht wie

Wäre dir dankbar falls du mir das zeigen könntest :)

MFG

BigBearRN
12.02.2009, 08:40
und ach ja
Mein PIC Board spinnt ein bisschen
Manchmal erkennt mein computer das Board nicht (Invalid target device id)
passt zwar nicht ganz zum thema aber weis jemand wie ich das problem lösen kann

MFG