Hi, wiedermal Probleme mit meiner Servosteuerung.... Das Unterprogramm void einstellung (.....) funktioniert ohne Probleme, auch die Übergabe der Werte im Hauptprogramm klappt reibungslos Einstellung(10000, 20000, 30,35 );//(printlcd("SYS XXX, DIA XX",1));(printlcd("T3 - Abbruch",2)); ABER: versuche ich gleichzeitig eine Ausgabe an das LCD Display(hier auskommentiert) ergibt sich folgendes Problem.... die Ausgabe funktioniert aber es wird kein PWM Signal mehr ausgegeben sondern der Ausgangspin geht im wechsel an und aus... die gekoppelte LED blinkt.... LCD Ausgabe weg... alles klappt... super PWM.... bin verzweifelt... :-D Grüße aus Heidelberg
Step Han schrieb: > Grüße aus Heidelberg und > #include <cbs5131.h> Sieht mal schwer nach Carl-Bosch-Schule Heidelberg aus. Sollen wir jetzt Deine Hausaufgaben oder Deine Projektarbeit machen? Ist das TGI oder BKI? > TMOD = 1; // Timer0 und Timer1 auf 16 Bit Passt nicht zusammen. Hier wird Timer 0 auf 16 Bit und Timer 1 auf 13 Bit gesetzt. Grundsätzlich sollte man keine Dezimalzahlen in Config-Register schreiben. Nur Hex oder Binär. (oder weisst Du wie nach TMOD = 146; die Timer laufen??) Wo ist in dem Programm eine Endlosschleife? Wieso wird nur einmal in timer_config das Timer-Flag abgefragt? Darüber hinaus bleibt man nicht mit while(TF0==0); stehen und wartet auf dem Timer. Da ist ja eine Warteschleife noch besser. Die PWM-Erzeugung geschieht auch nur einmalig in der "Einstellenirgendwasunverständliches()"-Funktion. Tip: geh' ab und zu mal in den Unterricht, lasse mittels Warteschleifen eine LED blinken. Dann änderst Du die Warteschleifen auf 1000us, 1500us, 2000us und 20ms ab und bastelst dir daraus das Servosignal zusammen. Wenn sich dann der Servo per Taster bewegen lässt kannst Du über Timer nachdenken (gleiche Reihenfolge, erst LED...). Zeichne Dir vorher ein Struktogramm, das du dann umsetzt - wenn Du damit Probleme hast, schau dir mal NSD10 an (z.B. von hier http://www.tinohempel.de/info/info/info-cd/nsd.zip). Das ist zwar Steinalt, kennt keine langen Dateinamen und ist nicht sehr hübsch, aber es kann aus einem Diagramm C-Code erzeugen (aber bitte den nicht weitercompilieren, sondern den relvanten Ablauf in Dein Projekt übernehmen).
du hast ja schmerzen..... erstens der servo läuft.... zweitens ist es total daneben hier jemanden anzugreifen.... drittens, ja es ist die cbs.... und deshalb könnte man darüber nachdenken das die medizintechnikerklassen wenig c-programmierung haben und deshlab mit ihren projekten zu kämpfen haben.... depp.... aus antworten von leuten wie dir kann man echt verzichten....
Step Han schrieb: > erstens der servo läuft.... Ich behaupte mal, der Servo läuft nur, weil der Controller mangels Endlosschleife immer wieder von vorne beginnt. > zweitens ist es total daneben hier jemanden anzugreifen.... Wieso angreifen? Dir fehlen rudimentäre Kenntnisse, wie ein Programm auf einem Mikrocontroller auszusehen hat. Ohne Endlosschleife wird das nix. > drittens, ja es ist die cbs.... und deshalb könnte man darüber > nachdenken das die medizintechnikerklassen wenig c-programmierung haben > und deshlab mit ihren projekten zu kämpfen haben.... Dann schau Dir die Grundlagen an, bevor Du mit umfangreicheren Projekten hantierst. > depp.... ?? > aus antworten von leuten wie dir kann man echt verzichten.... Wieso? Hast du jetzt mal endlich eine Endlosschleife eingebaut? Frägst Du das Timerflag korrekt ab, statt drauf zu warten? In meiner Antwort waren mindestens 3 zielführende Hinweise. Und wenn meine Schüler gar keine Ahnung haben, dann sage ich denen genau das gleiche. Man kann als Anfänger einen Servo auch mit Warteschleifen bedienen - man kann ja nicht alles am Anfang wissen. Aber grundsätzliche Kontrollstrukturen sollten in fehlerfreien Programmcode umgesetzt werden können.
.... ok vielleicht etwas überreagiert... sorry dafür.... ich weis nicht welche endlosschleifen gemeint sind.... jeder unterprogrammaufruf läuft doch in schleifen bis die bedingung nicht mehr erfüllt ist... das unterprogramm selber startet sich ja durch die if-schleifen immer wieder... TMOD = 1 heisst ganz eindeutig das das beide timer mit 16bit laufen, hab das heute vom it lehrer checken lassen... das problem waren die displayausgaben im hauptprogramm.... das klappt jetzt auch nachdem ich diese aus der while schleife rausgenommen habe... und ja, mir fehlen kenntnisse aber das liegt an der ausbildungsmethode der schule.... wir haben zum thema µc programmierung bei for-schleifen aufgehört und das was jetzt da steht hab ich mir selbst beigebracht... in anbetracht der zeit ist auch keine möglichkeit mehr da viel zu ändern weil der termin zur abgabe der technikerarbeit feststeht.... mein betreuer will das ich das ganze über eine interrupt programmierung realisiere aber das utopisch....
Step Han schrieb: > .... ok vielleicht etwas überreagiert... sorry dafür.... Dann bitte in Zukunft erst Dampf ablassen und nachdenken. > ich weis nicht welche endlosschleifen gemeint sind.... DIE Endlosschleife, die jedes Mikrocontrollerprogramm haben sollte. Im Gegensatz zum PC gibt es hier ja kein Betriebssystem, zu dem ein beendetes Programm zurückkehrt. Beim PC-Programmieren enden C-Programme oft mit return 0; Beim Controller gibt es das nicht. Der liest stur einen Befehl nach dem anderen aus dem EEPROM und wenn dann keine Schleife (Rücksprung) folgt, liest er den leeren Speicher (leere EEPROMs enthalten 0xFF, das ist beim 8051 der Op-Code für mov R7,A => er wird also endlos der Akku in R7 kopiert. Nach spätestens 65536 mov-Befehlen ist der Speicher aber zu Ende und der Programm-Counter läuft über. Dann fängt der Controller wieder bei der Adrese 0x0000 an, was praktisch dasselbe ist wie nach Reset... Ein C-Programm hat IMMMER folgendes Grundgerüst:
1 | /* Kommentar am Anfang */
|
2 | #include <registerdefinitionen.h> |
3 | |
4 | // globale Variablen und Deklarationen
|
5 | |
6 | // Funktionsprototypen, falls nicht in einer .H-Datei
|
7 | |
8 | void main (void) // davon darf es im Projekt nur genau eines geben |
9 | {
|
10 | // lokale Variablen für main()
|
11 | init_der_hardware( ); // das wird alles nur einmal ausgeführt! |
12 | |
13 | while(1) // Endlosschleife, manchmal sieht man auch for(;;) |
14 | {
|
15 | // wiederholt ausgeführte Befehle und Funktionsaufrufe.
|
16 | // kann auch mal leer sein, wenn alles mit Interrupts gemacht wird
|
17 | }
|
18 | }
|
19 | |
20 | // Funktionsdeklarationen, falls nicht in externe .C-Dateien ausgelagert
|
> jeder unterprogrammaufruf läuft doch in schleifen bis die bedingung > nicht mehr erfüllt ist... und nach der letzten Bedingung?? > durch die if-schleifen immer wieder... www.if-schleife.de !! > TMOD = 1 heisst ganz eindeutig das das beide timer mit 16bit laufen, hab > das heute vom it lehrer checken lassen... TMOD (wurde hoffentlich mal vorgestellt, ansonsten im 8051-Family-Datenblatt*** auf Seite 87) Bit7 Bit0 --------------------------------- | G |C/T| M1| M0| G |C/T| M1| M0| --------------------------------- Die Bits 0-3 sind für Timer0, Bits 4-7 für Timer 1 zuständig. 16-Bit-Mode ist Mode 1, also M1M0 = 01 Dezimal 1 ist 0b 0000 0001 => Auf welchem Wert sind damit die Bits M1M0 für den Timer 1????? > und ja, mir fehlen kenntnisse aber das liegt an der ausbildungsmethode > der schule.... wir haben zum thema µc programmierung bei for-schleifen > aufgehört leider etwas zu früh... > und das was jetzt da steht hab ich mir selbst beigebracht... > in anbetracht der zeit ist auch keine möglichkeit mehr da viel zu ändern > weil der termin zur abgabe der technikerarbeit feststeht.... Upps, als Technikerarbeit ist das mal recht spät im Jahr! > mein betreuer will das ich das ganze über eine interrupt programmierung > realisiere aber das utopisch.... Interrupt an sich ist gar nicht so tragisch, wenn der Rest erstmal läuft. Frage erstmal in der Endlosschleife das TF0-Flag ab. Jetzt ist der Timer übergelaufen. Also Flag löschen und danach entscheiden, was zu tun ist. Wenn der Servo-Ausgang gerade 0 ist, steht jetzt also der Impuls an. Also gewünscht Impulszeit laden und den Ausgang auf 1 setzen. Im 2.Fall ist der Ausgang noch auf 1, also Pausenzeit laden und den Ausgang löschen. Die Pausenzeit beim Servo ist unkritisch und kann auch konstant (alles zwischen 10 und 100ms wird von den meisten Servos geschluckt) sein. Vorschlag: Pause 18ms => 18000us => 18000MZ bei 12MHz Takt. Etwas umfangreichere Timer-Tips habe ich hier schonmal geschrieben, vielleicht klappt es ja damit: Beitrag "Re: Signal für eine gewisse Zeit setzen in C (8051)" *** Atmel hat alles allgemeine zu den 8051 in ein separates Dokument ausgegliedert. Daher stehen hier die Grundlagen drin, im Controller-Datenblatt dann die Spezialitäten des Derivats. http://www.atmel.com/Images/doc4316.pdf
Ich habe zu den Timern mal einen kurzen Artikel erstelle: http://www.mikrocontroller.net/articles/8051_Timer_0/1
Bernhard Spitzer schrieb: > Ich habe zu den Timern mal einen kurzen Artikel erstelle: > http://www.mikrocontroller.net/articles/8051_Timer_0/1 Kleine Anmerkung zur Reloadwert Berechnung in Assembler : Dort sollte man die Zeit für die INT Erkennung und den Jump zur ISR und auch die MOV Befehle zum Reload des Timers mit berücksichtigen. Sind zwar nur 9uS bei 12MHz, aber will mans genau haben ists schon sinnvoll.
Habe ich in dem Artikel ja auch geschrieben. Allerdings wollte ich erstmal die wichtigsten Grundlagen für Anfänger etwas aufzeigen ohne gleich mit allen Problemfeldern einzusteigen. Darüber hinaus wären bei 50ms Timerzeit die 9µs unter 0,02% Abweichung. Da liegt der 12Ct Quarz mit 100ppm in ähnlicher Größenordnung. Man kann ja aber auch in Assembler einfach mov TH0, #HIGH(65536-50000+9) mov TL0, #LOW(65536-50000+9) schreiben. Bei konstanten Werten rechnet ja der Compiler vorher. Wenn in C der Timer mit Interrupt verwendet wird, kann es ja auch noch sein, dass der Compiler diverse push-Befehle einfügt. Dann hilft einfach ausmessen der realen Zeit im Simulator und Korrektur der Reload-Werte. Hier können übrigens sehr interessante Effekte entstehen, weil der Interrupt ja keinen ASM-Befehl unterbrechen kann. Wenn die Hauptschleife eine ungünstige Anzahl an Maschinenbefehlen benötigt, dann haut der Interrupt unregelmäßig genau zwischen 2 Befehle oder er trifft auf einen Befehl der 2 oder 4 Maschinenzyklen braucht. Dadurch entsteht ein Jitter im erzeugten Timer-Signal, den man sich erstmal nicht erklären kann... Ein _nop_() in der Hauptschleife mehr und der Jitter ist eventuell komplett weg - oder noch schlimmer als vorher :-)
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.