Maticová klávesnice a beeper

Seznámení se s principem maticové klávesnice a piezoelektrického akustického měniče.
Řešené příklady
Zadání
Příklad 1
zobrazujte na LCD právě zmáčknutou klávesu na maticové klávesnici.

Příklad 2
Vytvořte simulaci přístupového systému, kdy je nutno zadat 4 místný PIN a poté bude na LCD zobrazena zpráva zda je přístup povolen, nebo zamítnut.

Nápověda

Zapojení maticové klávesnice

schema-maticova_kl.png

Piny ID0 až ID3 jsou výstupní piny a ID4 až ID7 jsou vstupní piny mikrokontroléru. Čtení probíhá po sloupcích. Příklad čtení tlačítka BTN1 - na výstupní piny nastavíme 0111, tzn. že při zmáčknutém BTN1 se potenciál logické nuly přivede na pin ID4, na ostatních pinech čteme logickou 1. Podobně se postupuje pro ostatní sloupce.

Čtení z maticové klávesnice

////////////////////////Zacatek cteni

tlacitka=255;

old_ddr=DDRB; //zaloha nastaveni DDR

_delay_us(cas);
setb(DDRB,0); // vystupy
setb(DDRB,1);
setb(DDRB,2);
setb(DDRB,3);

clrb(DDRB,4); // vstupy
clrb(DDRB,5);
clrb(DDRB,6);
clrb(DDRB,7);


PORTB=0b00001110;

// 1 sloupec

_delay_us(cas);

if bit_is_clear(PINB,4) tlacitka=1;
if bit_is_clear(PINB,5) tlacitka=4;
if bit_is_clear(PINB,6) tlacitka=7;
if bit_is_clear(PINB,7) tlacitka=100; // #

// 2 sloupec
PORTB=0b00001101;

_delay_us(cas);

if bit_is_clear(PINB,4) tlacitka=2;
if bit_is_clear(PINB,5) tlacitka=5;
if bit_is_clear(PINB,6) tlacitka=8;
if bit_is_clear(PINB,7) tlacitka=0;

// 3 sloupec
PORTB=0b00001011;

_delay_us(cas);


if bit_is_clear(PINB,4) tlacitka=3;
if bit_is_clear(PINB,5) tlacitka=6;
if bit_is_clear(PINB,6) tlacitka=9;
if bit_is_clear(PINB,7) tlacitka=101; // *


// 4 sloupec
PORTB=0b00000111;

_delay_us(cas);


if bit_is_clear(PINB,4) tlacitka=11; //F1
if bit_is_clear(PINB,5) tlacitka=12; //F2
if bit_is_clear(PINB,6) tlacitka=13; //F3
if bit_is_clear(PINB,7) tlacitka=14; //F4

PORTB=0b00001111; // nectu

DDRB=old_ddr; //zaloha nastaveni DDR
/// konec cteni

Funkce pro pípnutí:
void pip(int ton) 
{
    // priklad:
    // ton=1000
    setb(DDRD,5);
    int i;
            for (i=0;i<300;i++) 
                {
                negb(PORTD,5);
                _delay_us(ton);             
                }
}

Řešení

Příklad 1
#define F_CPU 14745600UL 

#include <avr/io.h>
#include <string.h>
#include <stdio.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "knihovnaLCD.c"


//*******************************************************************************************
// UPRAVY
//-------------------------------------------------------------------------------------------
//
#define setb(port,pin)    port |= 1<<pin    //nastav bit
#define clrb(port,pin)    port &= ~(1<<pin) //nuluj bit
#define negb(port,pin)    port ^= 1<<pin    //neguj bit

//***********************************************************************************


unsigned int cas=10;
unsigned char tlacitka=255;
char tmp [20];
int i;
unsigned char old_ddr;




