|
Виж темите без отговор | Виж активните теми
Дата и час: Вто Юли 28, 2026 12:41 am
| Автор |
Съобщение |
|
Ки4о
Ранг: Форумен бог
Регистриран на: Съб Юли 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 -> А или * се изписва нещо различно от цифра и после тава една боза.....
Въпроса ми е:Когато се работи с буквено-цифрена клавиатура отделно ли се пишат подпрограми за сканиране или след всеки скан на клавиатурата се търси кой е клавиша,дали може той да бъде натиснат в това меню,... (стават много проверки,губи се памет).За момента съм го направил с идеята който натиска бутоните- знае какво прави  ,но мисля да го направя дуракоустойчиво та тези проверки ще трябва да ги правя.Мисля да ги направя 2 подпрограми - за букви и за цифри отделно но има ли друг по-елегантен начин да се излезе от проблема ?
|
| Пет Яну 26, 2007 9:04 pm |
|
 |
|
Dimitar
Ранг: Форумен бог
Регистриран на: Пет Ное 12, 2004 3:38 pm Мнения: 9103 Местоположение: Chicago, IL
|
 Re: 4x4 Keypad
Нещо немога да ти схвана мисълта за да ти отговоря за програмата, но когато правиш нещо никога не изхождай от презумцията, че който ще работи с него - ще знае какво да прави. Напротив даже - най-добрия тест за откриване на грешки в едно устройство е да го дадеш на някой, който идея си няма как работи. Когато ти си го тестваш - акъла ти никога няма да роди комбинация, която не е правилна - на тъпаците акъла им ражда какви ли не неща  .
|
| Пет Яну 26, 2007 9:32 pm |
|
 |
|
ToHu
Ранг: Форумен бог
Регистриран на: Нед Сеп 26, 2004 9:21 pm Мнения: 30686 Местоположение: София
|
 Re: 4x4 Keypad
Потвърден факт
А относно питането .. нещо не схващам, call Scan_KBD вика функция, чийто резултат се записва във W регистъра, като се върнеш я ползваш директно, това ОК. Идеята до някъде е следната редполагам, на клавиш нула имаш нула, на клавиш 1 имаш едно ..... какво имаш на клавиш А ... защото към 1 добавящ 30 и става хекса, но ако за А връща 10, няма да получиш А, това едното, може би си го събразил.
Освен това ако опресняването е на прекъсване, таймер да речем, може да чупиш W регистъра .... и не разбирам две неща 0-9, А-F са 16 бутона, освн ако не съм се объркал нещо .. тези * и # къде са вързани или не си 4х4 или а нщо не разбирам, за да е така триабва да е 3х6 18 бутона не 16.
|
| Пет Яну 26, 2007 9:42 pm |
|
 |
|
fuser
Ранг: Ориентиран
Регистриран на: Сря Юли 05, 2006 1:54 pm Мнения: 279
|
 Re: 4x4 Keypad
защо не се обадиш да пием по нещо и да обсъдим проблема 
|
| Пет Яну 26, 2007 10:44 pm |
|
 |
|
miro_atc
Ранг: Форумен бог
Регистриран на: Нед Фев 26, 2006 6:52 pm Мнения: 11266 Местоположение: Добрич
|
 Re: 4x4 Keypad
Не знам при ПИК как е, но обикновено при другите процесорчета сканирането на клавиатура не е точно "подпрограма"...
Но както и да си направил вече функцията за сканирането, щом работи няма значение... Само дето не мога да разбера какъв ти е проблема да си направиш функции примерно getchar() и getdigit() които викат твоята Scan_KBD() докато не бъде натиснат правилен клавиш и вместо скан-код ти връщат ASCI ?
|
| Съб Яну 27, 2007 12:34 am |
|
 |
|
Ки4о
Ранг: Форумен бог
Регистриран на: Съб Юли 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,*,# ,Извинявам се за грешката по-горе
* ми отговаря на Е,# на F.Когато получа стойността на бутона в temp,добавяйки Н'30' директно получавам ASCII а, * и # са ми Еsc и Ентер.Работата е там че като се сканира за число и не е натиснато числото а * например се получава 0x0E +0x30 -> друг аски символ.
Силно съм се замислил над решението - сканирам за число и изход едновременно.Ако се подаде друга комбинация- програмата не реагира и си иска число или изход.Работата е че кода става тромав а търся по-елегантно решение.Надявам се да съм обяснил проблема дето ме човърка.
@fuser, ще пием по бира но в момента съм много под пара,само малко да ми мине от главата и съм на линия 
|
| Съб Яну 27, 2007 12:49 pm |
|
 |
