www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Interrupt/Pin-Abfrage beim ADUC831


Autor: bluefox (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Ich hab mir vor kurzem ein Übungsboard mit nem ADUC831 drauf zugelegt.

Nun möchte ich die 4 auf dem Board vorhandenen Tasten abfragen, in der 
Art: Wenn Taste 1 gedrückt ist, dann soll LED1 leuchten.

Laut Beschreibung kann man eine Taste z.B. mit taste=P1&0x0F in "einer 
Interruptfunktion" abfragen. Aber wie programmiert man das genau (in C) 
?

ich habe schon lange hier im Forum gesucht, bin aber leider noch nicht 
fündig geworden, was so ein simples (?) Problem betrifft :-)

Laut einem - nicht funktionierenden - Beispielprogramm von AnalogDevices 
sieht die InterruptRoutine so aus:
void tasten(void) interrupt 0
{ 
  flag1=1;
  //   0 1 1 1 1 0 0 0  Dekodierung für Tasten
  taste=(P2&0x78)>>3;
}
Doch wie erhalte ich daraus einen Wert im main-Programm bzw. wie lese 
ich einen bestimmten Tastenwert aus ??

Danke!
Lg
bluefox

Autor: B e r n d W. (smiley46)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo  bluefox

Leider konnte ich im Schaltplan die Tasten nicht finden. Wo sind die 
denn angeschlossen? Manche Ports der ADUCs haben keinen internen PullUp, 
die müssen dann selber verdrahtet werden. Da Port1 auch als AD-Eingang 
verwendet wird, könnten die hier auch fehlen.

Aus dem Datenblatt:
Port 1 is an 8-bit input port only. Unlike other ports, Port 1 defaults 
to Analog Input mode, to configure any of these Port Pins as a digital 
input, write a "0" to the port bit. Port 1 pins are multifunction and 
share the following functionality...
#include <stdio.h>
#include <aduc831.h>

#define TASTE1 1
#define TASTE2 2
#define TASTE3 4
#define TASTE4 8

int main()
{
char taste;

  while (1) 
  {
    taste = P1 & 0x0F;
    if (taste) 
    {
       switch (taste)
       {
          case TASTE1: funktion1();
                       break;
          case TASTE2: funktion2();
                       break;
          case TASTE3: funktion3();
                       break;
          case TASTE4: funktion4();
                       break;
       }
    }

    // Tu in der Zwischenzeit irgendwas
  }
  return 0;
}

Erst mal so probieren. Wenn das funktioniert, dann mit einem Timer 
Interrupt die Tasten abfragen und per globaler Variablen an main() 
übergeben.

