|
Проблема с преобразованиями |
|
|
|
Nov 22 2011, 05:22
|
Местный
  
Группа: Участник
Сообщений: 248
Регистрация: 30-09-11
Пользователь №: 67 474

|
Здравствуйте. Реализую клавиатуру числовую 0-9. Для окончания ввода использую клавишу принятия ввода. Работаю с 1,2,3,4,5 значными цифрами, если введено чило, содержащее более 5 цифр, то ошибка. Как преобразовать из двоично-десятичной формы в двоичную знаю. Но вот как реализовать сохранение группы нажатых цифр в одну переменную 16-битную - вот проблема. Например ввели число 4563, надо чтобы оно было сохранено в 16-битной переменнойи и цифры были сохранены в нужной мне последовательности после нажатия клавиши "accept". Помогите, пожалуйста, в данной проблеме?
|
|
|
|
|
Nov 22 2011, 06:21
|
Частый гость
 
Группа: Участник
Сообщений: 105
Регистрация: 9-09-11
Пользователь №: 67 080

|
Цитата(max_mart @ Nov 22 2011, 08:22)  Здравствуйте. Реализую клавиатуру числовую 0-9. Для окончания ввода использую клавишу принятия ввода. Работаю с 1,2,3,4,5 значными цифрами, если введено чило, содержащее более 5 цифр, то ошибка. Как преобразовать из двоично-десятичной формы в двоичную знаю. Но вот как реализовать сохранение группы нажатых цифр в одну переменную 16-битную - вот проблема. Например ввели число 4563, надо чтобы оно было сохранено в 16-битной переменнойи и цифры были сохранены в нужной мне последовательности после нажатия клавиши "accept". Помогите, пожалуйста, в данной проблеме? я уже сталкивался с этой проблемой. Решил всё очень просто. Ввел счетчик нажатий клавиш. Выделил для каждого десятичного разряда байт в ОЗУ.Нажал первый раз - сохранил в область ОЗУ "тысячи", нажал второй раз -сотни, нажал третий раз - десятки, четвертый - единицы. Так же счетчиком включаю кнопку "стереть по символьно". Т.е. если нажал >=1-ого раза - загорается надпись удалить и кнопка "удалить" становиться активной. Когда ввел значение полностью загорается надпись "принять", по нажатии соответствующей кнопки "принять" умножаем число из ОЗУ"1000" на тысячу, затем сотни, десятки, единицы, и все суммируем.
|
|
|
|
|
Nov 22 2011, 06:27
|

внештатный сотрудник
     
Группа: Участник
Сообщений: 2 458
Регистрация: 10-05-08
Из: МО, Медвежьи озера
Пользователь №: 37 401

|
Цитата(max_mart @ Nov 22 2011, 09:22)  Помогите, пожалуйста, в данной проблеме? на кодирование кода клавиши (от 0 до 9) нужно 3 бита, для запоминания 5 кодов соответственно нужно 15 бит... так что просто последовательно пишете в 16-битный регистр коды клавиш в порядке нажатия, да и все  стоп, не 3, а 4 бита нужно... надо подумать
Сообщение отредактировал stells - Nov 22 2011, 06:29
|
|
|
|
|
Nov 22 2011, 06:39
|

Познающий...
     
Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125

