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

я уже сталкивался с этой проблемой. Решил всё очень просто. Ввел счетчик нажатий клавиш. Выделил для каждого десятичного разряда байт в ОЗУ.Нажал первый раз - сохранил в область ОЗУ "тысячи", нажал второй раз -сотни, нажал третий раз - десятки, четвертый - единицы. Так же счетчиком включаю кнопку "стереть по символьно". Т.е. если нажал >=1-ого раза - загорается надпись удалить и кнопка "удалить" становиться активной. Когда ввел значение полностью загорается надпись "принять", по нажатии соответствующей кнопки "принять" умножаем число из ОЗУ"1000" на тысячу, затем сотни, десятки, единицы, и все суммируем.
stells
Цитата(max_mart @ Nov 22 2011, 09:22) *
Помогите, пожалуйста, в данной проблеме?

на кодирование кода клавиши (от 0 до 9) нужно 3 бита, для запоминания 5 кодов соответственно нужно 15 бит... так что просто последовательно пишете в 16-битный регистр коды клавиш в порядке нажатия, да и все laughing.gif

стоп, не 3, а 4 бита нужно... надо подумать
haker_fox
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;

Вроде все. Если ошибся, коллеги поправят rolleyes.gif
Navovvol
Можно сделать еще интересней. Допустим диапазон от 0 до 999 999 999. Так же имеем 9 байт ОЗУ под хранение разрядов и счетчик нажатий кнопок. нажали один раз сохр. значение в ОЗУ "единицы" нажали второй раз - перенесли значение из ОЗУ " единицы" в ОЗУ "десятки", сохр. новое значение в ОЗУ "единицы" и так далее. Потом множим и суммируем .Но программа у меня вышла очень объемной.
haker_fox
QUOTE (Navovvol @ Nov 22 2011, 14:40) *
Можно сделать еще интересней.

Я предлагаю подход разделения. Функции опроса клавиатуры не коим образом не связаны с какими-либо счетчиками. Это уже можно сделать снаружи, иерархично. Таким образом, каждая часть программы самостоятельна, но является тесно связанной в целом. Ваш подход несколько иной, и это здорово! rolleyes.gif чем больше у автора темы будет рекомендаций, тем проще ему сделать выбор (или сложнее))))
stells
так все красиво расписывают: буфер , ОЗУ...

вопрос к автору: я правильно понял, что для сохранения кодов нажатых клавиш есть только 16 бит и больше ничего? это студенческая задачка? она точно решается?
haker_fox
QUOTE (stells @ Nov 22 2011, 14:49) *
так все красиво расписывают: буфер , ОЗУ...

Автор темы не дал нам больше информации для рамышлений, поэтомы мы вольны давать советы, не вдаваясь в отсутствующие подробности. Да и вопрос задан не в теме для начинающих, хотя его и можно туда переместить.
stells
Цитата(haker_fox @ Nov 22 2011, 10:57) *
Автор темы не дал нам больше информации для рамышлений

а по-моему он вполне конкретно описал задачу:

Цитата(max_mart @ Nov 22 2011, 09:22) *
как реализовать сохранение группы нажатых цифр в одну переменную 16-битную

haker_fox
QUOTE (stells @ Nov 22 2011, 14:58) *
а по-моему он вполне конкретно описал задачу:

Чтож, вполне возможно, что его не вполне корректно поняли, т.к. человеческий язык, в отличие от машинного, допускает вариации в понимании rolleyes.gif bb-offtopic.gif
Подождем автора, пусть прояснит ситуацию.
max_mart
Во первых я замарачиваться не стал сделал клаву просто от ножки МК через резистор на конпку.
Во вторых цифре от 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 битной переменной.
Но я не знаю как мне их сохранять при нажатии клавиши, чтобы не потерять последовательность.
Помогите, пожалуйста с кодом? Дописать его, чтобы реализовать задуманное.
stells
Цитата(max_mart @ Nov 22 2011, 11:16) *
5 цифр числа просто в 16-битную пер. не уместится

так и "не просто" не уместится... диапазон чисел от 00000 до 99999 не помещается в 16 бит никак

