Forum: Mikrocontroller und Digitale Elektronik Timer 2 Signale


von Frank (Gast)


Lesenswert?

Hallo!!

Vielleicht kann mir ja jemand weiterhelfen. Benutze einen C8051F020 
meine
Frequenz läuft auf 24 Mhz.

So ich möchte mit einem Timer folgendes machen:

Bei meinem 1. Extennen Interrupt positive Flanke möchte ich den Timer 
starte ( Signal 1)

Bein meinem 2. Externen Interrupt an einem anderen Pin möchte ich bei 
postiver Flanke den Timer stoppen.

Diese Zeit die dort Vergangen ist möchte ich gerne ausgeben über UART.
( Die ausgabe über UART funktioniert geht mir hier nur um den timer)


der 1. _interrupt(0) void External0IntHandler (void){

soll den timer zum laufen Bringen.

kann ich das einfach machen indem ich den TR1=1 setze?

beim > _interrupt(2) void External1IntHandler (void){

soll der Timer gestoppt werden und die Werte gespeichert werden.

also so :
unsigned int wert1,wert2;
TR1=0;
wert1=TL1;
wert2=TH1;

geht es so vielleicht?

von Peter D. (peda)


Lesenswert?

Frank wrote:

> geht es so vielleicht?

Ja.


Peter

von Frank (Gast)


Lesenswert?

hört sich ja schomal gut an das es so funktioniert ;-)

und wie kann ich den wert dann ausgeben? muss ich da was beachten. 
Arbeite mit EDE TASKING.

von Joe (Gast)


Lesenswert?

>> unsigned int wert1,wert2;
>> TR1=0;
>> wert1=TL1;
>> wert2=TH1;

Kannst hier unsigned char verwenden denn TH1, TL1 sind je 8 BIT und 
bilden gemeinsam z.B. einen 16 BIT Timerwert:
1
uint16_t TimerVal;
2
3
TimerVal = TH0 << 8 | TL0;

Solltest du also diese Betriebsart verwenden (16 BIT) Timer dann mußt du 
den Integer Wert noch Stelle für Stelle nach ASCII umcodieren und kannst 
diesen dann ausgeben.

von Frank (Gast)


Lesenswert?

>> unsigned int wert1,wert2;
>> TR1=0;
>> wert1=TL1;
>> wert2=TH1;


also muss ich das gar nicht so schreiben sondern brauche ich nur dieses 
zu schreibe:

uint16_t TimerVal;

TimerVal = TH0 << 8 | TL0;

und jetzt habe ich im TimerVAl meinen gemessenen Wert stehen?

von Frank (Gast)


Lesenswert?

sorry war ne blöde frage ;-)

also timer arbeitet jetzt mit Interrupt und gibt auch den Wert im 
HyperTerminal aus.

habe aber nun folgendes Problem. mache eine PrintF ausgabe des TimeVal.
auf den beiden Pins die die Interrupts auslösen liegt jeweils ein 40kHz 
signal.kann es sein das das zu schnell ist? wenn ich ein signal auf 50Hz 
setzte gibt er mir schön immer den Wert im Terminal aus sobal das signal 
von der Frequenz her größer wird bekomme ich keine ausgabe mehr im 
Terminal der bleibt komplet stehen.


kann mir da jemand helfen. sind die 40khz zu schnell? und deswegen 
bleibt der HyperTerminal stehen ?

von Karl H. (kbuchegg)


Lesenswert?

Frank wrote:

> kann mir da jemand helfen. sind die 40khz zu schnell? und deswegen
> bleibt der HyperTerminal stehen ?

HyperTerminal bleibt mit Sicherheit nicht stehen.
Aber du hast mit Sicherheit einen Fehler im Programm, der
dafür sorgt, dass ab irgendeiner Frequenz keine Ausgabe
mehr erzeugt wird.
Dein Programm schickt nichts mehr weg -> HyperTerminal
zeigt daher auch nichts mehr an.

Dein Fehler liegt in Zeile 42
(Soll heissen: Ohne Programmtext kann dir auch keiner
helfen den Fehler zu suchen)

von Frank (Gast)


Lesenswert?

Habe aber mit dem Oszilloskop nach gesehen ob der Hyperterminal noch 
sendet das hat was angezeigt. obwohl er auf dem PC nicht mehr weiter 
angezeigt hat. und wenn ich die signale weggenommen habe ist das Signal 
am pin vom hyperterminal auch verschwunden. Was du meinst ist dann das 
ab einer gewissen Frequenz meine UART verückt spielt.

Was dann auf einen Programmierfehler der UART zurückzuführen ist?

von Power (Gast)


Lesenswert?

Mal 'ne andere Frage: benutzt du einen USB<=>Seriell-Adapter? Damit 
können solche Effekte auftreteten. Wenn möglich teste es mal mit einer 
onboard-RS232.

von Simon K. (simon) Benutzerseite


Lesenswert?