|
QUOTE (max_mart @ Nov 22 2011, 13:22)  Здравствуйте. Помогите, пожалуйста, в данной проблеме? Здравствуйте! Необходимо, как говорят, отделить мух от котлет) Отдельно реализуйте функции ввода с клавиатуры, отдельно складывайте числа в переменную. Пусть у Вас есть функция readKey(), которая возращает скан-код нажатой клавиши, или, если есть буфер, то позволяет считать последовательность нажатых кнопок. Допустим, Вы приняли коды 15, 13, 17, 18, которые обозначают цифры 5, 3, 7 и 8. Коды могут быть любыми, зависит от аппаратной реализации клавиатуры. Могут быть и сразу необходимые нам цифры. Однако у клавиши "ВВОД" все равно будет какой-то свой код, например 20. Как из скан-кодов получить цифры, объяснять не буду. Используется вычитание. Поскольку, как правило, заранее не известно, сколько разрядов будет в числе, Вы не знаете сколько цифер введет пользователь, прежде, чем нажать "ВВОД". Следовательно, цифры необходимо складывать в буфер. Затем считаете количество цифр. Так Вы знаете сколько разрядов необходимо. В нашем случае 4 (цифры 5, 3, 7 и 8). Значит максимальное число, введенное пользователем, может быть 9999. Проверяете, входит в 16 разрядов. Да, входит, в независимости от того, знаковая или беззнаковая переменная используется. Если бы не входила - выдали бы ошибку, не задумываясь. Далее, из буфер выбираете цифры в любом порядке, но с учетом веса. Например 5 - это тысячи, 8 - единицы. Далее, проходясь циклом по буферу, выбираете цифру, домножаете на "вес" и суммируете результат в переменную, предварительно ее обнулив. Примерно так (цикл не пишу нарочно, просто по шагам): uint16_t sum. sum = 0; sum += 5 * 1000; sum += 3 * 100; sum += 7 * 10; sum += 8; Вроде все. Если ошибся, коллеги поправят
--------------------
Выбор.
|
|
|
|
|
Nov 22 2011, 07:16
|
Местный
  
Группа: Участник
Сообщений: 248
Регистрация: 30-09-11
Пользователь №: 67 474

|
Во первых я замарачиваться не стал сделал клаву просто от ножки МК через резистор на конпку. Во вторых цифре от 0-9 соответствует 4 разрядный двоичный код, поэтому 5 цифр числа просто в 16-битную пер. не уместится, если исп. ее для хран. нажатой цифры. И как я уже выше написал: Я не пойму только одного момента: как мне сохранить нажатый код цифры, ячтобы в дальнейшем ее расчитать и получить нужное мне число. Вот пример на 6 цифрах: unsigned char counter=0; // для подсчета кол-ва введенных цифр unsigned key[6]; // массив для хранения цифры для опред. кнопки unsigned int addr=0;
if (!ZERO) { writed(10); // 0 on LCD key[0]=0; counter++; } if (!ONE) { if (pp == 0) { writed(1); // 1 on LCD key[1]=1; counter++; } pp=10000; } if (!TWO) { if (pp == 0) { writed(2); // 2 on LCD key[2]=2; counter++; } pp=10000; } if (!THREE) { if (pp == 0) { writed(3); // 3 on LCD key[3]=3; counter++; } pp=10000; } if (!FOUR) { if (pp == 0) { writed(4); // 4 on LCD key[4]=4; counter++; } pp=10000; } if (!FIVE) { if (pp == 0) { writed(5); // 5 on LCD key[5]=5; counter++; } pp=10000; }
if (!ACCEPT) // accept input data(end of inputting data) { if (pp == 0) { if (counter == 1) // 1 digit { // надо сохр введеные цифры в пер. addr, чтобы получить 1 значное число counter=0; //..
} if (counter == 2) // 2 digits { // надо сохр введеные цифры в пер. addr, чтобы получить 2 значное число counter=0; //..
} if (counter == 3) // 3 digits { // надо сохр введеные цифры в пер. addr, чтобы получить 3 значное число counter=0; //..
} if (counter == 4) // 4 digits { // надо сохр введеные цифры в пер. addr, чтобы получить 4 значное число counter=0; //..
} if (counter == 5) // 5 digits { // надо сохр введеные цифры в пер. addr, чтобы получить 5 значное число counter=0; //.. } if (counter > 5) { counter=0; // отображаю ошибку } Вот как мне сохр. в пер. addr я не знаю. Я знаю что, чтобы получить например число 453 из введенных цифр надо просто: 4*100+5*10+3=453 в 16 битной переменной. Но я не знаю как мне их сохранять при нажатии клавиши, чтобы не потерять последовательность. Помогите, пожалуйста с кодом? Дописать его, чтобы реализовать задуманное.
|
|
|
|
|
Nov 22 2011, 09:48
|

Профессионал
    
Группа: Свой
Сообщений: 1 202
Регистрация: 26-08-05
Из: Донецк, ДНР
Пользователь №: 7 980

