Witam wszystkich!
Napisałem program, który w moim zamierzeniu powinien odczytywać klawiaturę ps2 podpiętą pod atmega32. Wykorzystuje przerwania na opadającym zboczu na porcie PD2(INT0). Owszem program ten odczytuje, że coś zostało wciśnięte, ale mam problem ze zidentyfikowaniem wciśniętego klawisza (funkcja czy_wysw nie działa tak jak powinna). Otóż w ogóle nie wchodzi mi chyba w case 0xF0, bo chcę tam zapalić diodę przez PORTC=0x01, ale ona się nie zapala. W symulacjach w avrstudio działa jak powinno, ale na sprzęcie (zl3avr) guzik z tego. Poświęciłem prawie 3 dni na znalezienie przyczyny - niestety bezskutecznie. Liczę na Was. Pozdrawiam
klawiatura ps2 atmega
-
K_o_n_r_a_d
- Użytkownik
- Posty: 123
- Rejestracja: 29 lip 2005, 10:21
- Lokalizacja: Lublin
Oj sorki, widać, że nie był już przytomny, bo miałem załączyć kod, a tego nie zrobiłem. Załączam go więc teraz:
___________________________________________
kody umieszczamy pomiędzy znacznikami "Code", spark
Kod: Zaznacz cały
//obsluga klawiatury ps/2
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <inttypes.h>
#include <avr/pgmspace.h>
#include <avr/parity.h>
#define F_CPU 1000000
#define PS_KIER DDRD
#define PS_WYJ PORTD
#define PS_WEJ PIND
#define PS_DATA 3
#define PS_CLK 2
void ini_klaw(void)
{
PS_KIER = 0x00;
PS_WEJ = _BV(2)|_BV(3);
MCUCR = 0x02; //zbocze opadajace aktywuje przerwanie
sbi(GICR, 6); //aktywuje przerwanie INT0
cbi(GIFR, 6); //zerowanie flagi INTF0
}
unsigned char asciim[]={'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
unsigned char asciid[]={'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
unsigned char make_code[]={0x1C, 0x32, 0x21, 0x23, 0x24, 0x2B, 0x34, 0x33, 0x43, 0x3B, 0x42,
0x4B, 0x3A, 0x31, 0x44, 0x4D, 0x15, 0x2D, 0x1B, 0x2C, 0x3C, 0x2A,
0x1D, 0x22, 0x35, 0x1A, 0x45, 0x16, 0x1E, 0x26, 0x25, 0x2E, 0x36,
0x3D, 0x3E, 0x46};
int lp=0;
unsigned char znak=0, znak_pusz=0;
czy_wysw(unsigned char klawisz)
{
int j;
switch(klawisz)
{
case 0xF0:
PORTC=0x01;
znak_pusz=klawisz;
break;
}
if(znak_pusz==0xF0)
{
znak_pusz=0;
for(j=0;j<=35;j++)
{
if(klawisz==make_code[j])
PORTC=0x01;
}
}
}
void czyt_klaw(void)
{
unsigned char par,par_ob; //bit parzystosci
if(lp==10) //bit stopu o wartosci 1
{
if(PS_WEJ&0x08)
{
czy_wysw(znak);
znak=0;
lp=0;
return;
}
else
return;
}
if(PS_WEJ&0x08 && lp<1) //jesli mamy 0 na CLK i 1 na DATA, to uC jest zajety i nie moze odczytywac danych z klawiatury
{
return;
}
;
if(lp<9 && lp>0)
{
znak>>=1;
if(PS_WEJ&0x08)
{
znak|=0x80;
}
}
if(lp==9)
{
par=PS_WEJ&0x08;
}
lp++;
}
SIGNAL (SIG_INTERRUPT0)
{
czyt_klaw();
}
int main(void)
{
DDRC=0xff;
ini_klaw();
sei();
while(1);
}kody umieszczamy pomiędzy znacznikami "Code", spark
Ostatnio zmieniony 05 sty 2009, 19:36 przez waldek86, łącznie zmieniany 1 raz.
- Aro
- Użytkownik
- Posty: 677
- Rejestracja: 30 paź 2006, 18:49
- Lokalizacja: Świerczyniec | Wrocław
- Kontakt:
Trochę dziwny algorytm odczytu, i na dodatek wszystko w przerwaniu i możesz nie wyrobić się czasowo. Proponuję inne rozwiązanie czyli w przerwaniu tylko sam odczyt kodu, a w pętli głównej zrealizujesz zamianę na ASCII. I przede wszystkim zastosuj wtedy bufor na przynajmniej kilkanaście bajtów. Poniżej kod, który ściągnąłem z elektrody i trochę ulepszyłem, działa niezawodnie.
Kod: Zaznacz cały
#define DTA B
#define DTApin 0
#define CLK B
#define CLKpin 1
#define PS2_TEST (PIN(DTA)&_BV(DTApin))
volatile uint8_t PS2_Dane=0;
volatile uint8_t comm=0;
volatile uint8_t fifo[20];
volatile uint8_t i;
SIGNAL(SIG_INTERRUPT1)
{
switch(i)
{
case 0 : // bit startu
if(PS2_TEST)break; //jeśli to nie bit startu ignoruj ramkę
PS2_Dane = 0;
i++;
break;
case 1 : // bity danych
if(PS2_TEST) PS2_Dane |= 0x01;
i++;
break;
case 2:
if(PS2_TEST) PS2_Dane |= 0x02;
i++;
break;
case 3:
if(PS2_TEST) PS2_Dane |= 0x04;
i++;
break;
case 4:
if(PS2_TEST) PS2_Dane |= 0x08;
i++;
break;
case 5 :
if(PS2_TEST) PS2_Dane |= 0x10;
i++;
break;
case 6:
if(PS2_TEST) PS2_Dane |= 0x20;
i++;
break;
case 7 :
if(PS2_TEST) PS2_Dane |= 0x40;
i++;
break;
case 8:
if(PS2_TEST) PS2_Dane |= 0x80;
i++;
break;
case 9 :
// bit parzystości
i++;
break;
case 10 :
// bit stopu
fifo[comm++]=PS2_Dane;
i = 0;
break;
}
GIFR&=~_BV(INT0);
}Żeby nie zaczynać nowego tematu, chciałbym Was jeszcze zapytać, czy można odblokować atmege32? Przez niedoczytanie i nierozwagę zmieniłem bowiem ustawienia fusebitów w avrstudio i teraz gdy chcę programować, to wyskakuje mi błąd :address 0x0000 expected 0x940c . O tym, że procesor jest zablokowany wnioskuję gdyż nie mogę zmienić żadnych ustawień na fusebitach. Próbowałem go odblokować przez dołączenie kwarcu z zewnątrz o f=16MHz, ale nie pomogło(bo nie wiem jaką f ustawiłem. W avrstudio mam ExtXTAL Startup:30us +1k CK ale jakiej f to odpowiada to nie wiadomo). Myślę jednak, że problemem jest to, że nie można zaprogramować bitu SPI enable i dlatego nie można zaprogramować atmegi32. Czytałem, że jeśli dołączenie rezonatora z zewnątrz nie pomoaga, to można spróbować użyć programatora LPT. Czy da się tak odblokować procka, a jeśli tak to jak?
-
00dexter00
- -
- Posty: 21
- Rejestracja: 23 mar 2008, 14:22
- Lokalizacja: Turbia