|
Predator_MF
Ранг: Форумен бог
Регистриран на: Чет Окт 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 а е натиснат някакъв друг) - пак можеш да го решиш със проста табличка, в която елементите ще показват кои символи ще се показват на дисплея, пример:
С една функция проверяваш дали натиснатия бутон е някой от тези, ако не е, просто го игнорираш. Има варианти още много разбира се, не виждам какво обаче в тия функции ти се струва тромаво, микросекунда ли цепиш или FLASH-а не ти стига ?!
|
| Съб Яну 27, 2007 1:19 pm |
|
 |
|
evc
Ранг: Напреднал
Регистриран на: Пет Окт 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 |
|
 |
|
mndsl
Ранг: Новодошъл
Регистриран на: Вто Май 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 |
|
 |
|
evc
Ранг: Напреднал
Регистриран на: Пет Окт 21, 2005 8:45 am Мнения: 499
|
И през ум не ми е минавало да му пиша програмата, исках да му кажа, че преобразуването може да стане с проста таблица, но ето го преведено на асемблер тогава:
_________________ Простотията е Божи дар, но човек не бива да парадира с подаръците си!
|
| Съб Яну 27, 2007 2:40 pm |
|
 |
|
Ки4о
Ранг: Форумен бог
Регистриран на: Съб Юли 22, 2006 9:50 pm Мнения: 1638
|
Работат е там че работя с много таблици - и нещо мястото взе да не стига - проца е 16F877 но работата с таблици е удобна в банка0 от другите банки ако трябва да се четат таблици - става каша,не че не се оправям в нея,ама..
Правя го по втория начин - на менюта дето се искат само цифри и */#,останалото игнорирам и на менюта само с букви - игнорирам цифрите.Това го оправих преди малко и работи-
Благодаря на всички дали съвети до сега
Забозявам нещата като следя за комбинации от 2 натиснати клавиша едновременно
Сега това ще го правя,но още нещо нямам идея точно как.Въпроса е как се прави това по принцип- кода сам ще си го напиша.
|
| Съб Яну 27, 2007 3:06 pm |
|
 |
|
evc
Ранг: Напреднал
Регистриран на: Пет Окт 21, 2005 8:45 am Мнения: 499
|
Аз лично избягвам да ползвам комбинации от два натиснати клавиша!
Прави се като не прекъсваш сканирането при откриване на натиснат клавиш, а продължаваш до края. На твое място бих изхабил още един байт и бих връщал от подпрограмата за сканиране на клавиатурата два байта, като всеки бит от тях ще ми отговаря на съответния бутон - "1" - натиснат, "0" - отпуснат. Сканираш поредния бутон и ако е натиснат вдигаш кери флага и завърташ двата байта наляво. Ако не е натиснат - нулираш кери флага преди завъртането. Така 16 пъти за 16-те бутона.
_________________ Простотията е Божи дар, но човек не бива да парадира с подаръците си!
|
| Съб Яну 27, 2007 3:37 pm |
|
 |
|
miro_atc
Ранг: Форумен бог
Регистриран на: Нед Фев 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 |
|
 |
|
Ки4о
Ранг: Форумен бог
Регистриран на: Съб Юли 22, 2006 9:50 pm Мнения: 1638
|
Проблема го реших.Благодаря на всички отзовали се за съветите и сорсовете. 
|
| Съб Яну 27, 2007 10:08 pm |
|
 |
|
fuser
Ранг: Ориентиран
Регистриран на: Сря Юли 05, 2006 1:54 pm Мнения: 279
|
сподели решението с нас ... няма да е лошо да го знаем!!! аз пък ползвам различни подпрограми към самият дисплей и когато се наложи да покажа цифра, буква или знак - минавам през съответната подпрограма.
|
| Нед Яну 28, 2007 6:47 pm |
|
|
Кой е на линия |
Потребители разглеждащи този форум: 0 регистрирани и 1 госта |
|
Вие не можете да пускате нови теми Вие не можете да отговаряте на теми Вие не можете да променяте собственото си мнение Вие не можете да изтривате собствените си мнения Вие не можете да прикачвате файл
|
|