вот только непонятно, почему Вы себя ограничили этими 16-ю битами?
max_mart
мне нужно число 0-65535. Если мне надо будит большее число, то я по этой же схеме преобразую в число до 3 миллионов(long int).
А пока 16-битное
Navovvol
к сожалению я ни черта не понимаю в С/С++
hd44780
Автор, как я понял, хочет получить, допустим, число 468, если ему нажмут кнопки 4, 6, 8.

Берёте одну переменную-накопитель, 16 бит. Инициализируете её нулём.
Далее простой алгоритм - нажали какую-то цифру, вы получаете из какого-то сканкода саму цифру, текущий накопитель умножаете на 10 и прибавляете только что введённую цифру. Всё.
Плюс контроль, чтобы накопитель не переполнился при очередном умножении.
Захотите больше - сделайте накопитель не 16 бит, а 32, 64 ....
Классический алгоритм с бородой ....

Зачем тут буфер, накопление n-разрядных кодов в нём и прочие сложности?
Потом ведь всё равно этот буфер в число конвертить надо ...
Буфер надо, если необходима возможность полного редактирования числа. Да и то - проще не сканкоды в буфер класть, а готовые цифры. Проще и понятнее. У вас же не матрица 105 клавиш от компа?
haker_fox
QUOTE (hd44780 @ Nov 22 2011, 17:48) *
Буфер надо, если необходима возможность полного редактирования числа. Да и то - проще не сканкоды в буфер класть, а готовые цифры. Проще и понятнее. У вас же не матрица 105 клавиш от компа?

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

Где-то так...
Но вопрос контроля за переполнением типа лежит на программисте.
Об этом надо помнить, или вводить программный контроль.
max_mart
Не понял:
зачем умножать на 10 и для чего прибавлять код кнопки?
И потом у меня вверху указан код, который я реализую! Мне надо под него синхронизировать выше указанную проблему!!!
hd44780
Цитата(max_mart @ Nov 22 2011, 14:08) *
зачем умножать на 10 и для чего прибавлять код кнопки?

Чтобы преобразовать последовательность Ваших кнопок в число, которое Вы хотите поиметь на выходе сего алгоритма.
Оно же для запоминания последовательности нажатий кнопок, о чём Вы спрашивали выше.

Вы же сами написали где-то выше по теме:

Я знаю что, чтобы получить например число 453 из введенных цифр надо просто: 4*100+5*10+3=453 в 16 битной переменной.

Совершенно верно написали. Я этим умножением и сложением это и делаю.

Цитата(max_mart @ Nov 22 2011, 14:08) *
И потом у меня вверху указан код, который я реализую! Мне надо под него синхронизировать выше указанную проблему!!!


А мне стало страшно, когда я увидел Ваш код w00t.gif Им только детей маленьких пужать - какое страшное это программирование ....

Отделите опрос клавиатуры от получения числа. А если Вы завтра захотите эту клавиатуру ещё в 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


Проверку переполнения накопителя сами добавьте. Это Вам домашнее задание лично от меня biggrin.gif .
Потому что контроля на 5 цифр недостаточно - число 99999 - 5 цифр, но в 16 бит оно не влезает.
max_mart
ладно подумаю на накопителем. цифр всего 5, а максимальное число то у меня будит 65535
ut1wpr
Цитата(max_mart @ Nov 22 2011, 15:54) *
ладно подумаю на накопителем. цифр всего 5, а максимальное число то у меня будит 65535

Не знаю, кто и кого там у вас по утрам будит, а код с проверкой будЕт такой:
Код
Result = 0;
while( (GetCodeValue = GetCodeButton() != ENTER) && (Result <= 65535) ){
  Result *= 10;
  Result += GetCodeValue;
}
max_mart
[удалено]
neiver
Цитата(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)

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