|
Автор, как я понял, хочет получить, допустим, число 468, если ему нажмут кнопки 4, 6, 8.
Берёте одну переменную-накопитель, 16 бит. Инициализируете её нулём. Далее простой алгоритм - нажали какую-то цифру, вы получаете из какого-то сканкода саму цифру, текущий накопитель умножаете на 10 и прибавляете только что введённую цифру. Всё. Плюс контроль, чтобы накопитель не переполнился при очередном умножении. Захотите больше - сделайте накопитель не 16 бит, а 32, 64 .... Классический алгоритм с бородой ....
Зачем тут буфер, накопление n-разрядных кодов в нём и прочие сложности? Потом ведь всё равно этот буфер в число конвертить надо ... Буфер надо, если необходима возможность полного редактирования числа. Да и то - проще не сканкоды в буфер класть, а готовые цифры. Проще и понятнее. У вас же не матрица 105 клавиш от компа?
Сообщение отредактировал hd44780 - Nov 22 2011, 09:56
--------------------
Чтобы возить такого пассажира, необходим лимузин другого класса. (с) Мария Эдуарда
|
|
|
|
|
Nov 22 2011, 10:49
|

Частый гость
 
Группа: Участник
Сообщений: 98
Регистрация: 20-06-05
Пользователь №: 6 150

|
Цитата(max_mart @ Nov 22 2011, 14:10)  нет не матрица. Всего 9 клавиш. Я не могу сообразить по коду, как все это реализовать. Поэтому и выложил его. Чтобы объеденитьь его вместе с тем, что я просил. Помогите, плиз. Вам ведь уже четко показали. Осталось на код положить. Код Result = 0; while( GetCodeValue = GetCodeButton() != ENTER ){ Result *= 10; Result += GetCodeValue; } Где-то так... Но вопрос контроля за переполнением типа лежит на программисте. Об этом надо помнить, или вводить программный контроль.
Сообщение отредактировал ut1wpr - Nov 22 2011, 10:50
|
|
|
|
|
Nov 22 2011, 11:39
|

Профессионал
    
Группа: Свой
Сообщений: 1 202
Регистрация: 26-08-05
Из: Донецк, ДНР
Пользователь №: 7 980

