Forum: Mikrocontroller und Digitale Elektronik 8051: AT89C51ED2 -Keyboard-Interface


von R. B. (rabis)


Angehängte Dateien:

Lesenswert?

Hi,

ich habe offensichtlich ein Verständnisproblem mit dem 
keyboard-interface des AT89C51ED2. Es ist eine einfache 2x3 
Tastaturmatrix angeschlossen.
Das Atmel-Testprogramm erkennt keine Taste, da kein Interrupt ausgelöst 
wird.
Woran kann das liegen? Den SPI-Bus benutze ich auch, später, wenn die 
Tasten
erkannt werden...
Verschiedene KBE, KBLS Registerkombinationen habe ich schon probiert...

Danke für etl. Tipps

RABIS
1
// SDCC
2
#include <AT89C51ED2.h>
3
// ...
4
5
unsigned int keypressed;         /* key pressed value */
6
__bit volatile key_flag;         /* software flag */
7
8
void  main()
9
{
10
   EA=1;                         /* enable interrupts */
11
                                 /* init keyboard */
12
   KBE=0xFF;                     /*Enable all P1 I/O as keyboard IO */
13
   KBF=0x00;                     /* Clear all keyboard flags */
14
   IEN1 |=0x01;                  /* Enable keyboard interupt */
15
16
while(1)                         /* endless */
17
{
18
   if (key_flag)                 /* keyboard occur */
19
   {
20
      printf_fast("keypressed: %x\r\n",keypressed);
21
      key_flag=0;                /* reset softaware flag */
22
      }
23
   }
24
}
25
26
/**
27
* FUNCTION_PURPOSE:keyboard_interrupt. Save pressed key
28
* FUNCTION_INPUTS:void
29
* FUNCTION_OUTPUTS:void
30
*/
31
void keyboard_interrupt() interrupt 7 using 1
32
{
33
keypressed=KBF;                  /* save pressed key */
34
key_flag=1;                      /* set the software flag */
35
KBF=0x00;                        /* clear keyboard flags */ 
36
}

von Peter D. (peda)


Lesenswert?

R. B. schrieb:
> Das Atmel-Testprogramm erkennt keine Taste, da kein Interrupt ausgelöst
> wird.

Da hatter auch recht, High auf High ergibt keine Änderung.
Du müßtest erstmal P1.0 - P1.2 auf Low setzen.
Erst dann ändern sich beim Drücken P1.3 oder P1.4.


Peter

von R. B. (rabis)


Lesenswert?

@ Peter
Bis jetzt habe ich P1.3 und P1.4 auf low gesetzt und R1 und R2 
weggelassen.
Dann werden zumindest alle Tasten (doppelt) erkannt.
Danke vorerst, Deinen Tipp werde ich heute ausprobieren.
Atmel-Support ggrrrhhh.

RABIS

von Peter D. (peda)


Lesenswert?

R. B. schrieb:
> Dann werden zumindest alle Tasten (doppelt) erkannt.

Willkommen in der realen Welt der Mechanik, Taster prellen nunmal.
Deshalb nimmt man den Keyboard-Interrupt nur zum Aufwachen aus dem 
Powerdown.
Das Einlesen und Entprellen macht man dann in der üblichen Weise mit dem 
Timerinterrupt.


R. B. schrieb:
> Atmel-Support ggrrrhhh.

Der Support wird Dir kaum beim Programmieren lernen helfen.
Er ist für konkrete Probleme mit dem Chip zuständig, z.B. wenn Du einen 
Bugreport hast.


Peter

von Peter D. (peda)


Lesenswert?

R. B. schrieb:
> Bis jetzt habe ich P1.3 und P1.4 auf low gesetzt und R1 und R2
> weggelassen.

Wie rum, ist egal.
Ich hatte nur andersrum geschrieben, damit die 2 Pullups nicht nutzlos 
sind.


Peter

von R. B. (rabis)


Lesenswert?

Hier mal ne gute Beschreibung, die ich gefunden habe:

http://mikrocontroller.rahm-home.de/docfiles/Uebungen/4_7_6_Matrixtastatur_mit_Interrupt.pdf

Ich bin davon ausgegangen, dass die Keyboard-Steuerung im AT89C51ED2 
"intelligent" ist und Entprellung, Dekodierung und Multiplex übernimmt. 
Zu der Annahme hat mich die Application Note ANM071 für den TSC80251G1 
von Atmel verleitet.

Die "normale" Keyboardmatrix hatte ich schon.

Gruß
RABIS

von Peter D. (peda)


Lesenswert?

R. B. schrieb:
> Ich bin davon ausgegangen, dass die Keyboard-Steuerung im AT89C51ED2
> "intelligent" ist und Entprellung, Dekodierung und Multiplex übernimmt.
> Zu der Annahme hat mich die Application Note ANM071 für den TSC80251G1
> von Atmel verleitet.

Nö, da steht doch:
"In the demonstration software, timer 1 is used to manage the debounce 
delay."

Ein stupides Warten ist allerdings kein sehr zuverlässiges Entprellen, 
wird aber leider oft so gemacht.


Peter

von R. B. (rabis)


Angehängte Dateien:

Lesenswert?

So, hier nun meine (abschließende) Lösung:
keyboard.c
1
//-----------------------------------------------------------------------------
2
#ifndef __KEYBOARD
3
 #define __KEYBOARD
4
 #include <stdio.h>
5
 #include <serial_IO.h>
6
 #include ".\keyboard.h" 
