Свежие обсуждения
Микроконтроллеры

Преобразование HEX-DEC

Разыскиваются примеры преобразования 2х байтового шестнадцетиричного числа (00)(00)-(FF)(FF) в 3х байтовое двоично-десятичное (по полубайтам раскиданы значения)

(00)(00)-(FF)(FF) ->(00)(00)(00)-(06)(55)(36)

(хх) - регистр

Требование - использование произвольного набора регистров - тоесть без чтения регистрового пространства, как ячеек ОЗУ. Неиспользование младших 16 регистров. Максимум скорости.

Второй вариант - это преобразование однобайтового числа.

(00)-(FF) -> (00)(00)-(02)(56)
ОЗУ нельзя использовать. Можно пользовать аппаратный умножитель и расширенный набор команд ATMEGA.

 

Был апноут по такому преобразованию. Идея простая - преобразуемое число (два регистра) побитно вдвигается в регистры результата (3 регистра). Если при очередном вдвигании в какой-либо тетраде образуется комбинация более 10, к этой тетраде прибавляется число 6, в результате в следующую тетраду переходит единичка. Такая проверка выполняется последовательно на всех тетрадах. В итоге к моменту окончания сдвига (в данном случае 16 раз), в выходных регистрах образуется преобразованное число. Программа довольно наверченная, поскольку приходится работать с тетрадами.
Я делаю проще. Идея та же, но вначале я преобразую число так, чтобы в каждом байте было число не более 99. Если перед сдвигом регистра результата в нем находится чило более 50, к нему прибавляю число 78. После окончания преобразования в каждом байте результата остается число от 0 до 99. А затем эти числа просто перекодируются по таблице размером 100 байт - очевидным образом. Если память критична - пишется маленькая прога.

Исходники на ATMEGA дать не могу - не возникало такой задачи. Есть исходники под КР1878ВЕ1. Если интересно - вышлю.

 

Посмотрите здесь, если я правильно вас понял.

 

Еще одна идея (этот способ придуман для частотомера, который делаю сейчас на Atmega). Шестнадцатиричное число объемом в четыре разряда - это не что иное, как шестнадцатибитное двоичное. Программируем два действия: сложение двух десятичных чисел требуемой нам разрядности и умножение одного из них на два (и то и другое - столбиком). Предположим, что a и b - два двоично-десятичных числа, которые можно легко уместить и в регистры, а с - переводимое двоичное (оно же шестнадцатиричное).
Алгоритм такой:
a:=1;b:=0;
проверить 0 бит в с. если он равен 1, то добавить a к b
a:=a*2
проверить 1 бит в с. если он равен 1, то добавить a к b
a:=a*2
проверить 2 бит......
и так далее
проверить последний бит в с. если он равен 1, то добавить a к b

в b -результат

То есть, результат равен сумме всех весов единичных разрядов в исходном числе.

Не претендую на авторство, но этот метод буквально лежал на поверхности.

 

Мне пока нужно только в десятичное переводить. Обратно может и понадобиться, но потом в другом проекте, да и то только для упрощения сравнения.

 

GM: Посмотрите здесь, если я правильно вас понял.

Не подходят, там код оптимизированный на скорость вычисления, а мне нужна оптимизация на минимум используемых регистров. К тому-же для результата используется память, которая у меня тоже занята на 100%. В идеале мне хорошо-б обойтись всего 5 регистрами в пределах R16-R31. Потому как везде что-то храниться, а места для сброса в ОЗУ в этом ОЗУ уже увы нет

chav1961: Был апноут по такому преобразованию. Идея простая - преобразуемое число (два регистра) побитно вдвигается в регистры результата (3 регистра). Если при очередном вдвигании в какой-либо тетраде образуется комбинация более 10, к этой тетраде прибавляется число 6, в результате в следующую тетраду переходит единичка.

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

Еще раз взываю о помощи, а то работа встала.

 

Wladimir_TS, я уже писал, что от потетрадной обработки отказался, и вначале преобразую данные так, чтобы в каждом байте было число не более 99, а затем уж эти байты преобразую в BCD. С тетрадами гемора намного больше (и время выполнения, кстати, тоже). Если сильно горит, на выходных напЕшу прогу под ATMEL. Я так понимаю, у Вас что-то навроде Tiny15, раз проблемы с ОЗУ?

 

Ну, попробуйте этот код, вырвал из проекта, преобразует двоичные числа в диапазоне 0-999999 в символьное представление. Вместо сохранения в озу поставьте сохранение в регистрах, первый фрагмент binas1 вам не нужен, можно убрать, ну сами разберётесь.


;binary data res2-res1-res0 must be less 1000000
binasc: ldi temp,0x2F ;
binas1: inc temp ;10^5
subi res0,0xA0 ;
sbci res1,0x86 ;
sbci res2,0x01 ;
brsh binas1 ;
subi res0,0x60 ;
sbci res1,0x79 ;
sbci res2,0xFE ;
st x+,temp ;
ldi temp,0x2F ;
binas2: inc temp ;10^4
subi res0,0x10 ;
sbci res1,0x27 ;
brsh binas2 ;
subi res0,0xF0 ;
sbci res1,0xD8 ;
st x+,temp ;
ldi temp,0x2F ;
binas3: inc temp ;10^3
subi res0,0xE8 ;
sbci res1,0x03 ;
brsh binas3 ;
subi res0,0x18 ;
sbci res1,0xFC ;
st x+,temp ;
ldi temp,0x2F ;
binas4: inc temp ;10^2
subi res0,0x64 ;
brsh binas4 ;
subi res0,0x9C ;
st x+,temp ;
ldi temp,0x2F ;
binas5: inc temp ;10^1
subi res0,0x0A ;
brsh binas5 ;
subi res0,0xF6 ;
st x+,temp ;
subi res0,-0x30 ;10^0
st x+,res0 ;
ret

 

Вот вариант. Если проблема с памятью программ, вторую часть программы можно переписать на метод досчета, как реализовано у GM:

164027.asm