Отговори на тема  [ 17 мнения ]  Отиди на страница 1, 2  Следваща
4x4 Keypad 
Автор Съобщение
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Съб Юли 22, 2006 9:50 pm
Мнения: 1638
Мнение 4x4 Keypad
При четене на клавиатура 4х4 освен цифри от 0-9 има и букви А-F + още 2 бутона '#' и '*'.Когато се сканира клавиатурата при въвеждане на данни и едновременното им изобразяване се получават маймуници(правя го на PIC16 )
Това е част от кода:
movf temp,0 ; вземане на стойността на бутона от клав.
movwf hund_reg ;записване в съответния буфер
addlw H'30' ; изобразяване на LCD
movwf LCD_temp ; --//--
call Scan_KBD ; отново сканиране на клавиатура и така нататък

Та ако си натиснал вместо 0 -> А или * се изписва нещо различно от цифра и после тава една боза.....
Въпроса ми е:Когато се работи с буквено-цифрена клавиатура отделно ли се пишат подпрограми за сканиране или след всеки скан на клавиатурата се търси кой е клавиша,дали може той да бъде натиснат в това меню,... (стават много проверки,губи се памет).За момента съм го направил с идеята който натиска бутоните- знае какво прави :roll: ,но мисля да го направя дуракоустойчиво та тези проверки ще трябва да ги правя.Мисля да ги направя 2 подпрограми - за букви и за цифри отделно но има ли друг по-елегантен начин да се излезе от проблема ?


Пет Яну 26, 2007 9:04 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пет Ное 12, 2004 3:38 pm
Мнения: 9103
Местоположение: Chicago, IL
Мнение Re: 4x4 Keypad
Ки4о написа:
За момента съм го направил с идеята който натиска бутоните- знае какво прави :roll:

Нещо немога да ти схвана мисълта за да ти отговоря за програмата, но когато правиш нещо никога не изхождай от презумцията, че който ще работи с него - ще знае какво да прави. Напротив даже - най-добрия тест за откриване на грешки в едно устройство е да го дадеш на някой, който идея си няма как работи. Когато ти си го тестваш - акъла ти никога няма да роди комбинация, която не е правилна - на тъпаците акъла им ражда какви ли не неща 8) .


Пет Яну 26, 2007 9:32 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Сеп 26, 2004 9:21 pm
Мнения: 30686
Местоположение: София
Мнение Re: 4x4 Keypad
Dimitar написа:
Ки4о написа:
За момента съм го направил с идеята който натиска бутоните- знае какво прави :roll:

Нещо немога да ти схвана мисълта за да ти отговоря за програмата, но когато правиш нещо никога не изхождай от презумцията, че който ще работи с него - ще знае какво да прави. Напротив даже - най-добрия тест за откриване на грешки в едно устройство е да го дадеш на някой, който идея си няма как работи. Когато ти си го тестваш - акъла ти никога няма да роди комбинация, която не е правилна - на тъпаците акъла им ражда какви ли не неща 8) .


Потвърден факт :)

А относно питането .. нещо не схващам, call Scan_KBD вика функция, чийто резултат се записва във W регистъра, като се върнеш я ползваш директно, това ОК. Идеята до някъде е следната редполагам, на клавиш нула имаш нула, на клавиш 1 имаш едно ..... какво имаш на клавиш А ... защото към 1 добавящ 30 и става хекса, но ако за А връща 10, няма да получиш А, това едното, може би си го събразил.
Освен това ако опресняването е на прекъсване, таймер да речем, може да чупиш W регистъра .... и не разбирам две неща 0-9, А-F са 16 бутона, освн ако не съм се объркал нещо .. тези * и # къде са вързани или не си 4х4 или а нщо не разбирам, за да е така триабва да е 3х6 18 бутона не 16.


Пет Яну 26, 2007 9:42 pm
Профил
Ранг: Ориентиран
Ранг: Ориентиран

Регистриран на: Сря Юли 05, 2006 1:54 pm
Мнения: 279
Мнение Re: 4x4 Keypad
защо не се обадиш да пием по нещо и да обсъдим проблема :)


Пет Яну 26, 2007 10:44 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Фев 26, 2006 6:52 pm
Мнения: 11266
Местоположение: Добрич
Мнение Re: 4x4 Keypad
Ки4о написа:
Въпроса ми е:Когато се работи с буквено-цифрена клавиатура отделно ли се пишат подпрограми за сканиране или след всеки скан на клавиатурата се търси кой е клавиша,дали може той да бъде натиснат в това меню,...


