www.mikrocontroller.net

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


Autor: AW (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Nils ‫‪ (n-regen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Taster prellt wahrscheinlich.
Siehe hier: http://www.mikrocontroller.net/articles/Entprellung

Autor: AW (Gast)
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ausserdem frage ich mich, wie du auf die Idee kommst, dass das hier
  unsigned int test = 0;

....
  while (test < 1)
  {
      test++;

....

    }

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

Autor: AW (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mit dieser Funktion, wollte ich sichergehen, dass er nur einmal den Takt 
herausgibt.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: AW (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: AW (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Jörg S. (joerg-s)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
PINB entspricht P2IN

1<<PINB2 entspricht 0x04

Autor: MRBI (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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;
  }
}

Autor: Jörg S. (joerg-s)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: MRBI (Gast)
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.
void entprellung (volatile const uint8_t *port, uint8_t maske)
....

Jetzt tut sie es.

Autor: MRBI (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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 :-)

Autor: MRBI (Gast)
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: MRBI (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab das Problem anders gelöst, funktioniert einwandfrei.

Autor: Walter W. (pridy)
Datum:

Bewertung
0 lesenswert
nicht 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ß :-)

Autor: martin_l (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Walter W. (pridy)
Datum:

Bewertung
0 lesenswert
nicht 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:
P1DIR |= 0x01;

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

soll es nun P1.6 sein, so muss ich die folgenden Zeilen verwenden:
P1DIR |= 0x40;
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:
#include "msp430f2101.h"

int main(void)
{
  WDTCTL = WDTPW + WDTHOLD;             // Stop watchdog timer
  P1DIR |= 0x01;                        // Set P1.0 to output direction
  P1DIR &= 0xF7;      // Set P1.3 to input direction

   while(1){
     //P1OUT ^= 0x01;                      // Toggle P1.0 using exclusive-OR
     if(P1IN == 1){
       P1OUT ^= 0x01;
     }
  }
}
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

Autor: Walter W. (pridy)
Datum:

Bewertung
0 lesenswert
nicht 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-t...
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 ^^

Autor: martin_l (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: martin_l (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
was man(n) nicht so alles schreibt....

Eso sollte eigentlich heissen:

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

=;o)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.