Forum: Mikrocontroller und Digitale Elektronik MSP430 1.Takt per Taster an LED


von AW (Gast)


Lesenswert?

Hallo zusammen,
möchte über einen Taster einer LED einen einzigen Takt für bestimmte 
Zeit geben. Habe folgendes programmiert:

void main(void)
{
  unsigned int i;
  unsigned int test = 0;

  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
  P1DIR = 0x00;
  P2DIR |= 0x02;                            // P5.1 output

  _BIS_SR(GIE);                             //  w/ interrupt
  TACCR0 = 33;
  TACTL = TASSEL_1 + MC_2 + ID_0;           // ACLK, contmode,Vorteiler 
0

  do
  {
  if (P1IN == 0x01)
  {
    for(i=0; i <= 1024 ; i++);

  while (test < 1)
  {
      test++;
      TAR = 0x0000;
      P2OUT = 0x02;
      TACCTL0 = CCIE;                             // CCR0 interrupt 
enabled
    }
  }
  } while(1);
}

// Timer A0 interrupt service routine
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A_0 (void)
{
  P2OUT = 0x00;                            // OFF P5.1
  TACCTL0 = 0x0000;                             // CCR0 interrupt 
disabled
  TAR = 0x0000;
}



Kann mir jemand helfen, bekomme da nicht nur einen Takt, sondern 
mehrere.

von Nils ‫. (n-regen)


Lesenswert?

Der Taster prellt wahrscheinlich.
Siehe hier: http://www.mikrocontroller.net/articles/Entprellung

von AW (Gast)


Lesenswert?

ja, aber mit dieser for-schleife  for(i=0; i <= 1024 ; i++)
wartet er bestimmte zeit und macht es dann weiter.

von Karl H. (kbuchegg)


Lesenswert?

Und was glaubst du, was jeder Compiler, der nach 1945 entstanden ist, 
mit dem hier

    for(i=0; i <= 1024 ; i++);

machen wird, wenn er optimieren darf?
Diese Schleife bewritk überhaupt nichts, ausser Zeit zu verbrauchen. 
Nobelste Aufgabe jedes Compilers ist es, für den Programmierer 
Codestellen zu finden und umzugestelten, so dass das Programm schneller 
läuft.

von Karl H. (kbuchegg)


Lesenswert?

Ausserdem frage ich mich, wie du auf die Idee kommst, dass das hier
1
  unsigned int test = 0;
2
3
....
4
  while (test < 1)
5
  {
6
      test++;
7
8
....
9
10
    }

auf das von dir (meiner Meinung nach) geforderte Verhalten führen soll.

von AW (Gast)


Lesenswert?

Mit dieser Funktion, wollte ich sichergehen, dass er nur einmal den Takt 
herausgibt.

von Karl H. (kbuchegg)


Lesenswert?

1) Was genau verstehst du unter 'Takt'?

   ein einziges mal (*)
   oder einen Prozessortakt

2) ein unsigned besitzt per Definition kein Vorzeichen, ist also
   immer positiv.
   Wie kann eine Variable, die per Definition immer positiv ist,
   auf kleiner 0 getestet werden? Dazu müsste sie negativ werden
   können, was sie aber laut Definition nicht kann.


(*) wohl dieses hier.
Aber das wird so nichts.
Du versuchst schon wieder mit ungeeigneten Mitteln eine 
Tastenentprellung und Flankenerkennung zu vermeiden.

von AW (Gast)


Lesenswert?

1) ja, ich will nur einen einzigen Takt für bestimmte Zeit an die LED 
geben.
2) ich überprüfe doch gar nicht ob es kleiner null ist.

von Karl H. (kbuchegg)


Lesenswert?

AW schrieb:
> 1) ja, ich will nur einen einzigen Takt für bestimmte Zeit an die LED
> geben.
> 2) ich überprüfe doch gar nicht ob es kleiner null ist.



mein Fehler. Ich hab < 0 gelesen, wo < 1 steht.

Entschuldigung.


Trotzdem ist der ganze Ansatz für die Katz.
Denn du prüfst ja nirgends ob die Taste schon losgelassen wurde. Beim 
nächsten Durchlauf durch die äussere Schleife, ist ja die Taste unter 
Umständen immer noch gedrückt und damit wird dann der nächste Puls 
generiert (bei dem test dann allerdings nicht mehr so schnell kleiner 1 
ist).

Dein Programm macht also das hier
* generiere ein Taktsignal SOLANGE eine Taste gedrückt ist.
  Bleibst du eine halbe Stunde mit dem Finger auf der Taste, werden auch
  eine halbe Stunde lang Takte generiert.

von AW (Gast)


Lesenswert?

Was ist bei diesem Enprellungsmuster PINB und PINB2?

Warteschleifenvariante mit Maske und Pointer (nach Christian Riggenbach)

entprellung( &PINB, (1<<PINB2) );    // ggf. Prellen abwarten
  if( PINB & (1<<PINB2) )           // dann stabilen Wert einlesen
  {
    // mach was
  }
  else
  {
    // mach was anderes
  }