Не знам при ПИК как е, но обикновено при другите процесорчета сканирането на клавиатура не е точно "подпрограма"...
Но както и да си направил вече функцията за сканирането, щом работи няма значение... Само дето не мога да разбера какъв ти е проблема да си направиш функции примерно getchar() и getdigit() които викат твоята Scan_KBD() докато не бъде натиснат правилен клавиш и вместо скан-код ти връщат ASCI ?


Съб Яну 27, 2007 12:34 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Съб Юли 22, 2006 9:50 pm
Мнения: 1638
Мнение 
Проблема е следния - (явно не съм смогнал да обесня) - когато очакваме да е натиснат бутон за 5 ( примерно) а вместо това е натиснат # или някаква комбинация от клавиши на дисплея се изобразява друг символ.Temp ми е регистър от който се чете стойността на бутона натиснат от клавиатурата(след проверка дали действително е натиснат бутон,ако не е натиснат - чака се докато се натисне),добавя се към него Н'30' за да се получи ASCII стойността му и се праща към LCD-то за изобразяване . Ако след всяко натискане на бутон проверявам дали е буква,цифра,комбинация от буква/цифра отнема много време и памет.Ако се направят 3 подпрограми - една само цифрите да чете,една само буквите и една комбинациите става така че на някой места от програмата трябва да викам и трите подпрограми последователно защото може да искам да прекратя режим на въвеждане на данни (цифри) и да отида към друго меню.Тази програмя я пиша на асемблер а не на С и не мога да ползвам предложението на @miro.
Клавиатурата е с 16 бутона-0,1,2,3,4,5,6,7,8,9,A,B,С,D,*,# ,Извинявам се за грешката по-горе :oops:
* ми отговаря на Е,# на F.Когато получа стойността на бутона в temp,добавяйки Н'30' директно получавам ASCII а, * и # са ми Еsc и Ентер.Работата е там че като се сканира за число и не е натиснато числото а * например се получава 0x0E +0x30 -> друг аски символ.
Силно съм се замислил над решението - сканирам за число и изход едновременно.Ако се подаде друга комбинация- програмата не реагира и си иска число или изход.Работата е че кода става тромав а търся по-елегантно решение.Надявам се да съм обяснил проблема дето ме човърка.
@fuser, ще пием по бира но в момента съм много под пара,само малко да ми мине от главата и съм на линия :)


Съб Яну 27, 2007 12:49 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Чет Окт 07, 2004 1:22 pm
Мнения: 1949
Местоположение: София
Мнение 
На тоя "проблем" със последните два символа "*" и "#" има много решения, сещам се за две най-прости в момента (тъй като пишеш на ASM) -
1. Правиш табличка със символите от клавиатурата
2. Два "if-a" на ASM проверяват специално за тези два знака

И в двата случая ще ти е по-удобно, ако имаш функция "get_kbchar()" която да ти връща не ASCII кода на бутона, а поредния му номер. В първия случай правиш една табличка с ASCII кодовете на бутоните -
Код:
db kb_chars "0,1,2,3,4,5,6,7,8,9,A,B,C,D,*,#"

и с някаква малка функция (10-ина реда ми идват на ум още сега, но мисля че и сам ще се справиш) "kb_to_ascii()" обръщаш съответния натиснат бутон от число във ASCII. Във втория случай - IF на ASM се прави с 4 реда в PIC, не вярвам да се затрудниш особено да напишеш два IF-a които да проверяват дали номера на бутона е 14 или 15, ако не можеш, свиркай ще ти измислим код веднага.

Другия ти проблем - искаш да изкарваш само "правилно" натиснати бутони (в примера ти като очакваш да е натиснат бутон 5 а е натиснат някакъв друг) - пак можеш да го решиш със проста табличка, в която елементите ще показват кои символи ще се показват на дисплея, пример:
Код:
db  valid_btns "1,2,4,5,8"

С една функция проверяваш дали натиснатия бутон е някой от тези, ако не е, просто го игнорираш. Има варианти още много разбира се, не виждам какво обаче в тия функции ти се струва тромаво, микросекунда ли цепиш или FLASH-а не ти стига ?!


Съб Яну 27, 2007 1:19 pm
Профил
Ранг: Напреднал
Ранг: Напреднал
Аватар

