Forum: Mikrocontroller und Digitale Elektronik AT89C5131, Displayausgabe, Servosteuerung


von Step H. (step_h)


Angehängte Dateien:

Lesenswert?

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

von Bernhard S. (b_spitzer)


Lesenswert?

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).

von Step H. (step_h)


Lesenswert?

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....

von Bernhard S. (b_spitzer)


Lesenswert?

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.

von Step H. (step_h)


Lesenswert?

.... 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....

von Bernhard S. (b_spitzer)


Lesenswert?

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

von Bernhard S. (b_spitzer)


Lesenswert?

Ich habe zu den Timern mal einen kurzen Artikel erstelle:
http://www.mikrocontroller.net/articles/8051_Timer_0/1

von Manuel X. (vophatec)


Lesenswert?

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.

von Bernhard S. (b_spitzer)


Lesenswert?

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