<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="pl-pl">
<link rel="self" type="application/atom+xml" href="https://forum.atnel.pl/feed.php?f=23&amp;t=20109&amp;mode" />

<title>ATNEL tech-forum</title>
<link href="https://forum.atnel.pl/index.php" />
<updated>2018-01-30T00:43:17+01:00</updated>

<author><name><![CDATA[ATNEL tech-forum]]></name></author>
<id>https://forum.atnel.pl/feed.php?f=23&amp;t=20109&amp;mode</id>
<entry>
<author><name><![CDATA[piceropc]]></name></author>
<updated>2018-01-30T00:43:17+01:00</updated>
<published>2018-01-30T00:43:17+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=20109&amp;p=202932#p202932</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=20109&amp;p=202932#p202932"/>
<title type="html"><![CDATA[Obsługa klawiatury 4x4]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=20109&amp;p=202932#p202932"><![CDATA[
Cześć<br /><br />   Dopiero zaczynam działać z AVR'ami i chciałem poddać pod ocenę procedurę obsługi klawiatury matrycowej 4x4. <br />Wiedzę zaczerpnąłem z artykułu dotyczącego obsługi klawiszy: <!-- m --><a class="postlink" href="http://mirekk36.blogspot.com/2012/10/obsuga-klawiszy-zwoka-czasowa-cd3.html" >http://mirekk36.blogspot.com/2012/10/ob ... a-cd3.html</a><!-- m --><br />Wykorzystałem część rozwiązań jak możliwość przekazywania funkcji do procedury bazowanie na timerach programowych oraz nazewnictwo części zmiennych. Całkowicie nowa jest struktura procedury z poniższymi właściwościami:<br /><br />-Eliminacja drgań styków przy naciśnięciu i zwolnieniu klawisza<br />-Nie reagowanie w przypadku wystąpienia szpilkowych zakłóceń na pinach klawiatury<br />-Niezależny przydział każdej linii klawiatury do dowolnego pinu w dowolnym porcie<br />-Auto powtarzanie znaków przy długim naciśnięciu - ustalanie zwłoki do powtarzania oraz okresu pomiędzy powtórzeniami.<br />-Procedura nieblokująca oparta na znaczniku &quot;klock&quot; i poleceniu Switch symulująca automat stanowy.<br />-Przekazywanie znaku do bufora. W przypadku nie odczytania z bufora znaku procedura nie nadpisuje go blokując odczyt kolejnych znaków.<br />-Zabezpieczenie kontrolera przed zwarciem pinów przy jednoczesnym naciśnięciu kilku klawiszy przez odłączanie nieskanowanych kolumn poprzez Hi-Z<br /><br />Wymaga podciągnięcia 4 linii wejściowych do Vcc poprzez rezystory - w moim przypadku 33kOhm do linii PD4-PD7.<br />Wyeksportowana procedura z Eclipsa: KeyPad4x4_MultiPort.zip<br /><br />i listing głównej procedury:<br />[syntax=c]*<br /> * keypad4x4.c<br /> *<br /> *  Created on: 12 sty 2018<br /> *      Author: Piotr<br /> */<br /><br />#include &lt;avr/io.h&gt;<br />#include &lt;util/delay.h&gt;<br />#include &quot;keypad4x4.h&quot;<br /><br />volatile uint8_t Timer1,Timer2,Timer3;<br />uint8_t convertpadled&#91;16&#93; = {1,4,7,  17  ,2,5,8,0,3,6,9,  19  ,10,11,12,13}; // Tablica konwersji<br /><br />void keypad4x4( TKEYPAD4X4 * kpad) {<br /><br />register uint8_t key_pad = (*kpad-&gt;KPIN0 &amp; kpad-&gt;mask0) &amp;&amp; (*kpad-&gt;KPIN1 &amp; kpad-&gt;mask1) &amp;&amp; (*kpad-&gt;KPIN2 &amp; kpad-&gt;mask2) &amp;&amp; (*kpad-&gt;KPIN3 &amp; kpad-&gt;mask3);<br /> uint8_t row,col;<br /> uint8_t num_key;<br /><br /> row=0; col=0;<br /><br />switch(kpad-&gt;klock) {<br />case 0:<br />if ( !key_pad &amp;&amp; Timer1==0 ) {// Czekanie na naciśnięcie lub wygaśnięcie drgań<br />// po puszczeniu klawisza<br />Timer1=2;<br />Timer2=kpad-&gt;wait_time;// Ustalanie czasu do powtarzania klawiszy<br />kpad-&gt;klock=1;// Skok do następnej sekcji obsługi<br />}<br /><br />break;<br /><br />case 1:<br />if ( Timer1==0 ) {// Czekanie na wygaśnięcie drgań po naciśnięciu<br />if (!key_pad) {// Jeżeli dalej naciśnięty klawisz<br /><br />//*kpad-&gt;KDDR4 |= kpad-&gt;mask4;// pozostawienie 1 aktywnej kolumny - linia niewymagana<br />*kpad-&gt;KDDR5 &amp;= ~kpad-&gt;mask5;// KPIN4/mask4 w klawiaturze na (GND)<br />*kpad-&gt;KDDR6 &amp;= ~kpad-&gt;mask6;// pozostałe 3 jako Hi-Z<br />*kpad-&gt;KDDR7 &amp;= ~kpad-&gt;mask7;//<br /><br />while ((col&lt;4) &amp;&amp; (row==0)) {<br /><br />if (col==1) {<br />*kpad-&gt;KDDR4 &amp;= ~kpad-&gt;mask4;// pozostawienie 1 aktywnej kolumny<br />*kpad-&gt;KDDR5 |= kpad-&gt;mask5;// KPIN4/mask5 w klawiaturze na (GND)<br />}<br />if (col==2) {<br />*kpad-&gt;KDDR5 &amp;= ~kpad-&gt;mask5;// pozostawienie 1 aktywnej kolumny<br />*kpad-&gt;KDDR6 |= kpad-&gt;mask6;// KPIN4/mask6 w klawiaturze na (GND)<br />}<br />if (col==3) {<br />*kpad-&gt;KDDR6 &amp;= ~kpad-&gt;mask6;// pozostawienie 1 aktywnej kolumny<br />*kpad-&gt;KDDR7 |= kpad-&gt;mask7;// KPIN4/mask7 w klawiaturze na (GND)<br />}<br /><br />row +=   !(*kpad-&gt;KPIN0 &amp; kpad-&gt;mask0);<br />row += ( !(*kpad-&gt;KPIN1 &amp; kpad-&gt;mask1) &lt;&lt; 1 );<br />row += ( !(*kpad-&gt;KPIN2 &amp; kpad-&gt;mask2) &lt;&lt; 1 )|( !(*kpad-&gt;KPIN2 &amp; kpad-&gt;mask2) );<br />row += ( !(*kpad-&gt;KPIN3 &amp; kpad-&gt;mask3) &lt;&lt; 2 );<br /><br />col++;<br />}<br /><br />*kpad-&gt;KDDR4 |= kpad-&gt;mask4;// Sciągnięcie linii wyjściowych klawiatury do masy<br />*kpad-&gt;KDDR5 |= kpad-&gt;mask5;// Przygotowanie do oczekiwania na naciśnięcie<br />*kpad-&gt;KDDR6 |= kpad-&gt;mask6;//<br />*kpad-&gt;KDDR7 |= kpad-&gt;mask7;//<br /><br />num_key = ((col-1)&lt;&lt;2) + row - 1;// Obliczanie numeru klawisza<br />kpad-&gt;key=convertpadled&#91;num_key&#93;;  // Wywołanie konwersji num_key -&gt; char_led<br /><br />if (kpad-&gt;buffer == 255) {// Jeżeli bufor pusty<br />if (kpad-&gt;kfun1) kpad-&gt;kfun1();<br />kpad-&gt;buffer = kpad-&gt;key;// zapis do buffora<br />}<br />kpad-&gt;klock=2;// Skok do następnej sekcji<br />} else {<br />Timer1=10;// Wyjście w przypadku uruchomienia obsługi klawisza<br />kpad-&gt;klock=255;// z powodu zakłóceń szpilkowych<br />}<br />}<br />break;<br /><br />case 2:<br />if (!key_pad ) {// Podczas dalszego trzymania klawisza<br />if ( Timer2==0 ) {// czekanie na akcje długiego wciśnięcia<br />if (kpad-&gt;buffer == 255) {// Zapis do bufora gdy jest pusty<br />kpad-&gt;buffer = kpad-&gt;key;<br />if (kpad-&gt;kfun2) kpad-&gt;kfun2();// opcjonalna funkcja<br />}<br />Timer3=kpad-&gt;reapet_time;// Ustalenie okresu pomiędzy powtórzeniami<br />kpad-&gt;klock=3;// Skok do następnej sekcji<br />}<br />} else {<br />Timer1=10;// Puszczenie klawisza przed czasem akcji długiego<br />kpad-&gt;klock=255;// wciśnięcia. Wyjście z obsługi klawisza.<br />}<br />break;<br /><br />case 3:<br />if (key_pad) {// Po uruchomieniu akcji długiego wciśnięcia<br />Timer1=10;// Czekanie na puszczenie klawisza<br />kpad-&gt;klock=255;// Blokuje cykliczne akcje przy stałym wciśnięciu<br />} else {<br />if (Timer3==0) {<br />Timer3=kpad-&gt;reapet_time;// Odnowienie czasu autopowtarzania<br />if (kpad-&gt;buffer == 255) {// Zapis do bufora gdy jest pusty<br />kpad-&gt;buffer = kpad-&gt;key;<br />if (kpad-&gt;kfun2) kpad-&gt;kfun2();// opcjonalna funkcja<br />}<br />}<br />}<br />break;<br /><br />default:<br />kpad-&gt;klock=0;// Inicjalizacja znacznika sekwencji obsługi klawisza<br />kpad-&gt;key=255;<br />*kpad-&gt;KPIN4 &amp;= ~kpad-&gt;mask4;// Ustawienie na stałe stanu niskiego<br />*kpad-&gt;KPIN5 &amp;= ~kpad-&gt;mask5;// linii wyjściowych klawiatury<br />*kpad-&gt;KPIN6 &amp;= ~kpad-&gt;mask6;// Przełączanie pomiędzy<br />*kpad-&gt;KPIN7 &amp;= ~kpad-&gt;mask7;// Hi-Z  i  Level-Low (OUT)<br />*kpad-&gt;KDDR4 |= kpad-&gt;mask4;// Sciągnięcie linii wyjściowych klawiatury do masy<br />*kpad-&gt;KDDR5 |= kpad-&gt;mask5;// Przygotowanie do oczekiwania na naciśnięcie<br />*kpad-&gt;KDDR6 |= kpad-&gt;mask6;//<br />*kpad-&gt;KDDR7 |= kpad-&gt;mask7;//<br />}<br />}[/syntax]<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=18001">piceropc</a> — 30 sty 2018, o 00:43</p><hr />
]]></content>
</entry>
</feed>