Регистриран на: Пет Окт 21, 2005 8:45 am
Мнения: 499
Мнение 
Най-простичко си мисля ей така можеш да го направиш:
Код:
const unsigned char key_code[16]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,
                                    0x38,0x39,0x41,0x42,0x43,0x44,0x2A,0x23};

unsigned char key_ascII(unsigned char key_nomb){
            return key_code[key_nomb];
}

_________________
Простотията е Божи дар, но човек не бива да парадира с подаръците си!


Съб Яну 27, 2007 1:41 pm
Профил ICQ
Ранг: Новодошъл
Ранг: Новодошъл

Регистриран на: Вто Май 23, 2006 4:56 pm
Мнения: 113
Местоположение: Варна
Мнение 
evc написа:
Най-простичко си мисля ей така можеш да го направиш:
Код:
const unsigned char key_code[16]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,
                                    0x38,0x39,0x41,0x42,0x43,0x44,0x2A,0x23};

unsigned char key_ascII(unsigned char key_nomb){
            return key_code[key_nomb];
}


Човека пише програма на асемблер, а ти му даваш код на С!


Съб Яну 27, 2007 1:54 pm
Профил ICQ
Ранг: Напреднал
Ранг: Напреднал
Аватар

Регистриран на: Пет Окт 21, 2005 8:45 am
Мнения: 499
Мнение 
Цитат:
Човека пише програма на асемблер, а ти му даваш код на С!

И през ум не ми е минавало да му пиша програмата, исках да му кажа, че преобразуването може да стане с проста таблица, но ето го преведено на асемблер тогава:
Код:

key_ascII:
movfw key_nmb
addwf PCL,f
retlw    0x30
retlw    0x31
retlw    0x32
retlw    0x33
retlw    0x34
retlw    0x35
retlw    0x36
retlw    0x37
retlw    0x38
retlw    0x39
retlw    0x41
retlw    0x42
retlw    0x43
retlw    0x44
retlw    0x2A
retlw    0x23

_________________
Простотията е Божи дар, но човек не бива да парадира с подаръците си!


Съб Яну 27, 2007 2:40 pm
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Съб Юли 22, 2006 9:50 pm
Мнения: 1638
Мнение 
Работат е там че работя с много таблици - и нещо мястото взе да не стига - проца е 16F877 но работата с таблици е удобна в банка0 от другите банки ако трябва да се четат таблици - става каша,не че не се оправям в нея,ама..
Правя го по втория начин - на менюта дето се искат само цифри и */#,останалото игнорирам и на менюта само с букви - игнорирам цифрите.Това го оправих преди малко и работи-
Благодаря на всички дали съвети до сега
Забозявам нещата като следя за комбинации от 2 натиснати клавиша едновременно :oops:
Сега това ще го правя,но още нещо нямам идея точно как.Въпроса е как се прави това по принцип- кода сам ще си го напиша.


Съб Яну 27, 2007 3:06 pm
Профил
Ранг: Напреднал
Ранг: Напреднал
Аватар

Регистриран на: Пет Окт 21, 2005 8:45 am
Мнения: 499
Мнение 
Аз лично избягвам да ползвам комбинации от два натиснати клавиша!
Прави се като не прекъсваш сканирането при откриване на натиснат клавиш, а продължаваш до края. На твое място бих изхабил още един байт и бих връщал от подпрограмата за сканиране на клавиатурата два байта, като всеки бит от тях ще ми отговаря на съответния бутон - "1" - натиснат, "0" - отпуснат. Сканираш поредния бутон и ако е натиснат вдигаш кери флага и завърташ двата байта наляво. Ако не е натиснат - нулираш кери флага преди завъртането. Така 16 пъти за 16-те бутона.

_________________
Простотията е Божи дар, но човек не бива да парадира с подаръците си!


Съб Яну 27, 2007 3:37 pm
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Фев 26, 2006 6:52 pm
Мнения: 11266
Местоположение: Добрич
Мнение 
Стандартно се прави с клавиатурен драйвер...

Вариант за "драйвер" е една функция която се вика през фиксиран интервал от време (10-20ms). Когато имаш прекъсване на пиновете (повечето процесори имат), прекъсване на кой да е клавиш стартира цикличното извикване на тая функция и забранявава следващи прекъвания от тия пинове. На всяко влизане функцийката сканира клавиатурата и тако докато се сканира че няма повече натиснати клавиши. Тогава циклличното извикване (по таймер) се изкллючва и се разрешава прекъсванията от клавиатурните пинове....