http://www.mikrocontroller.net/articles/Entprellung

von Jörg S. (joerg-s)


Lesenswert?

PINB entspricht P2IN

1<<PINB2 entspricht 0x04

von MRBI (Gast)


Lesenswert?

Brauche Hilfe, kann mir jemand sagen wo ich hier Fehler habe?
Also genauer gesagt, habe ich an der stelle  entprellung ( &P1IN , ( 1 
<< 0x01)); einen Fehler.


void entprellung (volatile uint8_t *port, uint8_t maske);

void main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
  P1DIR = 0x01;                             // P1.0 Taster
  P2DIR |= 0x02;                            // P2.1 output
  unsigned int PIN1 = 0x01;
  _BIS_SR(GIE);                             // Enter LPM3 w/ interrupt
  TACCR0 = 100;
  TACTL = TASSEL_1 + MC_2 + ID_0;           // ACLK, contmode,Vorteiler 
0

  do
  {
  entprellung ( &P1IN , ( 1 << 0x01)); // ggf. Prellen abwarten
  if( P1IN & ( 1 << 0x01))           // dann stabilen Wert einlesen
  {
    // mach was
    TAR = 0x0000;
    P2OUT = 0x02;
    TACCTL0 = CCIE;                             // CCR0 interrupt 
enabled
  }
  else
  {
    // mach was anderes
  }
  } while(1);
}

// Timer A0 interrupt service routine
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A_0 (void)
{
  P2OUT = 0x00;                            // OFF P5.1
  TACCTL0 = 0x0000;                             // CCR0 interrupt 
disabled
  TAR = 0x0000;
}


void entprellung (volatile uint8_t *port, uint8_t maske)
{
  unsigned int   port_puffer;
  unsigned int   entprellungs_puffer;

  for( entprellungs_puffer=0 ; entprellungs_puffer!=0xff ; )
  {
    entprellungs_puffer<<=1;
    port_puffer = *port;
    _delay_us(150);
    if( (*port & maske) == (port_puffer & maske) )
      entprellungs_puffer |= 0x01;
  }
}

von Jörg S. (joerg-s)


Lesenswert?

MRBI schrieb:
> Brauche Hilfe, kann mir jemand sagen wo ich hier Fehler habe?
> Also genauer gesagt, habe ich an der stelle  entprellung ( &P1IN , ( 1
> << 0x01)); einen Fehler.
Wie äussert sich denn der Fehler?

von MRBI (Gast)


Lesenswert?

Error[Pe167]: argument of type "unsigned char const volatile *" is 
incompatible with parameter of type "uint8_t volatile *"

von Karl H. (kbuchegg)


Lesenswert?

Das "const" ist der Unterschied.

P1IN ist offenbar so definiert, dass man seinen Wert vom Programm aus 
nicht ändern kann. Macht auch Sinn.

Nur: die Funktion entprellung macht an den Aufrufer nicht die 
Zusicherung, dass sie das nicht versuchen wird.
1
void entprellung (volatile const uint8_t *port, uint8_t maske)
2
....

Jetzt tut sie es.

von MRBI (Gast)


Lesenswert?

Gut das Problem hat sich gelöst mit "const". Danke.

Aber irgendwie funktioniert das Programm trotzdem nicht.

Wenn ich den Taster mit der Portnummer P1.0 benutzte und LED mit der 
Portnummer P2.1. Muss ich in der Entprellfunktion auch was anpassen?

Möchte eine LED für bestimmte Zeit nach einem Tastendruck mit 
Entprellfunktion anmachen.

        _
       |   |
_______|   |___________________________________________ Taster P1.0
            ________________
           |                  |
___________|<-------t-------->|________________________ LED P2.1

von Karl H. (kbuchegg)


Lesenswert?

MRBI schrieb:

> Möchte eine LED für bestimmte Zeit nach einem Tastendruck mit
> Entprellfunktion anmachen.

Entprellung ist die eine Sache.
Aber dein Programm wartet immer noch nicht darauf, dass die Taste auch 
wieder losgelassen wird!

>
>         ___
>        |   |
> _______|   |___________________________________________ Taster P1.0
>             __________________
>            |                  |
> ___________|<-------t-------->|________________________ LED P2.1


Aus deiner Grafik geht jetzt hervor:
Die Zeit soll erst mit dem Loslassen des Tasters laufen :-)

von MRBI (Gast)


Lesenswert?

Die Zeit soll laufen (LED AN), wenn man den Taster betätigt hat.
Wo ist denn der Fehler in meinem Code?

von Karl H. (kbuchegg)


Lesenswert?

MRBI schrieb:

> Wo ist denn der Fehler in meinem Code?


Ich glaub ich schreibe es jetzt zum 3.ten mal:

Dein Code wartet nicht darauf, dass die Taste auch wieder losgelassen 
wird!
Ist die Zeit abgelaufen UND ist die Taste noch immer gedrückt, dann 
beginnt sofort der nächste Takt zu laufen, weil

  if( P1IN & ( 1 << 0x01))           // dann stabilen Wert einlesen