Frank wrote:
> Habe aber mit dem Oszilloskop nach gesehen ob der Hyperterminal noch
> sendet das hat was angezeigt. obwohl er auf dem PC nicht mehr weiter
> angezeigt hat. und wenn ich die signale weggenommen habe ist das Signal
> am pin vom hyperterminal auch verschwunden. Was du meinst ist dann das
> ab einer gewissen Frequenz meine UART verückt spielt.
>
> Was dann auf einen Programmierfehler der UART zurückzuführen ist?

Ähem, du weißt schon, dass lokal eingegebene Zeichen NICHT in dem 
unteren Teil angezeigt werden?! (Außer du stellst das lokale Echo ein, 
aber das vermute ich jetzt mal nicht)

von Frank (Gast)


Lesenswert?

Mein Prozessor ist ein C8051F020 Taktfrequenz auf 22Mhz.
den Timer habe ich auf 16 bit mit sysclock /12 Eingestellt.

Werde dann mal den Programmteil rein setzen. Denk mal es liegt dan 
wirklich an der UART.

Danke schonmal

klappt aber immerhin immer mehr mein Programm ;-))))

von Joe (Gast)


Lesenswert?

Das Programm zu sehen ist immer hilfreich ;-))

Wichtig wäre zu wissen wie deine UART Ausgabe aufgebaut ist (ebenfalls 
Interrupt oder Polling ? Interruptprioritäten ?). Über "printf" würde 
ich auch noch mal nachdenken, ganz schöner overhead für ne Integer 
Ausgabe, schau mal unter den Stichwörtern Modulo sowie ITOA nach. Nen 
kleiner Mehrzeiler könnte dein "printf" locker ersetzen.

Das Timing deiner Signale würde mich ebenso interessieren, kann der 
Timer überlaufen ? wann wird der Timer zurückgesetzt ? Wieviel Zeit 
steht für die Ausgabe zur Verfügung ?

von Frank (Gast)


Lesenswert?

Zu den Signalen kann ich dir schonmal sagen das, das der Timer auf 
jedenfall unter 25µs ist. Der rest müsste sich aus dem Programm ergeben. 
ich versuch es mal rein zu setzen.

von Joe (Gast)


Lesenswert?

Wie meinst du das ?

>> das der Timer auf jedenfall unter 25µs ist

Signal 1, Timer startet, 25µs später Signal 2 und Timer stoppt ? und 
dann ? in welcher Zeit findet das Ganze wieder statt.

Wieviel Zeit hast du für die Ausgabe ? Baudrate ? z.B. setze mal z.B. 
9600 Baud in Beziehung zur Zeit die du zur Verfügung hast.

von Frank (Gast)


Lesenswert?

ja genau so siehts aus kann auch sein das es kürzer wird als 25µs ich 
glaube ich weiss wodran es liegt. kann es sein das es sich um einen Race 
handelt? also das befor der 1. Wert angezeigt werden kann schon der 
nächste kommt?

von Joe (Gast)


Lesenswert?

!!in welcher Zeit findet das Ganze wieder statt??

Leider hast du meine Frage nicht beantwortet daher sag ich mal ja ;-))

von frank (Gast)


Lesenswert?

ja habe gemertk das das ganze sofort wieder stattfindet. also könnte ich 
doch mal versuchen z.B. durch ne while schleife in der main nicht jede 
messung auszugeben sonder nur alle 50 z.b.? j

von Joe (Gast)


Lesenswert?

>> durch ne while schleife in der main nicht jede messung auszugeben

Was soll das werden ? heiteres code erraten ? Bis jetzt kenne ich immer 
noch nicht deinen Konstrukt geschweige das du irgendetwas zu >deiner< 
Problemlösung beiträgst.

Wenn deine Messung im Interrupt läuft dann wirst du wohl nach erfolgter 
Messung deinen Interrupt mal abschalten müssen, dann Ausgabe des 
Meßwertes, und Interrupt wieder an. Ohne genaue Kenntnis der Abläufe 
kann man aber nur schwer einen Rat geben.

Obwohl ich deine Fragen in 2 Threads lese gibtst du leider nicht die 
Informationen die man braucht um dir zu helfen.

Schonmal über die anderen Tips nachgedacht ? wozu printf ? kostet auch 
Zeit und Code.

Ansonsten:

http://www.progforum.com/showthread.php?t=7571

Gruß,

Joe Semmel ;-))

von frank (Gast)


Angehängte Dateien:

Lesenswert?

So hier mal der Code hoffe mir kann jemand weiterhelfen. also bis 100Hz 
funktioniert die Ausgabe mit Printf aber wenn die Frequenz höher ist 
nicht mehr dann bleibt das Terminal Fenster stehen. Die Variablen A und 
Z habe ich nur eingefügt damit ich sehe ob der timer arbeitet.

von Joe (Gast)


Lesenswert?

Aus meiner Sicht machst du schon auf Hardwareebene einen Fehler, später 
mehr dazu.
1
_interrupt(2) void External1IntHandler (void){
2
  
3
  EA = 0;                                  //Interrupts sperren     
4
  TR0 =0;
5
  Z++; 
6
  TimerVal = TH0 << 8 | TL0;
7
  LED = 0;
8
  TL0=0x00;
9
  TH0=0x00;
10
  printf("\n\rTimerwert: %u",TimerVal);
11
  EA = 1;
12
}