int main(void)
{


//////////////////////////////////////////////////////////////////////////////////
DDRD=0xFF; // vystupní - Ledky
DDRC=0x00; // vstupní  - Tlacitka



///// LCD INIT

    LCD_Init();
    LCD_Clear();
    _delay_ms(2);
         

while (1)
      {
////////////////////////Zacatek cteni
tlacitka=255;
old_ddr=DDRB; //zaloha nastaveni DDR


_delay_us(cas);
setb(DDRB,0); // vystupy
setb(DDRB,1);
setb(DDRB,2);
setb(DDRB,3);

clrb(DDRB,4); // vstupy
clrb(DDRB,5);
clrb(DDRB,6);
clrb(DDRB,7);

PORTB=0b00001110;

// 1 sloupec

_delay_us(cas);

if bit_is_clear(PINB,4) tlacitka=1;
if bit_is_clear(PINB,5) tlacitka=4;
if bit_is_clear(PINB,6) tlacitka=7;
if bit_is_clear(PINB,7) tlacitka=100; // #


// 2 sloupec
PORTB=0b00001101;

_delay_us(cas);

if bit_is_clear(PINB,4) tlacitka=2;
if bit_is_clear(PINB,5) tlacitka=5;
if bit_is_clear(PINB,6) tlacitka=8;
if bit_is_clear(PINB,7) tlacitka=0;

// 3 sloupec
PORTB=0b00001011;

_delay_us(cas);


if bit_is_clear(PINB,4) tlacitka=3;
if bit_is_clear(PINB,5) tlacitka=6;
if bit_is_clear(PINB,6) tlacitka=9;
if bit_is_clear(PINB,7) tlacitka=101; // *

// 4 sloupec
PORTB=0b00000111;

_delay_us(cas);


if bit_is_clear(PINB,4) tlacitka=11; //F1
if bit_is_clear(PINB,5) tlacitka=12; //F2
if bit_is_clear(PINB,6) tlacitka=13; //F3
if bit_is_clear(PINB,7) tlacitka=14; //F4

PORTB=0b00001111; // nectu

DDRB=old_ddr; //zaloha nastaveni DDR

/// konec cteni
///////////////////////////////////////////////////////

// Vypis
LCD_Position(0 , 0);
LCD_WriteString("Ukazka cteni MK ");
LCD_Position(1 , 0);
sprintf(tmp,"Tlacitka = %3d", tlacitka);
LCD_WriteString(tmp);

      }
}

Příklad 2
#define F_CPU 14745600UL 

#include <avr/io.h>
#include <string.h>
#include <stdio.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "knihovnaLCD.c"

//*******************************************************************************************
// UPRAVY
//-------------------------------------------------------------------------------------------
//
#define setb(port,pin)    port |= 1<<pin    //nastav bit
#define clrb(port,pin)    port &= ~(1<<pin) //nuluj bit
#define negb(port,pin)    port ^= 1<<pin    //neguj bit

//***********************************************************************************
unsigned int cas=10;
unsigned char tlacitka_new=255;
unsigned char tlacitka=255;
char tmp [20];
char znak=0;
char muj_pin [5];
char pin [5];
int i;

unsigned char old_ddr;

void pip(int ton) // OK pipnuti
{
    // priklad:
    // cas=600
    // ton=1000
    setb(DDRD,5);
    int i;
            for (i=0;i<300;i++) 
                {
               
                negb(PORTD,5);
                _delay_us(ton);
               
                }
}