dann immer noch wahr ist.

von MRBI (Gast)


Lesenswert?

Hab das Problem anders gelöst, funktioniert einwandfrei.

von Walter W. (pridy)


Lesenswert?

Hallo,

ich hab da mal eine recht grundlegende Frage zum MSP430.
Ist es möglich einen Port für In- und Output zu verwenden?
Beispielsweise P1.3 einen Taster und P1.0 eine LED (so ist es auch auf 
dem Board MSP430LaunchPad bei der Lieferung aufgebaut)

[Oder muss man für Input P1 und für Ouput P2 verwenden, also 
verschiedene Ports verwenden?
Ich würde gerne innerhalb des selben Ports 1 zwei Pins verwenden: In- 
und Output]


Ist anscheinend eine zu grundlegende Frage um gefunden zu werden, habe 
gegoogelt, hier gesucht und das Datenblatt durchsucht.

Wäre cool, wenn das jemand weiß :-)

von martin_l (Gast)


Lesenswert?

Hallo Walter,

du kannst mit dem PxDIR Register des MSP die einzelnen Pins eines Ports 
als Input bzw. Output konfigurieren.

Schau mal im Family Users Guide zum entsprechenden Controller nach. Dort 
gibt es bestimmt das Kapitel Digital I/O.

und uns allen einen schönen Tag
=;o) martin

von Walter W. (pridy)


Lesenswert?

Hi,

ja das Kapitel Digital I/O habe ich gelesen. Irgendwie hat mir aber die 
Erleuchtung gefehlt - Danke für den Anstupser in die Richtung, habe es 
nochmal gelesen und so langsam hat es gedämmert..

hiermit sage ich, dass P1.0 als Ausgang (Direction) dienen soll:
1
P1DIR |= 0x01;

hiermit toggle ich das Bit mit einer EX-OR Verknüpfung, war im Beispiel 
enthalten:
1
P1OUT ^= 0x01;

soll es nun P1.6 sein, so muss ich die folgenden Zeilen verwenden:
1
P1DIR |= 0x40;
2
P1OUT ^= 0x40;
weil 0x40 entspricht 0100 0000, also das siebte Bit ==> P1.6


so weit so gut....
nun wollte ich meine erste kleine Übung machen, und zwar mit einem 
Taster eine LED beeinflussen, nur funktioniert es nicht so recht.
versucht habe ich es hiermit, klappt aber nicht:
1
#include "msp430f2101.h"
2
3
int main(void)
4
{
5
  WDTCTL = WDTPW + WDTHOLD;             // Stop watchdog timer
6
  P1DIR |= 0x01;                        // Set P1.0 to output direction
7
  P1DIR &= 0xF7;      // Set P1.3 to input direction
8
9
   while(1){
10
     //P1OUT ^= 0x01;                      // Toggle P1.0 using exclusive-OR
11
     if(P1IN == 1){
12
       P1OUT ^= 0x01;
13
     }
14
  }
15
}
hier wollte ich P1.3 als Eingang verwenden.
also 0xF7 entspricht 1111 0111, damit lösche ich das vierte Bit (also 
P1.3 auf 0)
was mache ich falsch?


ach ja, einen schönen Tag wünsche ich auch :D

von Walter W. (pridy)


Lesenswert?

...hm naja kleines Update:
die Idee im Beitrag vorher habe ich zwar immer noch nicht hinbekommen. 
Aber wie immer gibt es mehrere Lösungswege. Ein anderer Lösungsweg ist 
wohl den Taster einen Interrupt auslösen zu lassen und in der Interrupt 
Service Routine den Ausgangs-Pin (LED) zu togglen.

das habe ich hier gefunden:
http://www.egarante.net/2010/09/msp430-launchpad-tutorial-part-1-basics.html
ein echt gutes Einstiegstutorial :-)

falls trotzdem jemand eine Idee oder einen Hinweis zum Beitrag vorher 
hat, bin ich sehr gespannt - möchte alles erfahren über die Steuerung ^^

von martin_l (Gast)


Lesenswert?

aller Anfang ist schwer, aber sieht doch schon nicht schlecht aus.

Für die Lösung des Rätsels, hier ein kleiner Denkanstoß (Anstupser)
-> Wo genau fragst du ab, ob P1.3 "High" also wirklich das Bit3?

Man kann die I/O Bestimmung in diesem Falle auch in eine Zeile 
schreiben, also

   P1DIR = 0xF7;

aber es schadet nicht, |= und &= Schreibweise zu nutzen.

Weiterhin viel Spaß beim Programmieren, und es stimmt, ich werde jetzt 
mal schauen, ob der Weg zur Arbeit "Schneefrei"

Viele Grüße
martin

von martin_l (Gast)


Lesenswert?

was man(n) nicht so alles schreibt....

Eso sollte eigentlich heissen:

... und es stimmt, es gibt meistens mehrere Lösungswege!

=;o)

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.