Перейти к содержанию
    

Помогите разобраться с преобразованиями

Простите за глупый вопрос, но как выделить полубайт?
Накладыванием маски и сдвигами.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Чтобы избежать неоднозначности я использовал конкретный тип uint16_t, который соответствует 16-и битному unsigned int.
Я вот тут книгу читал:

 

46. Не пользуйтесь именами из стандарта ANSI Cи

Идентификаторы, начинающиеся с символа подчеркивания, и имена типов, оканчивающиеся на _t, были зарезервированы стандартом ANSI Cи для использования разработчиками компиляторов. Не используйте эти символы.

Информация устарела? (книга старая)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я вот тут книгу читал:

 

Информация устарела? (книга старая)

Дык вы не просто читайте, а еще и в смысл прочитанного вникайте ;)

Написано же

Не используйте эти символы.
Потому что эти типы описаны в стандарте С99 (раздел 7.18 Integer types) и являются стандартными. Для использования их достаточно подключить хедер stdint.h. :laughing:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Простите за глупый вопрос, но как выделить полубайт?
uint8_t x = 0x12;

uint8_t bcd_l = x & 0x0f; // младший (единицы)
uint8_t bcd_h = x>>4; // старший (десятки)

Вот так. После чего будет: bcd_l = 2, а bcd_h = 1.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну мне надо вывести значения в десятичной системе, которые выдает мне DS1307

 

Куда вывести? На дисплей? В символьном виде? Если да - то я Вам еще вот в этом посте написал. Что не ясно?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Дык вы не просто читайте, а еще и в смысл прочитанного вникайте
Оооо, дошло наконец! Автор имел ввиду не использовать - т.е. не определять своих имен, оканчивающихся на "_t" или начинающихся с "_" :)

 

Ну а по делу:

Ув. топикстартер, мне кажется Вам нужно заново перечитать все ответы и ЧЕТКО сформулировать проблему, которая сейчас преграждает вам путь к победе.

Прямо не стесняясь, от начала и до конца. Что уже сделано, что не понятно, что уже хоть как-то работает и как оно работает.

И тогда, возможно, кто-нибудь вам поможет.

 

Возьмем хотя-бы этот совет rezident:

Накладыванием маски и сдвигами.
С этим всё ясно? Потому что может так случиться, что смысл Вами до конца был не понят, а от того, что дважды спросить одно и то-же бывает неудобно - вы можете остановиться на пол пути.

 

P.S. ну это я для примера взял именно этот совет, возможно тут какраз Вам всё понятно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Возьмем хотя-бы этот совет rezident: С этим всё ясно? Потому что может так случиться, что смысл Вами до конца был не понят, а от того, что дважды спросить одно и то-же бывает неудобно - вы можете остановиться на пол пути.

Честно говоря, Вы правы, я толком не могу понять, что значит наложить маску... я так понимаю, что сдвигая часть бит, маска как бы восполняет недостающие биты, причем в нужном мне порядке, верно? например 00001111 сдвигаем влево на 4 бита - получаем 11110000 и добавляем маску 00001111, то получится 11111111 верно?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Отлично. Начнем.

Предположим, из порта(или откуда-то ещё) мы считали значение 01110011 и нам нужен младший полу-байт(т.е. 4бита) Понятно, что правильный ответ = 0011, но как заставить машину отбросить 4старших байта и оставить 4младших.

Тут нап придется вспомнить логические операции AND, OR, XOR, NOT.. и хотя-бы приблизительно помнить таблицу истинности для этих операций.

Так вот, поскольку процессор может выполнять эти операции за один такт - то можно достаточно эффективно получить интересующие нас 4бита.

Для этого я предлагаю воспользоваться логической операцией AND(лог. умножение). Так вот, то значение, НА КОТОРОЕ мы будем умножать значение переменной, считанной с порта - мы будем называть маской.

Так вот. По таблице истинности лог операции AND видно, что в ней "всегда побеждает" ноль(это я так запоминал в детстве). Но сейчас мы можем понять, что умножение на 0 даёт 0:)

Чтобы выделить младшие 4 бита я выберу маску 00001111.

