logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Klawiatura 4x4 - niepoprawny kod?[AVR][C]

SWITCHER20 26 Lis 2010 21:54 5141 16
REKLAMA
  • #1 8793570
    SWITCHER20
    Poziom 10  
    Witam jestem poczatkującym jeśli chodzi o jezyk C i ogólnie jeśli chodzi o programowanie. Mam taki problem .Chcę żeby po naciśnięciu odpowiedniego klawisz na klawiaturze zapalała się inna dioda led na porcie D (bądz sekwencja kilku diod).
    Na początku próbowałem z funkcja switch ale dałem spokój bo było jeszcze gorzej. Prosze o pomoc w poprawieniu teg listingu bądź może ktoś ma napisany inaczej też chętnie zobacze ..Jednak tylko w jezyku C..mogą zostać zastosowane przerwania zewnętrzne INT0...



    #define F_CPU 1000000L
    #include <avr/io.h>
    #include <avr/interrupt.h>
    int main(void)
    {
    //high nibble for output(columns) low for input(rows);
    DDRB=0x0F;
    //enable internal pullups for PB0-PB3
    PORTB=0xF0;
    //Port D for indication only
    DDRD=0xFF;
    
    
    while (1) //loop key check forever
    	{
    	
    		//first column
    		PORTB =0b01111111;
    		//check for rows and send key number to portD
    		//instead sending key number to PORTD you can use
    		// any function that serves pressed button
    		if (PINB, 3) PORTD =0b00000001;
    		if (PINB, 2) PORTD =0b00000011;
    		if (bit_is_set(PINB, 1)) PORTD =0b00000111;
    		if (bit_is_set(PINB, 0)) PORTD =0b00001111;
    		asm("nop");
    		//second column
    		PORTB =0b10111111;
    		if (bit_is_set(PINB, 3)) PORTD =0b00011111;
    		if (bit_is_set(PINB, 2)) PORTD =0b00111111;
    		if (bit_is_set(PINB, 1)) PORTD =0b00111111;
    		if (bit_is_set(PINB, 0)) PORTD =0b01111111;
    		asm("nop");
    				//third column
    		PORTB =0b11011111;
    		if (bit_is_set(PINB, 3)) PORTD =0b11111111;
    		if (bit_is_set(PINB, 2)) PORTD =0b11111110;
    		if (bit_is_set(PINB, 1)) PORTD =0b11111100;
    		if (bit_is_set(PINB, 0)) PORTD =0b11111000;
    		asm("nop");
    		//fourth column
    		PORTB =0b11101111;
    		if (bit_is_set(PINB, 3)) PORTD =0b11110000;
    		if (bit_is_set(PINB, 2)) PORTD =0b11100000;
    		if (bit_is_set(PINB, 1)) PORTD =0b11000000;
    		if (bit_is_set(PINB, 0)) PORTD =0b10000000;
    		asm("nop");
    	}
    }
    
    
  • REKLAMA
  • #2 8795664
    adambombel
    Poziom 12  
    Ja bym zrobił to tak:

    
    CODE 
    #define F_CPU 1000000L 
    #include <avr/io.h> 
    #include <avr/interrupt.h>
    
    // wartosci, które beda wystawione na portd dla kolejno 16 klawiszkow, i ostatnia dla bledu (dwa zera przy odczycie 
    const unsigned char ucPortDOutput[] = { 0x01, 0x03, 0x02, 0x06, 0x04, 0x0C, 0x08, 0x18, 0x10, 0x30, 0x20, 0x60, 0x40, 0xC0, 0x80, 0x81, 0x55 }
    
    unsigned char ucGetKey(void)
    {
    	unsigned char ucI;
    	
    	for (ucI = 0; ucI < 4; ucI++)
    	{
    		// wybieramy kolumne podajac 0 na linie portu
    		PORTB = (0xF0 & ~(1 << (4+ucI))) | 0x0F;
    		
    		// odczytujemy stan pinow ignorujac starsza polowe
    		switch (PINB & 0x0F)
    		{
    			case 0x0E: return 0x00 + ucI;	// klawisze [0] [1] [2] [3]
    			case 0x0D: return 0x04 + ucI;	// klawisz3 [4] [5] [6] [7]
    			case 0x0B: return 0x08 + ucI;	// klawisz3 [8] [9] [A] [B]
    			case 0x07: return 0x0C + ucI;	// klawisz3 [C] [D] [E] [F]
    			case 0xFF: break;				// nic nie wcisniete w tej kolumnie
    			default:   return 0x10;			// blad - 0 na wiecej niz jednym bicie
    		}
    	}
    	return 0xFF;						// nic nie wcisniete
    }
    
    int main(void) 
    {
    	unsigned char ucKlawiszek;
    	
    	//high nibble for output(columns) low for input(rows); 
    	DDRB=0x0F; 
    	//enable internal pullups for PB0-PB3 
    	PORTB=0xF0; 
    	//Port D for indication only 
    	DDRD=0xFF;
    
    	while(1)
    	{
    		if((ucKlawiszek=ucGetKey()) != 0xFF)
    		{
    			PORTD = ucPortDOutput[ucKlawiszek];
    		}
    	}
    }
    


    Nie bardzo zrozumiałem tyko o co chodzi z tym przerwaniem INT0.

    Mam nadzieje że kod jest stosunkowo jasny.
  • #3 8799038
    ppawel12
    Poziom 16  
    wyjaśnij o co chodzi ci z tym przerwaniem ? jesli chcesz by klawisze były sprawdzane w przerwaniu zastosuj ten schemat :



    #include <avr/io.h>
    #include <avr/interrupt.h>
    #define F_CPU 1000000UL
    
    // flagi klawiszy np. key1 => PD0, ....
    volatile int key1=0, key2=0, key3=0, key4=0, key5=0;
    
    //przerwanie odczytuje jaki klawisz zostal wcisniety
    SIGNAL (_VECTOR(1))
    	{
    	if(!(PIND&0x01))
    	key1=1;
    	if(!(PIND&0x02))
    	key2=1;
    	if(!(PIND&0x10))
    	key3=1;
    	if(!(PIND&0x20))
    	key4=1;
    	}
    
    int main()
    {
    // podt D to wejścia możesz zmienić ja jakiś inny
    	PORTD =(1<<PD0)|(1<<PD1)|(1<<PD2)|(1<<PD4)|(1<<PD5)|(1<<PD6)|(1<<PD7);
    
    //konfiguracja przerwania	
    	MCUCR = (1<<ISC01)|(0<<ISC00);
    	GICR = (1<<INT0);
    
    	sei();
    
    	while(1)
    	{
    //petla glowna sprawdza jaki klawisz zostal wcisniety i dokonuje akcji dla niego		
    	if (key1 == 1 || key2 == 1 || key3 == 1 || key4 == 1)
    	{
    		if(key1 == 1)
    		{
    			key1=0;
                            ...... // tu możesz zapalac diody jakie chcesz
    		}
    		if(key2 == 1)
    		{
    			......
    			key2=0;
    		}
    		if(key3 == 1)
    		{
    			......
    			key3=0;
    		}
    		if(key4 == 1)
    		{
    			......
    			key4=0;
    		}
    	}}
    }
    


    to kod do dalszej modyfikacji wciśniecie klawisza podaje sygnał na INT0 oraz na odpowiedni port D. W przerwaniu układ młuci wszystkie porty i ustawia flagę a w pętli while dokonuje akcji dla odpowiedniego warunku If i zeruje flagę i czeka na następną akcje. Do tego kodu musisz wprowadzić modyfikację w elektronice (ja zastosowałem diody do przerwania by sygnał z key1 nie przeniknął na inne porty). Umiejscowienie klawiszy jak chcesz.
  • REKLAMA
  • #4 8799204
    SWITCHER20
    Poziom 10  
    Witam dziekuje za pomoc :)
    INT0 jest przerwaniem zewnętrznym który przy podłączeniu przez JP13 z INT0 (PD2) na zestawie startowym ZL3AVR (opis http://www.programatory.com/produkty/moduly_uruchomieniowe/ZL3AVR/zl3avr.pdf).
    JP13 rozpoznaje czy klawisz został wciśnięty i wywołuje przerwanie zewnętrzne po czym nastepuje sprawdzenie który kllawisz został wciśnięty
    Dzięki za pomoc raz jeszcze
  • REKLAMA
  • #5 8799234
    adambombel
    Poziom 12  
    ppawel12 napisał:
    wyjaśnij o co chodzi ci z tym przerwaniem ? jesli chcesz by klawisze były sprawdzane w przerwaniu zastosuj ten schemat :



    #include <avr/io.h>
    #include <avr/interrupt.h>
    #define F_CPU 1000000UL
    
    // flagi klawiszy np. key1 => PD0, ....
    volatile int key1=0, key2=0, key3=0, key4=0, key5=0;
    
    //przerwanie odczytuje jaki klawisz zostal wcisniety
    SIGNAL (_VECTOR(1))
    	{
    	if(!(PIND&0x01))
    	key1=1;
    	if(!(PIND&0x02))
    	key2=1;
    	if(!(PIND&0x10))
    	key3=1;
    	if(!(PIND&0x20))
    	key4=1;
    	}
    
    int main()
    {
    // podt D to wejścia możesz zmienić ja jakiś inny
    	PORTD =(1<<PD0)|(1<<PD1)|(1<<PD2)|(1<<PD4)|(1<<PD5)|(1<<PD6)|(1<<PD7);
    
    //konfiguracja przerwania	
    	MCUCR = (1<<ISC01)|(0<<ISC00);
    	GICR = (1<<INT0);
    
    	sei();
    
    	while(1)
    	{
    //petla glowna sprawdza jaki klawisz zostal wcisniety i dokonuje akcji dla niego		
    	if (key1 == 1 || key2 == 1 || key3 == 1 || key4 == 1)
    	{
    		if(key1 == 1)
    		{
    			key1=0;
                            ...... // tu możesz zapalac diody jakie chcesz
    		}
    		if(key2 == 1)
    		{
    			......
    			key2=0;
    		}
    		if(key3 == 1)
    		{
    			......
    			key3=0;
    		}
    		if(key4 == 1)
    		{
    			......
    			key4=0;
    		}
    	}}
    }
    


    to kod do dalszej modyfikacji wciśniecie klawisza podaje sygnał na INT0 oraz na odpowiedni port D. W przerwaniu układ młuci wszystkie porty i ustawia flagę a w pętli while dokonuje akcji dla odpowiedniego warunku If i zeruje flagę i czeka na następną akcje. Do tego kodu musisz wprowadzić modyfikację w elektronice (ja zastosowałem diody do przerwania by sygnał z key1 nie przeniknął na inne porty). Umiejscowienie klawiszy jak chcesz.


    Czy przypadkiem nie miała to być klawiatura matrycowa 4x4? Bo ten kod czyta tylko proste podłączenie klawiszków do portu, a nie klawiature matrycową.

    Ponad to, patrząc na schemat zl3avr, to wyjście przerwania z klawiatury pracuje poprawnie jedynie podczas poporawnego sterowania jej kolumnami, tj. przemiatanie "0" po kolumnach musi odbywać się niezależnie od przerwania od klawiatury, a przerwanie zostanie zgłoszone dopiero kiedy na wyprowadzeniu kolumny wciskanego przycisku będzie stan niski.

    Można obsługę zrealizować np. tak:
    
    #define F_CPU 1000000L 
    #include <avr/io.h> 
    #include <avr/interrupt.h> 
    
    // wartosci, które beda wystawione na portd dla kolejno 16 klawiszkow, i ostatnia dla bledu (dwa zera przy odczycie 
    const unsigned char ucPortDOutput[] = { 0x01, 0x03, 0x02, 0x06, 0x04, 0x0C, 0x08, 0x18, 0x10, 0x30, 0x20, 0x60, 0x40, 0xC0, 0x80, 0x81, 0x55 } 
    
    volatile unsigned char ucKolumna;
    
    SIGNAL(SIG_INTERRUPT0)
    {
      unsigned char ucKlawisz;
      
      // odczytujemy stan pinow ignorujac starsza polowe
      // sprawdzamy, na którym bicie jest '0' i uwzgledniajac aktualnie wybraną kolumnę
      // ustawiamy zmienna ucKlawisz
      switch (PINB & 0x0F) 
      { 
        case 0x0E: ucKlawisz = 0x00 + ucKolumna;   // klawisze [0] [1] [2] [3] 
        case 0x0D: ucKlawisz = 0x04 + ucKolumna;   // klawisz3 [4] [5] [6] [7] 
        case 0x0B: ucKlawisz = 0x08 + ucKolumna;   // klawisz3 [8] [9] [A] [B] 
        case 0x07: ucKlawisz = 0x0C + ucKolumna;   // klawisz3 [C] [D] [E] [F] 
        default:   ucKlawisz = 0x10;               // blad - 0 na wiecej niz jednym bicie
      }
      
      // jeżeli nacisnieto jeden klawisz, to obslugujemy to podajac dane na PORTD
      if (ucKlawisz != 0x10)
      {
        PORTD = ucPortDOutput[ucKlawisz];
      }
    }
    
    int main(void) 
    { 
      unsigned char ucKlawiszek; 
       
      //high nibble for output(columns) low for input(rows); 
      DDRB=0x0F; 
      //enable internal pullups for PB0-PB3 
      PORTB=0xF0; 
      //Port D for indication only 
      DDRD=0xFF; 
    
      while(1) 
      {
        // niezależne od przerwania przemiatanie kolumn
        ucKolumna = (ucKolumna < 4 ? ucKolumna + 1 : 0);
        PORTB = (0xF0 & ~(1 << (4+ucKolumna))) | 0x0F;
      } 
    }
    
  • #6 8800098
    ppawel12
    Poziom 16  
    a widzisz że masz tam "....." to po to by sobie dopisać resztę kodu w zależności od potrzeby a umieszczenie klawiszy może być dowolne jak masz kod dobry to może być 4x3, 2x2, 4x4 itp.
    możesz go zmodyfikować dla innych bardziej skomplikowanych relacji klawiszy ale musisz zmodyfikować elektronikę tak by np. wciskając 1 klawisz poszedł sygnał na INT0 oraz na PD0 i PD1 i tak dalej, a inne wejścia pozostały bez zmiany.

    a jak dodam w przerwaniu:
    
    
    if(!(PIND&0x10) && !(PIND&0x20))
       key5=1; 
    
    ...
    if(key5 == 1)
          {
             ......
             key5=0;
          } 
    


    to będzie już mógł realizować inne konfiguracje.

    Na tym forum nie chodzi by dać całe rozwiązanie ale by naprowadzić, zamieściłem kawałek kodu z myślą że jak ktoś go weźmie to sobie go zmodyfikuje pod siebie to jest "szablon" jak można to tak nazwać :)
  • #7 8802432
    adambombel
    Poziom 12  
    ppawel12 napisał:
    a widzisz że masz tam "....." to po to by sobie dopisać resztę kodu w zależności od potrzeby a umieszczenie klawiszy może być dowolne jak masz kod dobry to może być 4x3, 2x2, 4x4 itp.


    Widze ".......", ale ich umiejscowienie ni jak nie pozwolą na zrealizowanie odczytu klawiatury matrycowej.

    ppawel12 napisał:
    ... ale musisz zmodyfikować elektronikę tak by np. wciskając 1 klawisz poszedł sygnał na INT0 oraz na PD0 i PD1 i tak dalej, a inne wejścia pozostały bez zmiany.


    To jest zestaw startowy i klawiatura już tam jest, więc podejrzewam że modyfikacja elektroniki raczej nie wchodzi w grę. Czy aby na pewno rozumiesz zasadę działania klawiatury matrycowej ?

    ppawel12 napisał:

    a jak dodam w przerwaniu:
    
    
    if(!(PIND&0x10) && !(PIND&0x20))
       key5=1; 
    
    ...
    if(key5 == 1)
          {
             ......
             key5=0;
          } 
    


    to będzie już mógł realizować inne konfiguracje.



    Jak dodasz w przerwanie co kolwiek to i tak, żeby ten dodany kod się wykonał musi nastąpić wywołanie przerwania, a w przypadku klawiatury matrycowej nie nastąpi ono, jeżeli kolumny nie będą prawidłowo sterowane, nie wspominając już o tym, że dodawanie obsługi więcej niż jednego klawisza jednocześnie w klawiaturze matrycowej generalnie jest raczej źródłem problemów.

    ciekawe jak będzie wyglądał ten "szablon", jak przyjdzie obsłużyć więcej klawiszy... np 32... (8x4 klawiszy).

    Śmiem twierdzić, że w kwesti klawiatury matrycowej mój kod jest zdecydowanie bardziej elastyczny od tego szablonu.

    ppawel12 napisał:

    Na tym forum nie chodzi by dać całe rozwiązanie ale by naprowadzić, zamieściłem kawałek kodu z myślą że jak ktoś go weźmie to sobie go zmodyfikuje pod siebie to jest "szablon" jak można to tak nazwać :)


    Owszem, nie chodzi, ale.... Początkującej osobie (autor tematu tak o sobie twierdzi) zdecydowanie łatwiej jest analizować/przerabiać działający kod niż uzupełniać coś co nie działa i w dodatku nie przystaje do sprzętu, na którym jest uruchamiane.
  • #8 8803707
    ppawel12
    Poziom 16  
    Jak się obawiasz, że kod będzie za duży wtedy dokonujesz podziału go na mniejsze pliki i do głównego pliku dołączasz tylko deklaracje. W prockach z tego co ja wiem i się nauczyłem to w głównej pętli powinno być tylko działania wyjściowe, obliczenia i wyprowadzanie sygnałów. Natomiast wszystkie działania, które dokonują odczytu z zewnątrz powinny wykorzystywać peryferia takie jak przerwania, liczniki, komparatory itp.

    Autor nie napisał, że to jest zestaw startowy już z gotową klawiaturą, poprosiło pomoc ty zaoferowałeś swój kod ja swój. W moim kodzie trzeba klawiaturę sobie samemu zrobić:P Jak to pomogło w rozwiązaniu pomocy to chyba nie ma sensu się dalej kłócić czyj kod jest lepszy itp.

    PS. w poprzednim poście dodałeś obsługę przerwania ale go nie skonfigurowałeś :P to to nie zadziała a po za tym by to obsłużyć musisz wciskać i przerwanie oraz klawisz ja mam wszystko spięte.

    Dodano po 5 [godziny] 8 [minuty]:

    Opracowałem nowy kod dla klawiatury 4x4 zapisując ją jako macierz:
    #include <avr/io.h>
    #define F_CPU 1000000L
    
    int main ()
    {
    	DDRB = 0xFF;
    	PORTB = 0x00;
    
    	short int row=0, kol=0, x=0;
    	int tab_key[14];
    
    	while(1)
    	{
    		
    		row = 0x01;
    		x = 0;
    		for(int i=0; i<4; i++)
    		{
    			kol=0x10;
    			for(int j=0; j<4; j++)
    			{
    				if((PINB & kol) && (PINB & row))
    					tab_key[x]=1;
    				else
    					tab_key[x]=0;
    				x++;
    				kol = kol << 1;
    			}
    			row = row << 1;
    		}
    	}
    }
    


    Tworzony jest wektor, w której są zapisywane jaki klawisz został wciśnięty. Porty od 0 do 3 to wiersze a porty od 4 do 7 to kolumny. Program przeszukuje pozycje po pozycji i wypełnia wektor na podstawie, którego można dalej podejmować akcje jakie kto chce. Program jest według mnie banalny można go modyfikować dla innych rozmiarów klawiaturek.
  • #9 8804652
    slaweczeek
    Poziom 2  
    Czy może ktoś mi wyjaśnić linijka po linijce kod do obsługi klawiatury matrycowej np. użytkownika "adambombel" lub inny który po wciśnięciu odpowiedniego klawisza zapala się dioda. Jestem początkującym i chciałbym żeby mi ktoś to porządnie wyjaśnił. Z góry dzięki.
  • #10 8804908
    Andiron
    Poziom 10  
    Masz na mysli ze na przycisku sa imiona, i co sie dzieje jak wcisniesz przycisk?
    No to ogolnie dziala to tak ze:
    1. nozka z ATmegi ma byc na wysokim stanie (pull up, 1 itp.)
    2. przycisk ma byc miedzy ta nozka a masa
    3. Wciskajac przycisk stan wysoki na nozce znika i mamy tam 0
    4. w ten sposob odczytujemy wcisniecie przycisku

    Klawiatura matrycowa - 4x4, czyli uzywamy 8 nozek z mikroprocka, 4 jako wyjscia (stany wysokie jak powyzej), 4 jako wejscia, wyobraz sobie kwadrat 4x4 jezeli wrzucas stan wysoki na linie gorna, to w tym czasie odczytujesz wejsciami ta linie, i jezeli stan spada na ktorejs kolumnie, to wiedzac w jakim wierszu bym stan wysoki i znasz kolumne spadku, mozesz wywnioskowac ktory to przycisk :)
  • #11 8805017
    adambombel
    Poziom 12  
    ppawel12:
    1. Podział na pliki nie zmniejsza kodu.
    2. Co do wykorzystania peryferiów to zależy od projektu
    3. Autor napisał że jest to ZL3AVR
    4. Odnośnie braku konfiguracji INT0 - masz racje, o tym zapomniałem
    5. Dla klawiatury matrycowej jest tylko jeden możliwy wariant całego odczytu klawiatury w przerwaniu - 0 na wszystkie kolumny, a jak wystąpi przerwanie, to "przejechać" kolumna po kolumnie i odczytywać wiersze.
    6. Nowy kod - ok, to pasuje "koncepcją" do klawiatury matrycowej, choć moim zdaniem nie ma sensu tworzenie wektora. Jedna zmienna wystarczy, bo odczytanie więcej niż jednego klawisza z klawiatury matrycowej jest co najmniej problematyczne.

    slaweczeek:
    Od początku... klawiatura matrycowa to taka, w której przyciski zwierają ze sobą kolumny i wiersze matrycy. Wyobraź to sobie jak druty ułożone pionowo - kolumny, a nad nimi ułożone poziomo - wiersze. Na skrzyżowaniu pionowych i poziomych drutów umieszczasz przyciski. Cały problem sprowadza się do wykrywania, która kolumna z którym wierszem została zwarta przez naciśnięty przycisk.

    Robi się to tak, że np. wiersze podciąga się do + zasilania rezystorami, i kolejno na jedną z kolumn podaje się stan niski. Jeżeli w danej kolumnie jest wciśnięty przycisk, to na odpowiadającym mu wierszu również wystąpi stan niski. Znając kolumnę, na którą podaliśmy "0" i wiersz z krórego odczytaliśmy "0" można wyliczyć, który przycisk został wciśnięty.

    Tłumacząc odpe się o najprostszą wersję bez przerwań itp.

    
    unsigned char ucGetKey(void) 
    { 
       unsigned char ucI; 
        
       for (ucI = 0; ucI < 4; ucI++) 
       { 
          // wybieramy kolumne podajac 0 na linie portu 
          PORTB = (0xF0 & ~(1 << (4+ucI))) | 0x0F; 
          // cala ta formulka powyzej ma na celu ustawienie "0" na wybranym pinie kolumny klawiatury,
          // a na pozostałych "1" zakladajac ze kolumny sa podlaczone do starszej polowy portu
           
          // odczytujemy stan pinow ignorujac starsza polowe, jednym slowem odczyt stanu wierszy klawiatury
          switch (PINB & 0x0F) 
          {
          // poniewaz rozpatrywanie sytuacji, kiedy wiecej niz jeden wiersz jest w stanie niskim
          // jest dla prostej klawiatury matrycowej bez sensu, to sprawdzane jest wystapienie
          // stanu niskiego tylko dla jednego wiersza
          
          //           vvvv     - te zera sa ignorowane przy odczycie
          //  0x0E - 0b00001110
          //                  ^ - to jest zero, ktore moze wystapic na wierszu podlaczonym do PB0
             case 0x0E: return 0x00 + ucI;   // klawisze [0] [1] [2] [3] 
             
          //  0x0D - 0b00001101
          //                 ^  - to jest zero, ktore moze wystapic na wierszu podlaczonym do PB1
             case 0x0D: return 0x04 + ucI;   // klawisze [4] [5] [6] [7] 
             
          //  0x0D - 0b00001011
          //                ^   - to jest zero, ktore moze wystapic na wierszu podlaczonym do PB2
             case 0x0B: return 0x08 + ucI;   // klawisze [8] [9] [A] [B] 
             
          //  0x0D - 0b00000111
          //               ^    - to jest zero, ktore moze wystapic na wierszu podlaczonym do PB3
             case 0x07: return 0x0C + ucI;   // klawisze [C] [D] [E] [F] 
    
             case 0xFF: break;            // nic nie wcisniete w tej kolumnie 
             default:   return 0x10;         // blad - 0 na wiecej niz jednym bicie 
          } 
       } 
       return 0xFF;                  // nic nie wcisniete 
    }
    
    Zakladajac, ze klawiatura jest podlaczona nastepujaco:
    
    PB0---[0][1][2][3]
    PB1---[4][5][6][7]
    PB2---[8][9][A][B]
    PB3---[C][D][E][F]
           |  |  |  |
           |  |  |  |
           P  P  P  P
           B  B  B  B
           4  5  6  7
    
    to funkcja zwraca:
    - wartość od 0x00 do 0x0F odpowiednio do wciśniętego klawisza
    - 0x10 - jeżeli wciśnięty jest więcej niż jeden klawisz i nie można zidentyfikować które
    - 0xFF - jeżeli nie jest wciśnięty żaden klawisz
    
  • #12 8805506
    slaweczeek
    Poziom 2  
    adambombel dzieki za tak szybką odpowiedz. jak byś mógł jeszcze napisać jak ten listing wyglądał by z przerwaniem. A i jeszcze jedno co oznacza ucI. Mam jaszcze pytanie czy jest jakiś emulator do sprawdzenia działania programu który zapala diodę po naciśnięciu wybranego klawisza
  • #13 8805757
    ppawel12
    Poziom 16  
    są dwa :

    jeden w symulatorze AVRStudio, piszesz, wyłączasz optymalizacje, kompilujesz i sprawdzasz w symulatorze (zabawna na rejestrach takie kwadraciki albo 1 albo 0) F11 robisz skoki w programie.

    drugi to nakładka graficzna program o nazwie Hapsim, działa podczas symulacji w trybie RUN. Włączasz symulacje bez trybu RUN, odpalasz nakładkę i konfigurujesz jaki procek, i co chcesz mieć wyświetlacz, klawisze diody itp konfigurujesz je !!. Potem klikasz w AVRStudio RUN i wszystko śmiga. Wpisz w google nazwę programu.

    Tak bodajże to było krok po kroku.


    adambombel: podanie zestawu startowego padło po moje odpowiedzi pierwszej potem dałem inny dobry kod, stworzony od podstaw według idei kod jest prosty i można go swobodnie rozpisać dla innych matryc. Oraz podaje jaki klawisz został wciśnięty, co można potem wykorzystać w innych programach itp.

    pozdrawiam
  • #14 8806856
    slaweczeek
    Poziom 2  
    Mam jeszcze jedną prośbę o napisanie kompletnego programu który po naciśnięciu klawisza np 1 zapala diodę 1 , klawisza 2 diodę 2 itd. z wykożystaniem przerwania zewnętrznego i dokładnym opisem krok po kroku co i jak oraz jak to sprawdzić w hapsinie
  • REKLAMA
  • #15 8808519
    ppawel12
    Poziom 16  
    jak masz klawiaturę taka normalną, tak podłączoną:

    PB0[0x01]---[0][1][2][3]
    PB1[0x02]---[4][5][6][7]
    PB2[0x04]---[8][9][A][B]
    PB3[0x08]---[C][D][E][F]
    | | | |
    | | | PB7[0x80]
    | | PB6[0x60]
    | PB5[0x20]
    PB4[0x10]


    taką masz klawiaturę tak podłączoną ? jakiś sygnał idzie do wejścia od przerwania PD2 lub PD3 ?? jak nie to nie zrealizujesz tego w ten sposób. Mój program pierwsze jest na klawiaturę własnej produkcji z dodatkową elektroniką.
    Spoko nie załamuj się jest inne wyjście przerwanie od licznika :) a mianowicie użyć licznika, który co np.10ms będzie sprawdzać klawisze i podejmować akcje

    Wieczorkiem będę miał więcej czasu to napisze ci cały program. Teraz podam szybko jak rejestry skonfigurować:
    bierzesz licznik 0;
    ustawiasz preskaler w TCCRO;
    licznik liczy i zwiększa rejestr TCNTC;
    włączasz przerwanie od licznika w rejestrze TIMSK;
    Link - tu masz dokumentacje.


    
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #define F_CPU 1000000UL
    
    
    volatile int tab_key[14];
    
    SIGNAL (_VECTOR(9)) //przepełnienie licznika i masz przerwanie
       {
       kod klawiatury np. mój 
       }
    
    int main()
    {
    // podt D to wejścia możesz zmienić ja jakiś inny
       DDRB = 0xFF;
       PORTB = 0x00;
    
    //konfiguracja przerwania   
       TCCRO = //tu ustawiasz preskaler strona 72 dokumentacji
       TIMSK = (1<<TOIE0); // aktywujesz przerwanie od przepełnienia
    
       sei(); // włączasz przerwania 
    
       while(1)
       {
    //petla glowna sprawdza jaki klawisz zostal wcisniety i dokonuje akcji dla niego      
       if (tab_key[0] == 1)
          {
           ..... zapalasz co chcesz i analogicznie dalej lecisz
           }
    } 




    Hapsim konfiguracja jest prosta jeśli wiesz co jest gdzie wyprowadzone tzn jakie porty to klawisz a jakie porty to diody to tam to konfigurujesz i wyzwalane 1 czy 0; Link tu masz opis tego programu

    PS nie licz by ktoś dał ci gotowca weź to co daliśmy z innym użytkownikiem i popróbuj sam dojść do celu masz już cały kod prawie napisany w kilku postaciach.
  • #16 8955536
    slaweczeek
    Poziom 2  
    witam mam taki program i nie wiem jak dołączyć klawiaturę matrycową, a mianowicie chce żeby po przyciśnięciu klawisza 1 wykonał się blok instrukcji (*) a po przyciśnięciu drugiego klawisza blok instrukcji (**) i trzeciego klawisza żeby silnik się zatrzymał. Prosze o pomoc i szczegółowy opis obsługi klawiatury bo naprawdę nie wiem jak się do tego zabrać.
    oto mój listing:
    
    /* STEROWANIE SILNICZKIEM KROKOWYM */
    #define F_CPU 1000000L
    #include <avr/io.h>
    #include <util/delay.h>
    #define LCD  PORTD		/* Zdefiniowanie portu do którego podłączony zostanie 
    					Wyświetlacz LCD */ 
    #define RS  0
    #define E  1
    #define SET_RS  LCD |= _BV(RS)
    #define CLR_RS  LCD &= ~_BV(RS)
    #define SET_E   LCD |= _BV(E)
    #define CLR_E   LCD &= ~_BV(E)
    void pisz_na_lcd(char aaa)			/* Procedura zapisu bajtu do wyświetlacza LCD */
    {
    SET_E; 					/* Ustaw na E stan wysoki */
    LCD = ((LCD & 0x0F) | (aaa & 0xF0)); 	/* Zapis pierwszej połówki bajtu */
    CLR_E; 					/* Opadające zbocze na E -> zapis do wyświetlacza */
    SET_E;					/* Ustaw na E stan wysoki */
    LCD = ((LCD & 0x0F) | ((aaa & 0x0F) << 4)); 	/* Zapis drugiej połówki bajtu */
    CLR_E; 				/* Opadające zbocze na E -> zapis do wyświetlacza */
    _delay_ms(10); 				/* Czekaj 10ms */
    }
    void pisz_instr(char aaa)			/* Procedura zapisu instrukcji do wyświetlacza LCD */
      {
    CLR_RS; 					/* Niski stan na RS -> zapis instrukcji */
    pisz_na_lcd(aaa); 				/* Zapis do LCD */
    }
    void pisz_dana(char aaa)			/* Procedura zapisu danej do wyświetlacza LCD */
        {
    SET_RS; 					/* Wysoki stan na RS -> zapis danej */
    pisz_na_lcd(aaa); 				/* Zapis do LCD */
        }
    void pisz_text(char * s)			/* Procedura zapisu tekstu do wyświetlacza LCD */
    	  {
    while(*s) 					/* Do napotkania 0 */
            { 
      pisz_dana(*s); 				/* Zapisz znak wskazywany przez s na LCD */
      s++; 						/* Zwiększ s (przygotuj nastepny znak) */
      	    }
    	  }
    void lcdxy(unsigned char w, unsigned char k)   /* Procedura ustawienia współrzędnych  
    						     kursora */
    {
    pisz_na_lcd ((w*0x40+k)|0x80); 		/* Rozkaz sterownika LCD ustawiający  						            kursor w określonych współrzędnych */
    }
    void lcd_init(void)				/* Procedura inicjalizacji wyświetlacza LCD */
     {
    _delay_ms(15); 				/* czekaj 15ms */
    CLR_E; 					/* E = 0 */
    CLR_RS; 					/* RS = 0 */ 
    char a; 						/* Zmianna licznikowa */
    for(a = 0; a < 3; a++) 				/* Powtórzenie trzykrotne bloku instrukcji */
      {
      SET_E; 					/* E = 1 */
      LCD &= 0x3F; 
      CLR_E; 					/* E = 0 */
      _delay_ms(5);; 				/* Czekaj 5ms */
        }
    SET_E; 					/* E = 1 */
    LCD &= 0x2E; 
    CLR_E; 					/* E = 0 */
    _delay_ms(10); 				/* Czekaj 10ms */
    pisz_instr(0x28); 				/* interfejs 4-bity, 2-linie, znak 5x7 */
    pisz_instr(0x08); 				/* wyłącz LCD, kursor i miganie*/
    pisz_instr(0x01); 				/* Czyść LCD */
    pisz_instr(0x0f); 				/* włącz LCD, kursor i mruganie */
      }
    
    
    
    
    
    
    int main(void) 
    {   
    // unsigned char a;		/* Deklaracja zmiennej a */
    DDRD = 0xFF;		/* Konfiguracja portów we/wy */
    PORTD = 0xFF;
    lcd_init();			/* Inicjalizacja LCD */
    lcdxy(0,0);			/* Ustawia kursor w pierwszym wierszu i pierwszej kolumnie */
    DDRB=0xff; 
    
    
    int i; 
    //**********************************
    
    //(*)
    {
    lcdxy(0,0);		/* Ustawia kursor w pierwszym wierszu i pierwszej kolumnie */
    pisz_text("obroty w prawo I");
    for(i=0; i<5 ;i++) //powtórzenie bloku instrukcji 102 kroki pełen obrot
    {
    
    PORTB=0x99;
    _delay_ms(1); // czekaj 2000ms 
    PORTB=0xAA;
    _delay_ms(1);
    PORTB=0x66;
    _delay_ms(1);
    PORTB=0x55;
    _delay_ms(1);
    pisz_instr(0x01);
    }
    
    pisz_text("obroty w lewo I");
    for(i=0; i<5 ;i++)
    {	
    PORTB=0x99;
    _delay_ms(1); // czekaj 2000ms 
    PORTB=0x55;
    _delay_ms(1);
    PORTB=0x66;
    _delay_ms(1);
    PORTB=0xAA;
    _delay_ms(1);	
    pisz_instr(0x01);
    }
    //*************************
    
    //(**)
    
    lcdxy(0,0);			/* Ustawia kursor w pierwszym wierszu i pierwszej kolumnie */
    
    pisz_text("obroty w prawoII");
    for(i=0; i<5 ;i++) //powtórzenie bloku instrukcji 102 kroki pełen obrot
    {
    PORTB=0x99;
    _delay_ms(9); // czekaj 2000ms 
    PORTB=0xAA;
    _delay_ms(9);
    PORTB=0x66;
    _delay_ms(9);
    PORTB=0x55;
    _delay_ms(9);
    pisz_instr(0x01);
    }
    
    pisz_text("obroty w lewo II");
    for(i=0; i<5 ;i++)
    {	
    PORTB=0x99;
    _delay_ms(9); // czekaj 2000ms 
    PORTB=0x55;
    _delay_ms(9);
    PORTB=0x66;
    _delay_ms(9);
    PORTB=0xAA;
    _delay_ms(9);	
    pisz_instr(0x01);
    }
    }
    }


    Dodałem znaczniki [code].
    Proszę o nich pamiętać w przyszłości.
    [zumek]
  • #17 8967404
    ppawel12
    Poziom 16  
    Weź edytuj swój post i dodaj kod programu jak powinno, ponieważ takie czytanie meczy i się gubię z nawiasami brak tabulatorów :/
    Użyjspecjalnych klawiszy co masz do dodania kodu
REKLAMA