Witam wszystkich użytkowników!
Jest to mój pierwszy post na forum elektroda.pl mam więc nadzieję, że okażecie mi trochę zrozumienia i pomożecie odpowiedzieć na pytanie, które już nie raz zdążyło pojawić się na tym forum. Przeszukałem dokładnie każdy temat dotyczący obsługi przycisków pod ATmegą8, ATmegą16 czy ATmegą32 jednak w żadnym z nich nie znalazłem instrukcji, która krok po kroku wyjaśniłaby schemat działania tej prostej klawiatury. Mikrokontrolerami AVR zajmuję się od niedawna (spokojnie można powiedzieć, że jestem na etapie początkującym) tak więc pisząc program obsługi przycisków pojawiło się w mojej głowie pytanie, które kieruję do Was, a które brzmi następująco: czy kod i opis obsługi przycisków opisany przeze mnie poniżej jest w 100% prawidłowy? jeżeli tak to mógłby posłużyć osobom, które podobnie jak ja zaczynają "przygodę" z programowaniem mikrokontrolerów AVR, a które nie miały do tej pory większego pojęcia o tym jak to wszystko działa.
Posiadam zestaw uruchomieniowy ZL3AVR. Piny kolumn K1, K2, K3 i K4 klawiatury łączę kablami odpowiednio z pinami PC0, PC1, PC2 i PC3 portu C mikroprocesora. Piny wierszy W1, W2, W3 i W4 klawiatury łączę kablami odpowiednio z pinami PC4, PC5, PC6 i PC7 portu C mikroprocesora. Piny portu A mikroprocesora łączę analogiczne kablami z pinami panelu LED (piny od D0 do D7).
kod programu:
konfiguracja portów:
Na początku funkcji main() PORTA ustawiam jako wyjście dla diod led (które będę wyświetlały binarną reprezentację kodu wciśniętego przycisku). Kod przycisku S1 jest równy 0 a idąc "w prawo" kody kolejnych przycisków są większe od poprzednich o 1, tj. kod przycisku S2 = 1, S3 = 2, S4 = 3, S5 = 4 itd. 4 młodsze bity PORTC ustawiam jako wyjście (PC0 jako pin wejściowy K1 klawiatury, PC1 jako pin wejściowy K2 klawiatury itd.). 4 starsze bity PORTC ustawiam jako wejście z pull-upami (PC4 jako pin wyjściowy W1 klawiatury, PC5 jako pin wyjściowy W2 klawiatury itd.).
działanie programu:
piny wejściowe klawiatury K1 do K4 zeruję
oznacza to, że wszystkie cztery kolumny przycisków są teraz aktywne bowiem i-tą kolumnę aktywujemy stanem niskim, tj. na i-tym bicie PORTC ustawiamy wartość 0. Jeżeli na i-tym bicie jest ustawiona wartość 1 to oznacza, że i-ta kolumna jest nieaktywna. Następna instrukcja warunkowa
sprawdza czy na którymkolwiek z czterech wierszy (bity PC4 do PC7) pojawił się stan niski, jeżeli tak to oznacza, że został wciśnięty przycisk (jeżeli wszystkie cztery bity PC4 do PC7 mają wartość 1 tzn, że nie został wciśnięty żaden przycisk). Program czeka 20ms w celu wyeliminowania efektu drgania styków po czym ponownie sprawdza czy został wciśnięty którykolwiek z przycisków. Następnie na PORTA zostaje wysłana binarna reprezentacja kodu przycisku
funkcja ScanKeyboard() po kolei aktywuje każdą z czterech kolumn klawiatury za każdym krokiem sprawdzając czy na którymś z wierszy pojawił się stan niski (wtedy mamy szukany przycisk (i-ta kolumna, j-ty wiersz) i jego kod = 4 * j + i). Po wykonaniu funkcji ScanKeyboard() zostają aktywowane wszystkie cztery kolumny klawiatury i program czeka na zwolnienie przytrzymanego przycisku.
będę wdzięczny za wszystkie uwagi dotyczące poprawności i opisu działania kodu oraz wszelkie jego usprawnienia, pozdrawiam!
Jest to mój pierwszy post na forum elektroda.pl mam więc nadzieję, że okażecie mi trochę zrozumienia i pomożecie odpowiedzieć na pytanie, które już nie raz zdążyło pojawić się na tym forum. Przeszukałem dokładnie każdy temat dotyczący obsługi przycisków pod ATmegą8, ATmegą16 czy ATmegą32 jednak w żadnym z nich nie znalazłem instrukcji, która krok po kroku wyjaśniłaby schemat działania tej prostej klawiatury. Mikrokontrolerami AVR zajmuję się od niedawna (spokojnie można powiedzieć, że jestem na etapie początkującym) tak więc pisząc program obsługi przycisków pojawiło się w mojej głowie pytanie, które kieruję do Was, a które brzmi następująco: czy kod i opis obsługi przycisków opisany przeze mnie poniżej jest w 100% prawidłowy? jeżeli tak to mógłby posłużyć osobom, które podobnie jak ja zaczynają "przygodę" z programowaniem mikrokontrolerów AVR, a które nie miały do tej pory większego pojęcia o tym jak to wszystko działa.
Posiadam zestaw uruchomieniowy ZL3AVR. Piny kolumn K1, K2, K3 i K4 klawiatury łączę kablami odpowiednio z pinami PC0, PC1, PC2 i PC3 portu C mikroprocesora. Piny wierszy W1, W2, W3 i W4 klawiatury łączę kablami odpowiednio z pinami PC4, PC5, PC6 i PC7 portu C mikroprocesora. Piny portu A mikroprocesora łączę analogiczne kablami z pinami panelu LED (piny od D0 do D7).
kod programu:
#define F_CPU 8000000L //wewnętrzny kwarc Atmegi32 taktowany 8MHz, w zewnętrznym kwarcu powinno być 16000000L (16MHz)
#include <avr/io.h>
#include <stdint.h>
#include <util/delay.h>
uint8_t ScanKeyboard(){
for(uint8_t i = 0; i < 4; ++i){
PORTC = ~(1 << i); //aktywuj i-tą kolumnę stanem niskim
for(uint8_t j = 0; j < 4; ++j) if(!((PINC >> (4 + j)) & 1)) return 4 * j + i; //jeżeli w j-tym wierszu pojawi się stan niski to mamy szukany przycisk (i-ta kolumna, j-ty wiersz), zwróć kod przycisku
}
return 0x10; //jeżeli nie został wciśnięty żaden przycisk - zwróć kod przycisku 0x10 (który nie istnieje)
}
int main(){
DDRA = 0xff; //PORTA jako wyjście dla diod led (panel LED, piny od D0 do D7)
PORTA = 0x00;
DDRC = 0x0f; //4 młodsze bity PORTC jako wyjście, 4 starsze jako wejście z pull-upami
PORTC = 0xf0;
while(1){
if(~(PINC >> 4) & 0x0f){
_delay_ms(20);
if(~(PINC >> 4) & 0x0f){
PORTA = ScanKeyboard();
PORTC = 0xf0;
while(~(PINC >> 4) & 0x0f);
}
}
}
}
konfiguracja portów:
Na początku funkcji main() PORTA ustawiam jako wyjście dla diod led (które będę wyświetlały binarną reprezentację kodu wciśniętego przycisku). Kod przycisku S1 jest równy 0 a idąc "w prawo" kody kolejnych przycisków są większe od poprzednich o 1, tj. kod przycisku S2 = 1, S3 = 2, S4 = 3, S5 = 4 itd. 4 młodsze bity PORTC ustawiam jako wyjście (PC0 jako pin wejściowy K1 klawiatury, PC1 jako pin wejściowy K2 klawiatury itd.). 4 starsze bity PORTC ustawiam jako wejście z pull-upami (PC4 jako pin wyjściowy W1 klawiatury, PC5 jako pin wyjściowy W2 klawiatury itd.).
działanie programu:
piny wejściowe klawiatury K1 do K4 zeruję
PORTC = 0xf0;oznacza to, że wszystkie cztery kolumny przycisków są teraz aktywne bowiem i-tą kolumnę aktywujemy stanem niskim, tj. na i-tym bicie PORTC ustawiamy wartość 0. Jeżeli na i-tym bicie jest ustawiona wartość 1 to oznacza, że i-ta kolumna jest nieaktywna. Następna instrukcja warunkowa
if(~(PINC >> 4) & 0x0f){sprawdza czy na którymkolwiek z czterech wierszy (bity PC4 do PC7) pojawił się stan niski, jeżeli tak to oznacza, że został wciśnięty przycisk (jeżeli wszystkie cztery bity PC4 do PC7 mają wartość 1 tzn, że nie został wciśnięty żaden przycisk). Program czeka 20ms w celu wyeliminowania efektu drgania styków po czym ponownie sprawdza czy został wciśnięty którykolwiek z przycisków. Następnie na PORTA zostaje wysłana binarna reprezentacja kodu przycisku
PORTA = ScanKeyboard();funkcja ScanKeyboard() po kolei aktywuje każdą z czterech kolumn klawiatury za każdym krokiem sprawdzając czy na którymś z wierszy pojawił się stan niski (wtedy mamy szukany przycisk (i-ta kolumna, j-ty wiersz) i jego kod = 4 * j + i). Po wykonaniu funkcji ScanKeyboard() zostają aktywowane wszystkie cztery kolumny klawiatury i program czeka na zwolnienie przytrzymanego przycisku.
PORTC = 0xf0;
while(~(PINC >> 4) & 0x0f);będę wdzięczny za wszystkie uwagi dotyczące poprawności i opisu działania kodu oraz wszelkie jego usprawnienia, pozdrawiam!