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


von bluefox (Gast)


Angehängte Dateien:

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:
1
void tasten(void) interrupt 0
2
{ 
3
  flag1=1;
4
  //   0 1 1 1 1 0 0 0  Dekodierung für Tasten
5
  taste=(P2&0x78)>>3;
6
}
Doch wie erhalte ich daraus einen Wert im main-Programm bzw. wie lese 
ich einen bestimmten Tastenwert aus ??

Danke!
Lg
bluefox

von B e r n d W. (smiley46)


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...
1
#include <stdio.h>
2
#include <aduc831.h>
3
4
#define TASTE1 1
5
#define TASTE2 2
6
#define TASTE3 4
7
#define TASTE4 8
8
9
int main()
10
{
11
char taste;
12
13
  while (1) 
14
  {
15
    taste = P1 & 0x0F;
16
    if (taste) 
17
    {
18
       switch (taste)
19
       {
20
          case TASTE1: funktion1();
21
                       break;
22
          case TASTE2: funktion2();
23
                       break;
24
          case TASTE3: funktion3();
25
                       break;
26
          case TASTE4: funktion4();
27
                       break;
28
       }
29
    }
30
31
    // Tu in der Zwischenzeit irgendwas
32
  }
33
  return 0;
34
}

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

von bluefox (Gast)


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.:
1
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.

von B e r n d W. (smiley46)


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.
1
#include <stdio.h>
2
#include <aduc831.h>
3
4
#define TASTE1 1
5
#define TASTE2 2
6
#define TASTE3 4
7
#define TASTE4 8
8
9
char taste;  // globale Variable
10
11
void 
12
init_interrupts()
13
{
14
  EX0 = 1; // External interrupt enabled
15
  EA = 1;  // Interrupts enabled
16
}
17
18
void 
19
ext0_int(void) interrupt 0
20
{
21
  taste = P1 & 0x0F;
22
}
23
24
int
25
main()
26
{
27
  taste = 0;
28
  init_interrupts();
29
30
  while (1) 
31
  {
32
    if (taste)        // falls taste gedrückt
33
    {
34
       switch (taste)
35
       {
36
          case TASTE1: funktion1();
37
                       break;
38
          case TASTE2: funktion2();
39
                       break;
40
          case TASTE3: funktion3();
41
                       break;
42
          case TASTE4: funktion4();
43
                       break;
44
       }
45
       while(taste);  // warten bis Taste losgelassen
46
    }
47
48
    // Tu in der Zwischenzeit irgendwas
49
  }
50
  return 0;
51
}

von B e r n d W. (smiley46)


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.

von bluefox (Gast)


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:
1
#include <ADUC831.H>
2
#include <stdio.h>
3
4
#define TASTE1 1
5
#define TASTE2 2
6
#define TASTE3 4
7
#define TASTE4 8
8
9
10
unsigned char counter;
11
void ser_ini(void)
12
{/* Set up UART Baudrate = 9600; 11,059MHz*/
13
  T3CON = 0x085;  T3FD = 0x08;  SCON   = 0x052;
14
15
}
16
17
char taste;
18
19
void init_interrupts()
20
{
21
  EX0 = 1; // External interrupt enabled
22
  EA = 1;  // Interrupts enabled
23
}
24
25
void ext0_int(void) interrupt 0
26
{
27
  taste = P1 & 0x0F;
28
}
29
30
main()
31
{
32
ser_ini();
33
34
35
taste = 0;
36
init_interrupts();
37
38
  while (1) 
39
  {
40
    if (taste)        // falls taste gedrückt
41
    {
42
       switch (taste)
43
       {
44
          case TASTE1: P2=1;
45
                       waitms(1000);
46
                       break;
47
          case TASTE2: P2=2;
48
                       waitms(1000);
49
                       break;
50
          case TASTE3: P2=4;
51
                       waitms(1000);
52
                       break;
53
          case TASTE4: P2=8;
54
                       waitms(1000);
55
                       break;
56
          default:     P2=5;
57
                       waitms(1000);
58
                       break;
59
       }
60
       while(taste);  // warten bis Taste losgelassen
61
    }
62
63
    // Tu in der Zwischenzeit irgendwas
64
  }
65
}
 :-(

von bluefox (Gast)


Lesenswert?

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

Und die andere Variante mit
1
#define TASTE1 0x0E
2
#define TASTE2 0x0D
3
#define TASTE3 0x0B
4
#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...

von B e r n d W. (smiley46)


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);
}