int main(void)
{


//////////////////////////////////////////////////////////////////////////////////
//DDRD=0xFF; // vystupní - Ledky
//DDRC=0x00; // vstupní  - Tlacitka

///// LCD INIT

    LCD_Init();
    LCD_Clear();
    _delay_ms(2);

    LCD_Position(0 , 0);
    LCD_WriteString(" Zadej PIN a * ");
    LCD_Position(1 , 0);
    LCD_WriteString("               ");


strcpy(muj_pin,"1234"); // nastaveni hledaneho pinu
pin[4]=0;                // zarucuje aby pole pin byl string (string musi koncit 0)                 

while (1)
      {
////////////////////////Zacatek cteni
tlacitka=255;

old_ddr=DDRB; //zaloha nastaveni DDR

_delay_us(cas);
setb(DDRB,0); // vystupy
setb(DDRB,1);
setb(DDRB,2);
setb(DDRB,3);

clrb(DDRB,4); // vstupy
clrb(DDRB,5);
clrb(DDRB,6);
clrb(DDRB,7);


PORTB=0b00001110;

// 1 sloupec

_delay_us(cas);

if bit_is_clear(PINB,4) tlacitka=1;
if bit_is_clear(PINB,5) tlacitka=4;
if bit_is_clear(PINB,6) tlacitka=7;
if bit_is_clear(PINB,7) tlacitka=100; // #

// 2 sloupec
PORTB=0b00001101;

_delay_us(cas);

if bit_is_clear(PINB,4) tlacitka=2;
if bit_is_clear(PINB,5) tlacitka=5;
if bit_is_clear(PINB,6) tlacitka=8;
if bit_is_clear(PINB,7) tlacitka=0;

// 3 sloupec
PORTB=0b00001011;

_delay_us(cas);

if bit_is_clear(PINB,4) tlacitka=3;
if bit_is_clear(PINB,5) tlacitka=6;
if bit_is_clear(PINB,6) tlacitka=9;
if bit_is_clear(PINB,7) tlacitka=101; // *


// 4 sloupec
PORTB=0b00000111;

_delay_us(cas);

if bit_is_clear(PINB,4) tlacitka=11; //F1
if bit_is_clear(PINB,5) tlacitka=12; //F2
if bit_is_clear(PINB,6) tlacitka=13; //F3
if bit_is_clear(PINB,7) tlacitka=14; //F4

PORTB=0b00001111; // nectu

DDRB=old_ddr; //zaloha nastaveni DDR

/// konec cteni
///////////////////////////////////////////////////////


if (tlacitka!=tlacitka_new) // pokud se stara hodnota nerovna nove znamena to novy stisk
 {
  
   tlacitka_new=tlacitka ; // novou hodnotu priradime stare


    if (tlacitka<10)      // reakce jen pokud je zmacknuto cislo (ne F1-F4 a # a *)
    {
       
       
       
        if (znak==0)  // pri vynulovani znaku (zmacknuti # driv nez jsou 4 znaky)  se smaze i druhy radek
        {
        LCD_Position(1 ,0);
        LCD_WriteString("                ");
        }
       
        znak=znak+3;     // vhodne rozhozeni cisel
        if (znak>12)      // jestlize je zapsano vice nez 4 znaky (3*4=12) vymaz spodni radek
        {
        LCD_Position(1 ,0);
        LCD_WriteString("                ");
        znak=2;
       
        }

        pin[i]=tlacitka+48;   // ukladani stisknutych cisel do stringu (prevod na ascii- 0 je 48 v ascii)
        i++;

        if (i==4) i=0;       //  vynulovani pozice a znovu zapisovani PINu
   

        // zobrazovani zadavanych znaku
        LCD_Position(1 , znak); 
        sprintf (tmp,"%d",tlacitka);
        LCD_WriteString(tmp);
       
        pip(100,1000);



      } // konec reakce na cisla

  } // konec reakce na stisk
 
 
if (tlacitka==100)   // pokud je zmackunto # spusti se porovnani zadaneho a ulozeneho PINu
{
        znak=0;i=0;   // osetreni pokud se zmackne # driv nez je
                         zadano  4 cisla PINu

        LCD_Position(1 , 0);
        if(strcmp(muj_pin,pin) == 0)
        {
        LCD_WriteString("PRISTUP POVOLEN!");
        pip(600,1000);
        }
        else
        {
        LCD_WriteString("PRISTUP ODEPREN!");
        pip(600,500);
        _delay_ms(200);
        pip(600,500);
        }   
    strcpy(pin,"0000"); // vynulovani nalezeneho pinu   
}

      }
}