Главная » Статьи » Полезные материалы

Преобразование форматов

В повседневной жизни мы имеем дело с обычными числами от 0 до 9, из которых складываем более значимые числа - двухзначные, трехзначные, четырех-, пяти-, шести-, восьми-, двадцати- и т.д. -значные. Эти числа представлены в так называемом, десятичном представлении. Почему так? Потому, что для представления любого числа используется 10 цифр - от 0 до 9. Мы с детства знаем этот формат, но не задумываемся о том, что он именно десятичный. Нам удобней работать с ним. 

Однако, мы занимаемся программированием микроконтроллеров, с которыми гораздо удобней бывает работать, используя другие форматы числа - двоичный и шестнадцатиричный. Остановимся на них подробней. 

Как вы уже, наверное, догадались, их названия образуются от количества цифр, используемых для представления этих чисел. Правильно! Двоичный формат подразумевает оперирование всего двумя цифрами - нулем и единицей.

Двоичный формат

Этот формат мы обычно используем при работе с портами и регистрами микроконтроллера, так как этот метод представления числа для них - самый удобный - мы сразу видим какой бит порта или регистра установлен, а какой сброшен. Регистры и порты обычно восьмиразрядные. Числа в двоичном формате тоже имеют длину 8 разрядов, но иногда незначащие старшие нули не записываются.

Чтобы понять, как образуется двоичное число разберем следующий пример:

Возьмем любое число. Чтобы не усложнять, для начала, пусть это будет число 183. В двоичном формате это же число будет выглядеть как %10110111

Знак "%" используется для обозначения двоичного числа.

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


183 = % (1*2^7 + 0*2^6 + 1*2^5 + 1*2^4 + 0*2^3 + 1*2^2 + 1*2^1 + 1*2^0) = %(128 + 0 + 32 + 16 + 0 + 4 + 2 + 1)

То есть, умножение на 0 дает ноль, а умножение на единицу двойки в степени номера позиции дает определенное число. Складываем их и получаем целый результат. Обратное преобразование осуществляется делением на 2.

183/2 = 91 и 1 в остатке

91/2 =   45 и 1 в остатке

45/2 =   22 и 1 в остатке

22/2 =   11 и 0 в остатке

11/2 =     5 и 1 в остатке

5/2 =       2 и 1 в остатке

2/2 =       1 и 0 в остатке


        остается 1, она то и будет старшим разрядом. Ставим рядком полученные остатки от деления - %10110111 - что и требовалось доказать.

Для чисел больше 255 в двоичном числе будет больше нулей и единиц.

На самом деле, я не пользуюсь этим методом, а обычно просто открываю калькулятор в windows и преобразую там. Это быстрее и проще :)


Шестнадцатиричный формат

Для обозначения этого формата мы используем знак "$" перед числом. Число этого формата составляется из 16 символов, состоящих как из цифр, так и из букв. Проще понять, что представляет собой шестнадцатиричная система, если посмотреть на таблицу:

 Десятичный Двоичный Шестнадцатиричный
0%0000$0
%0001$1
2%0010$2
3%0011$3
4%0100$4
5%0101$5
6%0110$6
7%0111$7
8%1000$8
9%1001$9
10%1010$A
11%1011$B
12%1100$C
13%1101$D
14%1110$E
15%1111$F

Обычно шестнадцатиричное число записывают в виде двух символов. 

Вернемся к нашим баранам, точнее, к числу, взятому для примера - 183

Как мы уже выяснили, в двоичном формате оно выглядит как  %10110111

Теперь, чтобы получить его в виде 16-ричного числа, мы найдем из таблицы старший полубайт ( %1011 ) этого числа и младший полубайт ( %0111 ). И составим число в 16-ричном формате -  $B7

Все просто! С помощью этого формата удобней записывать большие числа, так как они занимают меньше места. При программировании микроконтроллера вы загружаете программу именно в таком формате. Он называется еще HEX-файлом.


Двоично-десятичный формат

Итак, мы познакомились с основными форматами представления данных - системами исчисления. На практике же бывают случаи, когда требуются преобразования чисел в особый формат. Он вроде бы и тот, да не совсем. То есть представляется он либо в двоичной, либо в десятичной, либо в шестнадцатиричной форме, но несет несколько иную смысловую нагрузку. Речь идет о двоично-десятичном формате или, по-другому - BCD (binary-coded decimal) формат. В этой форме каждый десятичный (!) разряд записывается в виде двоичного полубайта. Мы знаем, что полубайт может принимать максимум 16 значений. А нам много и не нужно. Нам нужно всего 10 значений - от 0 до 9.

Исходя из всего вышесказанного, имеем:

Число 183 в двоично-десятичном формате будет выглядеть как 

1 8 3
 %0001 %1000 %0011

183 (D) = 000110000011 (BCD)

Если теперь преобразовать полученное число обратно в десятичный формат, то мы получим совсем другой результат

На практике нам обычно требуются числа с двумя значащими десятичными разрядами - обычно это часы реального времени. Там мы оперируем с цифрами от 0 до 59. То есть - два значащих разряда. Вот от этого примера мы и будем отталкиваться.