Autor: bluefox (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die Hilfe!

Leider funktioniert mit dem Code aber gar nix :-(

Die Tasten hängen alle an den Port1-Pins (P10 bis P13), aber außerdem 
habe ich noch in der Beschreibung gelesen, dass alle Port1-Pins auf den 
"INT0" zusammengeführt sind (??).
Interessanterweise funktioniert der Zugriff auf INT0 zwar, also z.B.:
P2=INT0; //P2 sind die LEDs.

Es leuchtet aber so immer nur die unterste LED  (also binär 0001) beim 
Tastendruck, egal welche Taste ich drücke - sprich: INT0 ist anscheinend 
nur 1Bit breit.

:-((( Ich kenn mich nimmer aus.

Autor: B e r n d W. (smiley46)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab schon viel mit dem Vorgänger ADuC812 gemacht, welcher ja fast 
identisch ist. Der Interrupt 0 ist ein externer Interrupt (P3.2/INT0). 
Damit kann man aber ohne weiteren Aufwand nur eine Taste abfragen. Dazu 
muss auch zuvor der Interrupt eingeschaltet werden.
#include <stdio.h>
#include <aduc831.h>

#define TASTE1 1
#define TASTE2 2
#define TASTE3 4
#define TASTE4 8

char taste;  // globale Variable

void 
init_interrupts()
{
  EX0 = 1; // External interrupt enabled
  EA = 1;  // Interrupts enabled
}

void 
ext0_int(void) interrupt 0
{
  taste = P1 & 0x0F;
}

int
main()
{
  taste = 0;
  init_interrupts();

  while (1) 
  {
    if (taste)        // falls taste gedrückt
    {
       switch (taste)
       {
          case TASTE1: funktion1();
                       break;
          case TASTE2: funktion2();
                       break;
          case TASTE3: funktion3();
                       break;
          case TASTE4: funktion4();
                       break;
       }
       while(taste);  // warten bis Taste losgelassen
    }

    // Tu in der Zwischenzeit irgendwas
  }
  return 0;
}

Autor: B e r n d W. (smiley46)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Die Tasten hängen alle an den Port1-Pins (P10 bis P13)
>dass alle Port1-Pins auf den "INT0" zusammengeführt sind (??).
Wahrscheinlich gehen 4 Dioden von den Tasten zu INT0

>P2=INT0; //P2 sind die LEDs.

Mach mal P2 = P1&0x0F;

Geht jeweils die LED an, entsprechnd der Taste? Dann gibt es Pull Ups 
und die Taste zieht den Port auf Null. Das Programm ist umgekehert 
gedacht. Widerstände auf Masse und Tasten auf Plus.

Vielleicht gehts so:

#define TASTE1 0x0E
#define TASTE2 0x0D
#define TASTE3 0x0B
#define TASTE4 0x07

>Es leuchtet aber so immer nur die unterste LED  (also binär 0001) beim
Das stimmt, INT0 wird als Bit und nicht als Byte eingelesen.

PS.
Die Syntax des Interupts ist für den Keil Compiler. Das kann sich bei 
Dir etwas unterscheiden.

Autor: bluefox (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hm. Es will einfach nicht funktionieren.

Ich hab alles so reinprogrammiert, wie du es beschrieben hast, ich hab 
sogar noch einen default-Wert für die switch-Funktion hineingenommen.

Jedes Mal springt er aber direkt in diesen default-Wert, d.h. der 
Tastendruck wird gar nicht erkannt.

Hier mein Code:
#include <ADUC831.H>
#include <stdio.h>

#define TASTE1 1
#define TASTE2 2
#define TASTE3 4
#define TASTE4 8


unsigned char counter;
void ser_ini(void)
{/* Set up UART Baudrate = 9600; 11,059MHz*/
  T3CON = 0x085;  T3FD = 0x08;  SCON   = 0x052;

}

char taste;

void init_interrupts()
{
  EX0 = 1; // External interrupt enabled
  EA = 1;  // Interrupts enabled
}

void ext0_int(void) interrupt 0
{
  taste = P1 & 0x0F;
}

main()
{
ser_ini();


taste = 0;
init_interrupts();

  while (1) 
  {
    if (taste)        // falls taste gedrückt
    {
       switch (taste)
       {
          case TASTE1: P2=1;
                       waitms(1000);
                       break;
          case TASTE2: P2=2;
                       waitms(1000);
                       break;
          case TASTE3: P2=4;
                       waitms(1000);
                       break;
          case TASTE4: P2=8;
                       waitms(1000);
                       break;
          default:     P2=5;
                       waitms(1000);
                       break;
       }
       while(taste);  // warten bis Taste losgelassen
    }

    // Tu in der Zwischenzeit irgendwas
  }
}
 :-(

Autor: bluefox (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also
 P2 = P1&0x0F; 
 funzt gar nicht.

Und die andere Variante mit
#define TASTE1 0x0E
#define TASTE2 0x0D
#define TASTE3 0x0B
#define TASTE4 0x07
 funktioniert leider auch nicht - es wird auch hier immer nur der 
default-Wert vom switch aufgerufen.



P.S: ich habe auch den keil-compiler - das kann also kein fehler sein.

sorry für den Doppelpost...

Autor: B e r n d W. (smiley46)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Leider hab ich gerade keinen ADuC hier, um das nachzuvollziehen. Bei den 
externen Interrupts kann man noch einstellen, ob sie auf Flanke oder 
Zustand reagieren und hohe Priorität (PX0=1).

Vielleicht geht der Interrupt noch nicht. Kontrollier mal, ob er 
überhaupt reinspringt.

void ext0_int(void) interrupt 0
{
  taste = P1 & 0x0F;
  P2=5;
  waitms(1000);
}

Autor: bluefox (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
void ext0_int(void) interrupt 0
{
  taste = P1 & 0x0F;
  P2=5;
  waitms(1000);
}
 funktioniert, d.h.  anscheinend wird der Interrupt zwar erkannt, aber 
es wird noch immer in den default-Wert gesprungen. Demnach kann das Teil 
nicht zwischen den einzlnen Tasten unterscheiden (oder so ähnlich?) :-(

Autor: B e r n d W. (smiley46)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also der Interrupt geht, aber es kommt keine Taste an und

P2 = P1&0x0F;

Jetzt hab ichs entdeckt. Die Tasten sind an J14 - J17 angeschlossen. Die
Tasten ziehen die Spannung auf Null, aber die Schmitt Trigger
invertieren. Bei gedrückter Taste liegt eine 1 am Port an und eine 0 am
P3.2.

Also ist doch die alte Version richtig:

#define TASTE1 1
#define TASTE2 2
#define TASTE3 4
#define TASTE4 8

Vielleicht macht diese Zeile noch Probleme.
while(taste);  // warten bis Taste losgelassen
Könntest Du die einfach mal auskommentieren?

Autor: B e r n d W. (smiley46)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#include <ADUC831.H>
#include <stdio.h>

#define TASTE1 1
#define TASTE2 2
#define TASTE3 4
#define TASTE4 8

unsigned char counter;
unsigned char taste;

void ser_ini(void)
{/* Set up UART Baudrate = 9600; 11,059MHz*/
  T3CON = 0x085;  T3FD = 0x08;  SCON   = 0x052;
}

void init_interrupts()
{
  EX0 = 1; // External interrupt enabled
  EA = 1;  // Interrupts enabled
}

void ext0_int(void) interrupt 0
{
  taste = P1 & 0x0F;
}

main()
{
  taste = 0;
  ser_ini();
  init_interrupts();

  while (1) 
  {
    if (taste)        // falls taste gedrückt
    {
       P2 = taste;
       waitms(1000);
       P2 = 0xFF;
    }
  }
}

Autor: bluefox (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also ich hab beide Variante versucht (while(taste) auskommentieren und 
deinen neuen Quelltext), aber leider funktionierts nicht:

Bei
...
if (taste)        // falls taste gedrückt
    {
       P2 = taste;
       waitms(1000);
       P2 = 0xFF;
    }
...
werden nur die 4 unteren der 8 LEDs deaktiviert (also eben 0x0F), aber 
nach 1 Sekunde passiert gar nichts, der Befehl 0xFF wird also nicht 
ausgeführt (ist mir unerklärlich).


Mir ist immer noch nicht ganz klar, wie das Board zwischen den vier 
Tasten unterscheiden soll, wenn ja nur eine 1Bit-Leitung (INT0) 
verwendet wird.
In deinem Beispiel mit der switch-Anweisung ist es zwar ausprogrammiert, 
aber das will leider auch nicht funktionieren.

verzweifel

Autor: bluefox (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hab das programm mal dahin geändert:
#include <ADUC831.H>
#include "LCD_DOGM_SPI.h"
#include <stdio.h>

#define TASTE1 1
#define TASTE2 2
#define TASTE3 4
#define TASTE4 15 //HIER!!!

idata char buffer[17];
void ser_ini(void)
{/* Set up UART Baudrate = 9600; 11,059MHz*/
  T3CON = 0x085;  T3FD = 0x08;  SCON   = 0x052;

}

unsigned char taste;
bit flag;
unsigned char counter;

void init_interrupts()
{
  EX0 = 1; // External interrupt enabled
  EA = 1;  // Interrupts enabled
  IT0=1;
}

void ext0_int(void) interrupt 0
{
  taste = P1 & 0x0F;

}

main()
{
  ser_ini();
  taste=0;
  init_interrupts();  
  while (1) 
  {
  if (taste)        // falls taste gedrückt
    {
       switch (taste)
       {
          case TASTE1: P2=1;
                       waitms(1000);
                       break;
          case TASTE2: P2=2;
                       waitms(1000);
                       break;
          case TASTE3: P2=4;
                       waitms(1000);
                       break;
          case TASTE4: P2=8;
                       waitms(1000);
                       break;
          default:     P2=16;
                       waitms(1000);
                       break;
       }
  P2=0;
  taste=0;
    }

  }
}
,
also die Kodierung für "TASTE4" auf 15 geändert. Nun wird immer der case 
TASTE4 ausgeführt (LEDs auf 8binär) --> d.h. sobald ich irgendeine Taste 
drücke, werden ALLE 4 Pins vom Port1 auf 1 gezogen.
Wie soll man da zwischen den einzelne Tasten unterscheiden können, wenn 
eh immer der selbe Code (1111b) ausgegeben wird??

Autor: B e r n d W. (smiley46)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ob die Tasten am ADUC ankommen, lässt sich einfach mit einem Multimeter 
überprüfen oder mit einer LED von GND auf den entsprechenden Pin. Bei 
gedrückter Taste müsste eine 1 ankommen.

Es könnte doch noch was damit zu tun haben:

Port 1 is an 8-bit input port only. Unlike other ports, Port 1 defaults
to Analog Input mode, to configure any of these Port Pins as a digital
input, write a "0" to the port bit.

main()
{
  ser_ini();
  taste=0;
  P1 = 0xF0;  // Bit 0 to 3 as digital input
  init_interrupts();
  .
  .
  .

Das ist eine Besonderheit, die es so bei anderen 51ern nicht gibt.

Autor: bluefox (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
P1 = 0xF0;

Das wars!!!! Du bist genial!! Lang lebe BerndW. :-)

Autor: bluefox (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kannst du mir noch bei nem anderen Problem bei diesem µC helfen?:

Ich möchte gern ein Signal (eine Gleichspannung) nach außen abgeben. Mit 
welchen Pins kann ich das am einfachsten machen? (P1.0 bis P1.3 ist ja 
für die Taster reserviert und P2 für die LEDs) - und wie mache ich das?

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.