|
Цитата(max_mart @ Nov 22 2011, 14:08)  зачем умножать на 10 и для чего прибавлять код кнопки? Чтобы преобразовать последовательность Ваших кнопок в число, которое Вы хотите поиметь на выходе сего алгоритма. Оно же для запоминания последовательности нажатий кнопок, о чём Вы спрашивали выше. Вы же сами написали где-то выше по теме: Я знаю что, чтобы получить например число 453 из введенных цифр надо просто: 4*100+5*10+3=453 в 16 битной переменной. Совершенно верно написали. Я этим умножением и сложением это и делаю. Цитата(max_mart @ Nov 22 2011, 14:08)  И потом у меня вверху указан код, который я реализую! Мне надо под него синхронизировать выше указанную проблему!!! А мне стало страшно, когда я увидел Ваш код  Им только детей маленьких пужать - какое страшное это программирование .... Отделите опрос клавиатуры от получения числа. А если Вы завтра захотите эту клавиатуру ещё в 10 местах опрашивать? Или поменять тип клавиатуры? Или ещё что-то? И что, будете 10 раз писать один и тот же алгоритм опроса? Я бы это делал как-то так: Код int GetCodeButton() { if (!ZERO) return 0;
if (!ONE) return 1;
.............
if (!ACCEPT) return 20; } // GetCodeButton
// Цикл получения числа // Накопитель word Result = 0; // счётчик введённых знаков int count=0; ......
while( 1 ) { int GetCodeValue = GetCodeButton();
// проверка Enter if (GetCodeValue==20) break; Result *= 10; Result += GetCodeValue;
count ++; // Проверка, что ввели 5 знаков if (count>5) break; } // while Проверку переполнения накопителя сами добавьте. Это Вам домашнее задание лично от меня  . Потому что контроля на 5 цифр недостаточно - число 99999 - 5 цифр, но в 16 бит оно не влезает.
Сообщение отредактировал hd44780 - Nov 22 2011, 11:54
--------------------
Чтобы возить такого пассажира, необходим лимузин другого класса. (с) Мария Эдуарда
|
|
|
|
|
Nov 22 2011, 12:45
|

Частый гость
 
Группа: Участник
Сообщений: 98
Регистрация: 20-06-05
Пользователь №: 6 150

|
Цитата(max_mart @ Nov 22 2011, 15:54)  ладно подумаю на накопителем. цифр всего 5, а максимальное число то у меня будит 65535 Не знаю, кто и кого там у вас по утрам будит, а код с проверкой будЕт такой: Код Result = 0; while( (GetCodeValue = GetCodeButton() != ENTER) && (Result <= 65535) ){ Result *= 10; Result += GetCodeValue; }
|
|
|
|
|
Nov 22 2011, 14:20
|
Местный
  
Группа: Участник
Сообщений: 214
Регистрация: 22-03-10
Из: Саратов
Пользователь №: 56 123

|
Цитата(ut1wpr @ Nov 22 2011, 16:45)  Не знаю, кто и кого там у вас по утрам будит, а код с проверкой будЕт такой: Код Result = 0; while( (GetCodeValue = GetCodeButton() != ENTER) && (Result <= 65535) ){ Result *= 10; Result += GetCodeValue; } Здесь проверка переполнения будет работать только, если Result - 32-х разрядная переменная. Беззнаковая 16-ти разрядная переменная всегда меньше или равна 65535. Считать введенные цифры тоже не корректно, можно ввести 99999 и будет переполнение. На переполнение можно проверить так: Код if(Result > Result*10) Если это условие выполняется, то следующая цифра в переменную уже не поместится.
|
|
|
|
|
Nov 22 2011, 15:11
|

Частый гость
 
Группа: Участник
Сообщений: 98
Регистрация: 20-06-05
Пользователь №: 6 150

|
Цитата(neiver @ Nov 22 2011, 18:20)  Здесь проверка переполнения будет работать только, если Result - 32-х разрядная переменная. Беззнаковая 16-ти разрядная переменная всегда меньше или равна 65535. Считать введенные цифры тоже не корректно, можно ввести 99999 и будет переполнение. На переполнение можно проверить так: Код if(Result > Result*10) Если это условие выполняется, то следующая цифра в переменную уже не поместится. Верно. Поправка принята. Либо long Result, либо приведенный пример проверки.
|
|
|
|
|
Nov 22 2011, 17:51
|

Профессионал
    
Группа: Свой
Сообщений: 1 202
Регистрация: 26-08-05
Из: Донецк, ДНР
Пользователь №: 7 980

|
Цитата(max_mart @ Nov 22 2011, 18:36)  Хотелось бы узнать какое значение получает функция GetCodeButton(), если ниче не нажато? Интернет глюнул, моя правка потерялась ... Напиши в конце return 100; Если ничего не нажали, вернёт 100. Цитата(max_mart @ Nov 22 2011, 18:36)  И если я буду использовать loong int result. Смогу ли яего потом сдвинуть вправо на 16 бит ю? Например: unsigned int addr addr = (unsigned int)(result>>16); Сможешь. А почему нет?
--------------------
Чтобы возить такого пассажира, необходим лимузин другого класса. (с) Мария Эдуарда
|
|
|
|
|
Nov 22 2011, 18:31
|
Местный
  
Группа: Участник
Сообщений: 248
Регистрация: 30-09-11
Пользователь №: 67 474

|
Хотелось бы узнать какое значение получает функция GetCodeButton(), если ниче не нажато? реализовываю немного по-другому(по-своему): unsigned char k[5], index=0; if ("not AACEPT") { k[index]= GetCodeButton() } if ("ACCEPT") { например если 456: addr = k[2]*100+k[1]+k[0]; Если (addr > 65535) ошибка; Если (введено больше 5 цифр) ошибка; } а 100!!! Извиняюсь!!! Не прочитал сразу до конца!!! ПЕРЕГРЕВ!!!!)))  А вот теперь сразу и другой вопрос. Как мне обработать все это, чтобы он не сохранял знач 100(игнорировал его) в массив k[index] или в переменную типа long int???
|
|
|
|
|
Nov 22 2011, 18:34
|

Профессионал
    