Посмотрим что это нам даст:

01110011

AND

00001111

equal

00000011

Верхняя строка - исходное значение. Ниже - маска. В самом низу результат. Как видим, операции эти потому и называются bitwise, потому что выполняются над битами операндов

 

Почему rezident упомянул про сдвиг?

Рассмотрим случай, когда нужно получить значение старшего полубайта. Маска будет, соответственно 11110000.

Имеем:

01110011

AND

11110000

equal

01110000

Т.е. младший полубайт мы как-бы обнулили и осталось сдвинуть всё это дело на 4 бита вправо.

01110000 >> 4 == 00000111

 

Это я привел пример, когда размер переменной == 8бит, а нам нужно 4. Но бывает так, что переменная 16бит, а нам нужно из них, скажем, биты с 10 по 13.

Тогда выбираем маску, с установленными в 1 битами с 10 по 13, а остальные 0. Маска, естественно, должна быть тоже 16битная. Но потом, чтобы значение этих байтов можно было применить как значение(к примеру в операции сравнения) нам нужно подвинуть их так, чтобы бит, стоящий на позиции 10 занял позицию 0. Т.е. нужен сдвиг на 10 вправо.

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

Так вот после описанных мною операций мы получим число байт в буфере :)

 

Ну и т.д.

Для закрепления материала задам задачку: нужно УСТАНОВИТЬ бит 5 какого-то(8ми битного) регистра в 0. Что для этого нужно? Какая маска и какая логическая операция должна быть использована?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

int bcd2dec (int bcd)
{
 int x,y;
 x = (bcd & 0xf);
 y = ((bcd & 0xf0)>>4)*10;
   return x+y;
}

Вот что получилось! Отлично работает!

А вот с обратным преобразованием как-то не получилось, вот код

int dec2bcd (int dec)
{
 int w,x,y;
 while ( dec >=  10)
 {
   dec -=10;
   w++;
 }
 x = dec;

 y = (w<<4);
 return y+x;
}

 

Что я не так сделал? Я хотя бы правильным путем пошел?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

...

Что я не так сделал?

Не прочитали статью в википедии, рекомендованную Вам на первой странице треда:

...

При сложении двоично-десятичных чисел каждый раз, когда происходит перенос бита в старший полубайт, необходимо к полубайту, от которого произошёл перенос, добавить корректирующее значение 0110.

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

При вычитании двоично-десятичных чисел, для каждого полубайта, получившего заём из старшего полубайта, необходимо провести коррекцию, отняв значение 0110

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Neytrino В функции dec2bcd в глаза бросается неинициализированная (нулём) переменная(w) . На вид правильно. Но для надёжности стоит различать ещё "+" от "|" . Если уйти от "оптимизации", то функцию можно переписать одной строчкой. на предыдущей странице rezident давал пример того же самого только немного красивее.

 

rezident Неужели библиотечные "целое/целое" и "%" массивнее самописных? Ведь алгоритм прозрачен и сделать по другому сложно. Разве что вызовы вместо "инлайна" ... Или есть ещё что-то, что я не учитываю?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

rezident Неужели библиотечные "целое/целое" и "%" массивнее самописных?
Я этого не утверждал. Просто бывают случаи когда целесообразнее вообще отказаться от применения умножения (хотя бы в подобном BCD-преобразовании), которое вызывает увеличение кода на лишние сотни байт линковкой соответствующей библиотеки.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не прочитали статью в википедии, рекомендованную Вам на первой странице треда:

А можно, если конечно не сложно, разжевать это мне, я что-то не совсем понял данной статьи, если быть точнее как производить коррекцию и как вычислить в функции те самые недопустимые комбинации

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А можно, если конечно не сложно, разжевать это мне, я что-то не совсем понял данной статьи, если быть точнее как производить коррекцию и как вычислить в функции те самые недопустимые комбинации

Проще всего делать bcd-преобразование непосредственно перед выводом на экран или сразу после ввода значения (если есть ввод). А вычисления делать в обычном бинарном формате, не заморачиваясь десятичной коррекцией.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...