Если это условие выполняется, то следующая цифра в переменную уже не поместится.
Верно. Поправка принята. Либо long Result, либо приведенный пример проверки.
max_mart
int GetCodeButton()
{
if (!ZERO)
return 0;

if (!ONE)
return 1;

.............

if (!ACCEPT)
return 20;
} // GetCodeButton
Хотелось бы узнать какое значение получает функция GetCodeButton(), если ниче не нажато?
Result = 0;
while( (GetCodeValue = GetCodeButton() != ENTER) && (Result <= 65535) ){
Result *= 10;
Result += GetCodeValue;
}
И если я буду использовать loong int result. Смогу ли яего потом сдвинуть вправо на 16 бит ю?
Например:
unsigned int addr
addr = (unsigned int)(result>>16);
hd44780
Цитата(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);


Сможешь. А почему нет?
max_mart
Хотелось бы узнать какое значение получает функция 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!!! Извиняюсь!!! Не прочитал сразу до конца!!! ПЕРЕГРЕВ!!!!))) rolleyes.gif

А вот теперь сразу и другой вопрос. Как мне обработать все это, чтобы он не сохранял знач 100(игнорировал его) в массив k[index] или в переменную типа long int???
hd44780
Цитата(max_mart @ Nov 22 2011, 21:31) *
Как мне обработать все это, чтобы он не сохранял знач 100(игнорировал его) в массив k[index] или в переменную типа long int???


int key = GetCodeButton();

if (key == 100)
{ // Ничего не нажали
} // if
else
{ // что-то нажали
} // else
max_mart
[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!!! Извиняюсь!!! Не прочитал сразу до конца!!! ПЕРЕГРЕВ!!!!))) rolleyes.gif

А вот теперь сразу и другой вопрос. Как мне обработать все это, чтобы он не сохранял знач 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!!! Извиняюсь!!! Не прочитал сразу до конца!!! ПЕРЕГРЕВ!!!!))) rolleyes.gif

А вот теперь сразу и другой вопрос. Как мне обработать все это, чтобы он не сохранял знач 100(игнорировал его) в массив k[index] или в переменную типа long int???

Наверное так да???
if (GetCodeButton()!= 100) k[index] = KEYBOARD();
Пардон вместо KEYBOARD(), надо GetCodeButton(). Перегрев!!!))) rolleyes.gif


И k[index++] = GetCodeButton(); - так надо, а не k[index]= GetCodeButton() rolleyes.gif
haker_fox
QUOTE (max_mart @ Nov 22 2011, 15:16) *
Во первых я замарачиваться не стал сделал клаву просто от ножки МК через резистор на конпку.

Это как?) А подтягивающие резисторы есть?
max_mart
Конечно!!! Внутренние подтягивающие резисторы на 40кОм с диодом к +!!!
hd44780
hacker_fox, там и резистор не нужен. Нога МК - кнопка - земля. Если это AVR, конечно. Автор об этом ни звука не сказал ....
И надо еще pull-up внутренний включить.
Сам так милион раз делал.

max_mart, из Вашего поста номер 30 - http://electronix.ru/forum/index.php?showt...st&p=997217 я ни хрена не понял....
max_mart
С учетом всего выше сказанного реализую это все. но по-своему!!!
unsigned char k[5], index=0;

if ("not AACEPT")
{
if (GetCodeButton()!= 100) {k[index]= GetCodeButton(); index++;}
}
if ("ACCEPT")
{
например если 456: addr = k[2]*100+k[1]+k[0];
Если (addr > 65535) ошибка;
Если (введено больше 5 цифр) ошибка;
}
hd44780
Ладно, хотите массив, делайте массив. Тоже верно.
Но тогда уж не

Цитата(max_mart @ Nov 23 2011, 12:06) *
addr = k[2]*100+k[1]+k[0];

а addr = k[2]*100+k[1]*10+k[0];
max_mart
))) Извиняюсь!!! Писал в торопях!!! Работы полно было!!!)))
Но все равно всем спеасибо за поддержку и советы!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1 biggrin.gif 1111493779.gif biggrin.gif
haker_fox
QUOTE (hd44780 @ Nov 23 2011, 13:23) *
hacker_fox, там и резистор не нужен.

Нужен rolleyes.gif А внутренний или внешний - не так важно rolleyes.gif

QUOTE (max_mart @ Nov 24 2011, 02:03) *
Но все равно всем спеасибо за поддержку и советы!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Да пожалуйста! Лишь бы все получилось!
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.