Группа: Свой
Сообщений: 1 202
Регистрация: 26-08-05
Из: Донецк, ДНР
Пользователь №: 7 980

|
Цитата(max_mart @ Nov 22 2011, 21:31)  Как мне обработать все это, чтобы он не сохранял знач 100(игнорировал его) в массив k[index] или в переменную типа long int??? int key = GetCodeButton(); if (key == 100) { // Ничего не нажали } // if else { // что-то нажали } // else
--------------------
Чтобы возить такого пассажира, необходим лимузин другого класса. (с) Мария Эдуарда
|
|
|
|
|
Nov 22 2011, 19:08
|
Местный
  
Группа: Участник
Сообщений: 248
Регистрация: 30-09-11
Пользователь №: 67 474

|
[quote name='max_mart' date='Nov 22 2011, 21:31' post='997204'] Хотелось бы узнать какое значение получает функция GetCodeButton(), если ниче не нажато? реализовываю немного по-другому(по-своему): unsigned char k[5], index=0; if ("not AACEPT") { k[index]= GetCodeButton() } if ("ACCEPT") { например если 456: addr = k[2]*100+k[1]+k[0]; Если (addr > 65535) ошибка; Если (введено больше 5 цифр) ошибка; } а 100!!! Извиняюсь!!! Не прочитал сразу до конца!!! ПЕРЕГРЕВ!!!!)))  А вот теперь сразу и другой вопрос. Как мне обработать все это, чтобы он не сохранял знач 100(игнорировал его) в массив k[index] или в переменную типа long int??? Наверное так да??? if (GetCodeButton()!= 100) k[index] = KEYBOARD(); [quote name='max_mart' date='Nov 22 2011, 21:35' post='997217'] [quote name='max_mart' date='Nov 22 2011, 21:31' post='997204'] Хотелось бы узнать какое значение получает функция GetCodeButton(), если ниче не нажато? реализовываю немного по-другому(по-своему): unsigned char k[5], index=0; if ("not AACEPT") { k[index]= GetCodeButton() } if ("ACCEPT") { например если 456: addr = k[2]*100+k[1]+k[0]; Если (addr > 65535) ошибка; Если (введено больше 5 цифр) ошибка; } а 100!!! Извиняюсь!!! Не прочитал сразу до конца!!! ПЕРЕГРЕВ!!!!)))  А вот теперь сразу и другой вопрос. Как мне обработать все это, чтобы он не сохранял знач 100(игнорировал его) в массив k[index] или в переменную типа long int??? Наверное так да??? if (GetCodeButton()!= 100) k[index] = KEYBOARD(); Пардон вместо KEYBOARD(), надо GetCodeButton(). Перегрев!!!))) И k[index++] = GetCodeButton(); - так надо, а не k[index]= GetCodeButton()
|
|
|
|
|
Nov 23 2011, 05:23
|

Профессионал
    
Группа: Свой
Сообщений: 1 202
Регистрация: 26-08-05
Из: Донецк, ДНР
Пользователь №: 7 980

|
hacker_fox, там и резистор не нужен. Нога МК - кнопка - земля. Если это AVR, конечно. Автор об этом ни звука не сказал .... И надо еще pull-up внутренний включить. Сам так милион раз делал. max_mart, из Вашего поста номер 30 - http://electronix.ru/forum/index.php?showt...st&p=997217 я ни хрена не понял....
Сообщение отредактировал hd44780 - Nov 23 2011, 05:25
--------------------
Чтобы возить такого пассажира, необходим лимузин другого класса. (с) Мария Эдуарда
|
|
|
|
|
Nov 23 2011, 13:05
|

Профессионал
    
Группа: Свой
Сообщений: 1 202
Регистрация: 26-08-05
Из: Донецк, ДНР
Пользователь №: 7 980

|
Ладно, хотите массив, делайте массив. Тоже верно. Но тогда уж не Цитата(max_mart @ Nov 23 2011, 12:06)  addr = k[2]*100+k[1]+k[0]; а addr = k[2]*100+k[1]*10+k[0];
Сообщение отредактировал hd44780 - Nov 23 2011, 13:06
--------------------
Чтобы возить такого пассажира, необходим лимузин другого класса. (с) Мария Эдуарда
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|