von bluefox (Gast)


Lesenswert?

1
void ext0_int(void) interrupt 0
2
{
3
  taste = P1 & 0x0F;
4
  P2=5;
5
  waitms(1000);
6
}
 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?) :-(

von B e r n d W. (smiley46)


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?

von B e r n d W. (smiley46)


Lesenswert?

1
#include <ADUC831.H>
2
#include <stdio.h>
3
4
#define TASTE1 1
5
#define TASTE2 2
6
#define TASTE3 4
7
#define TASTE4 8
8
9
unsigned char counter;
10
unsigned char taste;
11
12
void ser_ini(void)
13
{/* Set up UART Baudrate = 9600; 11,059MHz*/
14
  T3CON = 0x085;  T3FD = 0x08;  SCON   = 0x052;
15
}
16
17
void init_interrupts()
18
{
19
  EX0 = 1; // External interrupt enabled
20
  EA = 1;  // Interrupts enabled
21
}
22
23
void ext0_int(void) interrupt 0
24
{
25
  taste = P1 & 0x0F;
26
}
27
28
main()
29
{
30
  taste = 0;
31
  ser_ini();
32
  init_interrupts();
33
34
  while (1) 
35
  {
36
    if (taste)        // falls taste gedrückt
37
    {
38
       P2 = taste;
39
       waitms(1000);
40
       P2 = 0xFF;
41
    }
42
  }
43
}

von bluefox (Gast)


Lesenswert?

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

Bei
1
...
2
if (taste)        // falls taste gedrückt
3
    {
4
       P2 = taste;
5
       waitms(1000);
6
       P2 = 0xFF;
7
    }
8
...
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

von bluefox (Gast)


Lesenswert?

hab das programm mal dahin geändert:
1
#include <ADUC831.H>
2
#include "LCD_DOGM_SPI.h"
3
#include <stdio.h>
4
5
#define TASTE1 1
6
#define TASTE2 2
7
#define TASTE3 4
8
#define TASTE4 15 //HIER!!!
9
10
idata char buffer[17];
11
void ser_ini(void)
12
{/* Set up UART Baudrate = 9600; 11,059MHz*/
13
  T3CON = 0x085;  T3FD = 0x08;  SCON   = 0x052;
14
15
}
16
17
unsigned char taste;
18
bit flag;
19
unsigned char counter;
20
21
void init_interrupts()
22
{
23
  EX0 = 1; // External interrupt enabled
24
  EA = 1;  // Interrupts enabled
25
  IT0=1;
26
}
27
28
void ext0_int(void) interrupt 0
29
{
30
  taste = P1 & 0x0F;
31
32
}
33
34
main()
35
{
36
  ser_ini();
37
  taste=0;
38
  init_interrupts();  
39
  while (1) 
40
  {
41
  if (taste)        // falls taste gedrückt
42
    {
43
       switch (taste)
44
       {
45
          case TASTE1: P2=1;
46
                       waitms(1000);
47
                       break;
48
          case TASTE2: P2=2;
49
                       waitms(1000);
50
                       break;
51
          case TASTE3: P2=4;
52
                       waitms(1000);
53
                       break;
54
          case TASTE4: P2=8;
55
                       waitms(1000);
56
                       break;
57
          default:     P2=16;
58
                       waitms(1000);
59
                       break;
60
       }
61
  P2=0;
62
  taste=0;
63
    }
64
65
  }
66
}
,
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??

von B e r n d W. (smiley46)


Angehängte Dateien:

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.

von bluefox (Gast)


Lesenswert?

1
P1 = 0xF0;

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

von bluefox (Gast)


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?

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.