7
//----------------------------------------------------------------------------- 
8
9
volatile __bit key_flag;     // software flag 
10
unsigned  char Keycode;
11
12
//-----------------------------------------------------------------------------
13
void Keyboard_Init(void) {
14
  P1    = #0b00000111;       // Spaltenleitungen = 0, Zeilenleitungen = 1
15
  KBLS  = #0b00000000;       // L-Pegel für Auslösung Keyboardinterrupt
16
  KBE   = #0b00000111;       // Tastatur Zeileninterrupts freigeben
17
  IEN1 |= KBD;   
18
}
19
20
//-----------------------------------------------------------------------------
21
//
22
// main
23
//
24
//-----------------------------------------------------------------------------
25
void main(void) {
26
 
27
#if (X2Mode == 1)
28
  CKCON0 = 0x01;             // X2  Mode
29
  CKCON1 = 0x01;             // SPI clock = Xtal/12
30
#else
31
  CKCON0 = 0x00;             // STD Mode
32
  CKCON1 = 0x00;             // SPI clock = Xtal/12           
33
#endif
34
35
  key_flag  = 0;
36
  Keyboard_Init();
37
  EA = 1;  
38
  
39
  inituart((unsigned int) \
40
          (256-((Xtal/Baud)*(X2Mode+1)/192)));     // Timer 1
41
  printf_fast("\r\n\-- Keyboard V 0.01 -- \r\n>");
42
  
43
  while(1){
44
    if (key_flag) {
45
      printf_fast("Keycode: %x\r\n",Keycode);
46
      key_flag  = 0;
47
    }     
48
  }         
49
} 
50
51
//-----------------------------------------------------------------------------
52
#endif
53
//-----------------------------------------------------------------------------

keyboard.h
1
//-----------------------------------------------------------------------------
2
3
#ifndef __AT89C51ED2
4
 #define __AT89C51ED2
5
 #include "D:\SDCC_include\AT89C51ED2.h"
6
 #define Xtal          22118400  
7
 #define X2Mode        1
8
#endif
9
 
10
//-----------------------------------------------------------------------------         
11
12
#define EEPROM        0x0000            // chip internal EEPROM
13
#define EEPROMSIZE    2048
14
#define XRAM          0x0000            // chip internal XRAM
15
#define XRAMSIZE      1792
16
#define Baud          38400
17
18
//-----------------------------------------------------------------------------
19
20
#ifdef __KEYBOARD
21
  extern void ISR_KBD (void) __interrupt KBD_VECTOR __using 1 __naked ;
22
#endif

und die isr.c
1
//-----------------------------------------------------------------------------
2
#include ".\keyboard.h"
3
//-----------------------------------------------------------------------------
4
//
5
// Function: Interrupt service routines
6
//
7
8
void ISR_Int0    (void) __interrupt IE0_VECTOR  __using 0 { EA = 0 ;}
9
void ISR_Timer0  (void) __interrupt TF0_VECTOR  __using 0 { EA = 0 ;}
10
void ISR_Int1    (void) __interrupt IE1_VECTOR  __using 0 { EA = 0 ;}
11
void ISR_Timer1  (void) __interrupt TF1_VECTOR  __using 0 { EA = 0 ;}
12
void ISR_Timer2  (void) __interrupt TF2_VECTOR  __using 0 { EA = 0 ;}
13
void ISR_UART    (void) __interrupt SI0_VECTOR  __using 0 { EA = 0 ;}
14
void ISR_PCA     (void) __interrupt PCA_VECTOR  __using 0 { EA = 0 ;}
15
void ISR_KBD     (void) __interrupt KBD_VECTOR  __using 1 ; 
16
void ISR_SPI     (void) __interrupt SPI_VECTOR  __using 0 { EA = 0 ;}
17
18
//----------------------------------------------------------------------------- 
19
20
extern volatile __bit key_flag;       // software flag 
21
extern unsigned char  Keycode;
22
       unsigned char  Spalte;
23
24
//-----------------------------------------------------------------------------
25
26
void ISR_KBD (void) __interrupt KBD_VECTOR __using 1 __naked {
27
  __asm
28
       push    acc
29
       push    psw
30
       mov     psw, #0x08       
31
       mov    _KBE, #0b00000000
32
       mov       a, _KBF
33
       jb    acc.0, 00001$            // Zeile 1
34
       jb    acc.1, 00002$            // Zeile 2
35
       jb    acc.2, 00003$            // Zeile 3             
36
00001$:                               // Zeile 1
37
       mov      P1, #0b11111110
38
       mov    _Keycode, #0x02
39
       sjmp   00004$                   
40
00002$:                               // Zeile 2
41
       mov      P1, #0b11111101
42
       mov    _Keycode, #0x04
43
       sjmp   00004$       
44
00003$:                               // Zeile 3
45
       mov      P1, #0b11111011
46
       mov    _Keycode, #0x06
47
       sjmp   00004$       
48
00004$:                               // FertigZeile
49
       acall  00005$   
50
       sjmp   00008$
51
00005$:                               // Spaltentest
52
       mov    a, P1
53
       cpl    a
54
       anl    a, #0b00011000
55
       swap   a
56
       mov    _Spalte,#0x01
57
       clr    c       
58
00006$:                               // Next Spalte                              
59
       rlc    a
60
       jc     00007$
61
       dec    _Keycode
62
       djnz   _Spalte,00006$       
63
00007$:                               // Break
64
       ret 
65
00008$:                               // Finished
66
       mov      P1, #0b00000111
67
       mov    _KBF, #0b00000000
68
       mov    _KBE, #0b00000111
69
       setb   _key_flag
70
       pop    psw
71
       pop    acc
72
       reti                       
73
  __endasm;
74
}
75
//-----------------------------------------------------------------------------

Viel Spaß allen!

RABIS

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.