Forum: Mikrocontroller und Digitale Elektronik MSP430 parallele Impulszählung mehrere Ports


von Rene (Gast)


Lesenswert?

Ich möchte Impulse (je ca. 20-50ms) zählen.
Impulsgeber sind mehrere Geräte (8), die unabhängig voneinander ihre 
Impulse abgeben, also auch mal parallel oder sehr kurz voneinander 
versetzt.
Meine Idee war es, z.B. an den Ports 1.1 bis 1.7 die Impulse zu 
empfangen und über Interrupt zu erfassen.
Der Interrupt für den Port 1 wird aber für den gesamten Port, also alle 
8 Leitungen abgerufen. Wenn also an Port 1 ein Impuls eintrifft, wird er 
aufgerufen. Die einzelnen Pins müßte ich dann in der Interruptroutine 
abfragen. Dann zähle ich aber mitunter Signale doppelt, da ich nicht 
weiß welcher Port den Interrupt ausgelöst hat.
Hat jemand eine Lösung?

von Karl H. (kbuchegg)


Lesenswert?

Rene schrieb:

> Meine Idee war es, z.B. an den Ports 1.1 bis 1.7 die Impulse zu
> empfangen und über Interrupt zu erfassen.
> Der Interrupt für den Port 1 wird aber für den gesamten Port, also alle
> 8 Leitungen abgerufen. Wenn also an Port 1 ein Impuls eintrifft, wird er
> aufgerufen. Die einzelnen Pins müßte ich dann in der Interruptroutine
> abfragen. Dann zähle ich aber mitunter Signale doppelt, da ich nicht
> weiß welcher Port den Interrupt ausgelöst hat.
> Hat jemand eine Lösung?

Zum einen erhebt sich die Frage, warum das unbedingt Interrupts sein 
müssen. 20-50ms sind für einen µC eine lange Zeit. Das würde auch mit 
Polling (also regelmässigem Nachsehen) genauso gut gehen.

Zum anderen: Na du kannst ja vergleichen, wie der Zustand des Portes 
beim letzten Interrupt war. Du merkst dir einfach den kompletten 
Portzustand und beim nächsten Interrupt vergleichst du mit dem dann 
vorliegenden Portzustand. Alle Bits die verändert sind, zeigen an, dass 
sich da was getan hat. Und dann merkst du dir genau diesen Portzustand 
für den wiedrrum nächsten Aufruf der ISR. Du musst natürlich ALLE 
Flanken am Port mitkriegen, nicht nur die steigenden Flanken.
(Hinweis: die XOR Operation kann man in so einem Fall tadellos 
einsetzen)

-> d.h. dein Interrupt bringt dir im Grunde jetzt gar nichts mehr, 
sofern dein Restprogramm nicht trödelt. Denn um das vergleichen mit dem 
vorhergehenden Portzustand kommst du eh nicht rum. Und das kannst du 
genausogut in der Hauptschleife auch machen.

von Rene (Gast)


Lesenswert?

Ich möchte die Anzahl der gezählten Impulse pro PIN extern 
kommunizieren. Ob ich den MSP430 dazu abfrage, oder dieser in 
definierten Zeitabständen die Anzahl übermittelt ist noch offen.

Die Idee des merken des Zustands ist fraglich, da die Impulse auch mal 5 
Minuten nicht auftreten. Kommt also nur an P1.1 ein Signal 
hintereinander, dann sehe ich das im Interrupt nicht durch eine 
Zustandsänderung - beim Polling ja.
Insofern gebe ich dir recht.

von Karl H. (kbuchegg)


Lesenswert?

Rene schrieb:

> Die Idee des merken des Zustands ist fraglich

Nö. Die ist nicht fraglich.
Das ist die Art und Weise, wie man das macht.

> da die Impulse auch mal 5
> Minuten nicht auftreten.

Und?

> Kommt also nur an P1.1 ein Signal
> hintereinander, dann sehe ich das im Interrupt nicht durch eine
> Zustandsänderung

Natürlich siehst du es. Du musst auf ALLE Flanken den Interrupt 
reagieren lassen, nicht nur die steigenden!
Bei JEDER Änderung an dein Eingangspins (von 0 auf 1, von 1 auf 0) muss 
dein Interrupt ausgelöst werden.

Und der Rest ist einfach nur ein Bytevergleich auf Bitebene
1
uint8_t oldState;
2
3
4
ISR( .... )
5
{
6
  uint8_t newState = kompletter Port einlesen;
7
8
  uint8_t changed = newState ^ oldState;
9
10
  // in changed ist an allen Bitpositionen eine 1, an der sich
11
  // der jetzige Zustand vom Port (newState) vom vorhergehenden
12
  // Zustand (oldState) unterscheidet
13
14
  // durch Untersuchung der Bits in changed, zusammen mit der
15
  // Information in newState kann man feststellen, ob und welcher
16
  // Pin gerade seinen Wechsel von 0 auf 1 gemacht hat
17
18
  if( (changed & 0x01)  && (newState & 0x01) )
19
    // Pin 0 hat von 0 auf 1 gewechselt
20
21
  if( (changed & 0x02)  && (newState & 0x02) )
22
    // Pin 1 hat von 0 auf 1 gewechselt
23
24
  if( (changed & 0x04) && (newState & 0x04) )
25
    // Pin 2 hat von 0 auf 1 gewechsel
26
27
  ....
28
29
30
  oldState = newState;
31
}

von Erstaunt (Gast)


Lesenswert?

@KHB
Was ist los, du gibst die Lösung vor? Wie sol er jetzt was lernen? ;-)

von Rene (Gast)


Lesenswert?

habe darüber sehr gut gelernt. Danke!

von Josef (Gast)


Lesenswert?

Es gibt auch das P1IFG Register. Darin wird ein Bit fuer den Pin
gesetzt, der den Interrupt ausgeloest hat.
Das Bit sollte per SW in der ISR zurueckgesetzt werden.

Gruss
Josef

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.