Функцийката си следи натиснитите клавиши и генерира кей-код за събития като "натиснат" клавиш, "отпуснат" клавиш и "садържан" клавиш и тия кодове се пъхат в малко fifo. Всеки код е само за един клавиш, но application-страната която вади от фифото може да следи за едновременно натиснати клавиши ако проверява за поредица применро НАТИСНАТ_А, НАТИСНАТ_В, ОТПУСНАТ_В, ОТУСНАТ_А...
Хубавато на тая схема е че всичко зависи от приложението - ако иска се интересува от едновременно натиснати клавиши, а ако не иска не се интересува. Второто позволява да си бачка добре и при дефектен клавиш (задържал).


Ето ти примерна функция, сорри че е на С, ама ако ти харесва идеята надявам се ще си я портнеш на асемблер:

Код:



unsigned char button_ticks[16];
unsigned int btns_pressed;

const unsigned char Key[]=
   { KEY_7, KEY_8, KEY_9, KEY_0, KEY_1, KEY_2, KEY_3,KEY_UP, KEY_OK,
     KEY_F1, KEY_C, KEY_NO, KEY_4, KEY_5, KEY_6, KEY_DOWN};

void Keyboard_task(void)
{
   unsigned char col,pos;
      unsigned char all_released = 1;
   unsigned int mask, new_keys;


   PIN_IDIS(KEYREAD);      //disable keyboard pin interrupts
   PIN_CLEAR(KEYDRIVE);   //drive all to 0 to discharge parasitic caps
   PIN_DIR_IN(KEYDRIVE);   //disconnect all drive pins
   
   mask = 0x10;
   for(col = 0; col<4; col++)
   {

      KEYDRIVE_P.out |= mask;   //Set one drive pin at 1
        KEYDRIVE_P.dir |= mask;
      

        new_keys <<= 4;
        new_keys |= PIN_IN(KEYREAD);

      PIN_CLEAR(KEYDRIVE);
      PIN_DIR_IN(KEYDRIVE);

        mask<<=1;
    }

   
    mask = 0x8000;
    for(pos=0;pos < 16; pos++)
   {
      if (mask & new_keys)
      {//button pressed
            all_released = 0;
         button_ticks[pos]++;
         if(mask & btns_pressed)
         { //button hold?
            if (button_ticks[pos] > REPEAT_TIME)
            {
               button_ticks[pos] = 0;
               post_key_code(KEY_REPEAT, Key[pos]);
            }
         } else
            if (button_ticks[pos] > PRESS_TIME)
            {
               button_ticks[pos] = 0;
               btns_pressed |= mask;
            post_key_code(KEY_PRESSED, Key[pos]);
            }
         
      } else
      {
         button_ticks[pos] = 0;
            if (mask & btns_pressed)
            {
               btns_pressed &= ~mask;
      
            post_key_code(KEY_RELEASED, Key[pos]);
            }
      }
      
        mask >>=1;
   }

   if(all_released)
   {
      PIN_CLR_EVENT(KEYREAD);   
      PIN_IE(KEYREAD);
      PIN_OUT_1(KEYDRIVE);
   }

}




Функията ползва 16 байта в която си брой дебонса на всеки клавиш и един int (16 бита) за състоянието на всеки клавиш..


Съб Яну 27, 2007 9:39 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Съб Юли 22, 2006 9:50 pm
Мнения: 1638
Мнение 
Проблема го реших.Благодаря на всички отзовали се за съветите и сорсовете. :)


Съб Яну 27, 2007 10:08 pm
Профил
Ранг: Ориентиран
Ранг: Ориентиран

Регистриран на: Сря Юли 05, 2006 1:54 pm
Мнения: 279
Мнение 
сподели решението с нас ... няма да е лошо да го знаем!!! аз пък ползвам различни подпрограми към самият дисплей и когато се наложи да покажа цифра, буква или знак - минавам през съответната подпрограма.


Нед Яну 28, 2007 6:47 pm
Профил
Покажи мненията от миналия:  Сортирай по  
Отговори на тема   [ 17 мнения ]  Отиди на страница 1, 2  Следваща

Кой е на линия

Потребители разглеждащи този форум: 0 регистрирани и 2 госта


Вие не можете да пускате нови теми
Вие не можете да отговаряте на теми
Вие не можете да променяте собственото си мнение
Вие не можете да изтривате собствените си мнения
Вие не можете да прикачвате файл

Търсене:
Иди на:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.
Хостинг и Домейни