Не будем привязываться к определенному синтаксису, поскольку операции будут одинаковые для любого Basic-компилятора.

Итак, пусть у нас имеется четыре переменные:

BCDOUT - переменная типа Byte для хранения результата преобразования из двоичного числа в формат BCD

BCDIN - переменная типа Byte, содержащая значение, которое требуется преобразовать из BCD в двоичный формат (или другой) (сразу запомним, что это число, записанное в виде десятичного числа, представляет собой число, записанное в двоично-десятичном формате)

BININ - переменная типа Byte, содержащая двоичное значение для преобразования в BCD (мы будем записывать его в десятичном виде для удобства)

BINOUT - переменная типа Byte, которая будет содержать результат преобразования из BCD в двоичный формат


Переменным BININ и BCDIN присвоим значения (ну, предположим, мы приняли по USART два эти числа):

BCDIN = 47 'Пусть 47 минут в двоично-десятичном формате    

BININ = 23 'Пусть это будет 23 часа


  • Займемся преобразованием двоично-десятичного формата в двоичный:

 Чтобы лучше понять процесс представим исходные числа в двоичном формате. Обратите на подсветку полубайтов, чтобы понять, что с ними происходит

BCDIN = %00101111

BINOUT = BCDIN >> 4 'Сдвигаем старший полубайт на место младшего и получаем в BCDOUT число 2 (%00000010). Умножаем его на 10, поскольку мы извлекаем старший полубайт, содержащий десятки числа.
BINOUT = BINOUT * 10 'Теперь мы имеем число 20 (%00010100)
Теперь извлекаем младший полубайт. Это делается просто: выполняется побитовое логическое И с числом %00001111 (или $0F). Побитовое И с нулевым значением вернет 0, а с единицей - то, что было до этой логической операции.
BCDIN = BCDIN & $0F 'Получим число  %00001111 ( или 15 по другому) - Мы приравняли нулю старший полубайт переменной BCDIN
Теперь сложим два полученных числа:

BINOUT = BINOUT + BCDIN = 20 + 15 = 35 (DEC) = %00001111 + %00010100 = %00100011 - Это число в двоичном формате

Всю операцию можно записать в одну строку:

BINOUT = ((BCDIN >> 4) * 10) + (BCDIN & $0F), но лучше разбить ее на несколько строк, поскольку в этом виде операция занимает больше программной памяти


  • Теперь произведем преобразование из двоичного числа в двоично-десятичный.
BININ = %00010111

Так как каждый полубайт двоично-десятичного формата содержит одну цифру, и мы знаем, что наше двоичное число - двухзначное, то нам нужно извлечь количество десяток и количество единиц, а потом составить из них BCD-число.

Чтобы извлечь десятки мы просто делим двоичное число на 10

BCDOUT = BININ / 10

Получаем число 2, так как младшая 3 отбрасывается при делении (мы имеем дело с целочисленной математикой).

Теперь наше число выглядит как %00000010

Но двойка у нас - это количество десяток! Значит нам нужно сдвинуть его в старший полубайт:

BCDOUT = BCDOUT << 4 'Получаем число  %00100000 или 32

Теперь, чтобы извлечь младшее число (число единиц - 3) нам нужно выполнить операцию, называемую Модуль в Picbasic. Эта операция возвращает остаток от деления, но не тот, что мы привыкли думать. До этого мы делили число 23 на 10 и получили 2, а теперь же мы получим число 3 - то что осталось от обычного деления на 10

BININ = BININ // 10 'Получим 3

Теперь сформируем двоично-десятичное число:

BCDOUT = BCDOUT + BININ = 32 + 3 = 35 - это число в двоично-десятичном представлении - это не одно и то же, что получилось в верхнем примере!!!

Опять же, все, что написано выше, можно уместить в одну строку.

  BCDOUT = (( BININ / 10) << 4) + ( BININ // 10) 

Но практика показывает, что если разбить это выражение на отдельные, короткие выражения, то они займут намного меньше программной памяти.

Еще хочется особо отметить, что двоично-десятичный формат - это не система исчисления!!! Это формат представления числа. Число в этом формате может быть записано как в двоичной, так и в шестнадцатиричной, так и в десятичной системе. Просто нужно помнить, что это число означает и в какой оно форме записано.

На этом все! Задавайте вопросы и комментируйте материал.





Категория: Полезные материалы | Добавил: ADMIN (30.10.2011)
Просмотров: 19946 | Комментарии: 6 | Теги: система исчисления, Bin, пример, преобразование форматов, BCD, компилятор | Рейтинг: 5.0/3
Всего комментариев: 6
1 ivan_fd   (31.10.2011 14:53) [Материал]
+1 wink

2 Matrix252005   (31.10.2011 16:57) [Материал]
Класс!!! СПС!!!

3 ADMIN   (01.11.2011 02:19) [Материал]
Рад, что понравилось. Какие еще будут предложения?

4 S_moke   (08.11.2011 11:10) [Материал]
Спасибо!

5 indeez   (10.02.2012 23:42) [Материал]
Спасибо! Я всё очень легко понял!

6 amid-   (15.05.2013 11:33) [Материал]
Оператор DIG не проще ? и мозг себе не надо  ломать! (афоризм)

Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]