Pack mal die Ausgabe in die 2te ISR und disable weitere Interrupts, 
hierdurch gehen zwar Messungen verloren allerdings sollte die gültige 
Messung sauber in die Ausgabe passen.

Main anpassen!!

Die elegantere Lösung wäre ein RS FlipFlop, für nen paar Cent baust du 
dir ein RS FlipFLop, der erste Impuls steuert SET, der 2te RESET. Am 
Ausgang des FF erhältst du ein sauberes Signal.
     ___
    |     |
----      --------

Die steigende Flanke läßt den Timer loslaufen, die neg. Flanke löst den 
Interrupt aus (Timer Torzeitsteuerung, siehe Datenblatt). Ein Timer 
reicht für die Ganze Messaufgabe, die Messung ist präzise, Ausgabe und 
dann Messung wiederholen.

Das wäre aus meiner Sicht der richtige Ansatz.

von Joe (Gast)


Lesenswert?

Noch mal zum Verständnis, die Impulslänge am Ausgang des FF entspricht 
somit genau der Differenz der beiden Signale.

Alles klar ?

In Main dann nur noch nen while (1);

von Frank (Gast)


Lesenswert?

Danke dir. was meinst du nochmal genau mit main anpassen? das printf 
rausnehmen ? werde das morgen mal ausprobieren. ist ein gutes Forum 
hier.

Der ansatz mit dem Flip Flop hört sich noch viel besser an. aber ich 
schaue mal ob ich von der genauigkeit vieleicht auch so hinkomme.
ansonsten werde ich es mal ausprobieren.

DAnke nochmal super Forum hier

von frank (Gast)


Lesenswert?

Tja macht aber genau daselbe wenn ich das so mache wie vorher. noch nen 
tip? kann ich die werte zwischenspeichern im array und dann ausgeben?

von Joe (Gast)


Lesenswert?

Irgendwie ist es schwer dir zu helfen, leider sagst du nie genau was 
ist.

Mach doch mal folgendes, schmeiß mal alle deine Interrupts raus und dann 
frag doch einfach den PIN ab und starte bzw. stop den Timer.
1
  if (meinEingangEins) TR0 = 1;
2
  if (meinEingangZwei) TR0 = 0;
3
  printf("\n\rTimerwert: %u",TimerVal);

So, was bezeichnest du als 100 Hz ? Du hast einen Timer als 16 BIT 
Zähler. Bei einer Frequenz von 22,1184 MHz / 12 = 1,843200 MHz.

Wenn deine Signale nun exakt 1µSec. auseinanderliegen würden dann wäre 
das Ergebnis 1 bzw. bei 10 µSec. 18, bei 100µSec. 184 usw. Bei ca. 100 
gehts dann nicht mehr ?

Bedenke, ich habe nicht deine Hardware auf meinem Tisch, sei mal nen 
bischen kreativ.

von frank (Gast)


Lesenswert?

glaub wir reden aneinander vorbei. Also habe auf dem einen pin ein 
signal liegen das 40khz hat und meinen timer starten soll auf dem 
anderen pin der meinen timer stoppen soll kann ich max mal ein signal 
mit 100hz anlegen bis mein hyper terminal keine ausgabe mehr macht. wenn 
ich über 100 Hz signal anlege dann hält mein Hyper terminal sofort an 
mit der Ausgabe. müsste aber 40khz anlegen können weil mein eigentliches 
Signal was ich an diesen pin anlegen will ja 40khz hat aber halt 
phasenverschoben ist.

also zum Verständniss nochmal.

pin 1 = 40khz Signal
pin 2 = 40khz Signal phasenverschoben

keine Ausgabe im Hyperterminal


pin 1=40kHz Signal

pin 2 = unter 100´Hz

timer funktioniert so wie er soll mit Ausgabe im Hyperterminal.

von frank (Gast)


Angehängte Dateien:

Lesenswert?

Hallo ich bins nochmal. Also ich habe jetzt mein Programm mal trastisch 
reduziert um den Fehler zu finden warum es anhält im HTerminal. Habe 
beide Interrupts rausgemacht und einfach mal einen Timer 2 definiert der 
einfach eine Variable hochzählt im HTerminal. Dann habe ich mein 1. 
40khz signal auf meinen /INT0 gelegt alles noch ok jetzt das 2. Signal 
40kHz an meinen /INT1 und das hyperterminal fenster hält an.



Wie kann das sein? ich mache ja noch nichts mit den Signalen? die werden 
ja nur angelegt und sonst passiert ja nicht damit.



Im Configuration Wizart sind die INT1 und INT0 über den XBR1 = 0x14; 
belegt.



Also mein  Timer wird angehalten sobald ich an den INT1 mein Signal lege 
warum?



habe mein verändertes Programm mal dran gehängt. aber wie gesagt ist nur 
ein timer der ne Variable hochzählt und ausgibt sonst nicht wenn ich den 
XBR1 einfach weglasse läuft alles.



Bitte um Hilfe oder kennt jemand das Problem?

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.