Obvod je připraven, pustíme se do programování.
Programovací jazyk a IDE
Program je napsaný v C. Jako IDE jsem si zvolil NetBeans, stačí modul C/C++.
Z čeho se vycházelo
Ke studiu jsem použil HidKeys a C64 usb keyboard, jako zákad posloužil hid-mouse z v-usb.
Krátce o kódu
Kód je slepený z výše zmíněných s více či méně podstatnými úpravami. Nejvíc se změnila funkce čtení kláves. Čtení odpovídá zapojení klávesnice k mikrokontroléru a matici kláves. Matice jsou 2, standartní a FN. FN varianta je pro stisk s aktivní FN klávesou.
Popis jednotlivých souborů
main.c obsahuje funkci main a iniciaizaci USB.
descriptor.h obsahuje hid descriptor, který definuje naši klávesnici. Převzal jsem ho z C64 usb keyboard.
keymap.h obsahuje konfiguraci klávesnice, její matice, init portů mikrokontroléru a upravenou funkci scankeys, která hlídá stisk kláves.
usbconfig.h je standartní konfigurace v-usb. Většinou není nutné upravovat. Dá se nastavit piny D+ a D-.
V Makefile je nutné nastavit F_CPU, dle použitého krystalu.
Init portů mikrokontroléru
Něco málo k registrům portů. Mikrokontroléry ATmega mají registry portů. Každý registr má 8 bitů. DDR určuje směr – vstup 0 a výstup 1. PIN se používá ke čtení. PORT nastavuje anebo deaktivuje pullup rezistory.
static void hardwareInit(void){
/* pin0 výstup, zbytek vstup */
PORTA = 0xFE;
DDRA = 0x01;
/* portB vstup */
PORTB = 0xFF;
DDRB = 0x00;
/* portC vstup */
PORTC = 0xFF;
DDRC = 0x00;
PORTD = 0xFA;
DDRD = 0x07;
_delay_ms(11);
DDRD = 0x02;
TCCR0 = 5;
}
Pin portu A, PA0, jsem nechal záměrně jako výstup a se zapnutým pullup rezistorem. Na vývojové desce je k němu totiž připojena led dioda, která má informativní charakter, program běží. Protože je tento pin jako výstupní připojil jsem k němu pin1 klávesnice, který je řádkem pro klávesy CTRL ALT SHIFT FN v matici. Zbytek pinů je vstup.
Port B vstup (řádky), Port C vstup (sloupce), Port D komunikace na PD0 a PD2, zbytek vstup (řádky na PD5 PD6 PD7). Zbytek inicializace jsem převzal.
Detekce stisku klávesy
#define NUMROWS 12
/* používané piny portu D */
const uchar DPORT = (1<<PD7)|(1<<PD6)|(1<<PD5);
/* buffer čtení sloupců */
static uchar readbuf[NUMROWS]={
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
/* hodnota testovaného řádku portu */
uchar data;
/* čtení kláves pro všechny řádky a uložení do bufferu */
for (row=0;row<NUMROWS;row++) {
/* připojené piny portu D vstup */
DDRD&=~DPORT;
PORTD|=DPORT;
/* výstup na portu B */
if (row < 8) {
data=1 << row;
/* nastavení výstupu na konkrétním pinu */
DDRB=data;
PORTB=~data;
}
/* výstup na portu D */
else if(row<11){ // 9, 10, 11 PORTD
/* port B pouze vstup */
DDRB=0;
PORTB=0xFF;
data = 1 << (row - 3);
/* nastavení výstupu na konkrétním pinu */
DDRD|=data;
PORTD&=~data;
}
/* počkáme */
_delay_us(30);
/* čteme, poslední řádek v matici je pro specílní klávesy
CTRL ALT SHIFT FN, jinak čteme obyčejné */
data = (row == 11 ? PINA : PINC);
readbuf[row]=data;
}
Všimněte si bufferu, má přednastaveny hodnoty 0xFF, to znamená, žádný stisk na daném řádku. Při čtení ze vstupního portu DDR=0xFF, s nastavenými pullup rezistory PORT=0xFF, pokud je pin odpojen, přečtete hodnotu 1, pokud spojen se zemí, anebo výstupním pinem, přečtete 0.
Díky tomu lze jednotlivě přečíst všechny stisky na klávesnici.
Zdrojový kód ke stažení
Stáhněte si zdrojový kód a zkompilujte příkazem
make hex
Výsledným souborem main.hex naprogramujte mikrokontrolér. Po naprogramování se pusťe do testování.