|
3 страниц
1 2 3 >
|
 |
Ответов
(1 - 31)
|
Oct 12 2009, 11:37
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(Neytrino @ Oct 12 2009, 12:38)  в IAR нет функций преобразования bin2dec и обратно. Вам это нужно для вывода значения на индикатор? Тогда что-то такое: Код unsigned int Bin; unsigned char D[5]; for(i=0; i<5; ++i) { D[i]= Bin % 10; Bin /= 10; } Десятичные цифры в массиве будут лежать "наоборот": D[0]-самая младшая (единицы), D[1]-десятки, и тд. Если нужно делать это быстро, то вычитанием десятков тысяч, единиц тысяч, сотен, и тд (воспользуйтесь поиском - это уже не раз обсуждалось).
|
|
|
|
|
Oct 12 2009, 12:41
|
Участник

Группа: Участник
Сообщений: 53
Регистрация: 26-02-09
Пользователь №: 45 406

|
Да, я опрашиваю DS1307 и вывожу значения на LCD на основе ks0108. Беда оказалась в том, что после того как секунды отсчитали 9 следующее значение было уже 16, после 24 сразу же 32 и т.д. Где-то наткнулся, что неправильно преобразованы числа, но готовой функции в IAR не нашел, как в CV вот и решил обратиться, т.к. кодов не нашел
|
|
|
|
|
Oct 12 2009, 12:47
|

Йа моск ;)
     
Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610

|
Цитата Да, я опрашиваю DS1307 и вывожу значения на LCD на основе ks0108. Дык это совсем другое дело, там же BCD. Каждый байт в символьный десятичный вид преобразуется банально: Код char *out; //Указатель на буфер строки char v; //Значение байта .... *out++=((v&0xF0)>>4)+'0'; *out++=(v&0x0F)+'0';
--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
|
|
|
|
|
Oct 12 2009, 13:38
|
Участник

Группа: Участник
Сообщений: 53
Регистрация: 26-02-09
Пользователь №: 45 406

|
а что такое bcd? я что-то не совсем понял гугл
|
|
|
|
|
Oct 13 2009, 15:56
|
Участник

Группа: Участник
Сообщений: 53
Регистрация: 26-02-09
Пользователь №: 45 406

|
CODE int bin2bcd(int v) { int out; int i1; i1=(v>>4)*10; out = i1; return out; } вот так я получил десятки, но что-то не могу получить единицы, помогите, я совсем запутался
|
|
|
|
|
Oct 13 2009, 17:02
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(Neytrino @ Oct 13 2009, 21:56)  вот так я получил десятки, но что-то не могу получить единицы, помогите, я совсем запутался Раз уж вы использовали умножение, то видимо и деление не будет извратом.  Используйте операцию % - получение остатка от целочисленного деления. Код i2=v%10; // получение остатка при делении на десять
|
|
|
|
|
Oct 13 2009, 17:22
|
Участник

Группа: Участник
Сообщений: 53
Регистрация: 26-02-09
Пользователь №: 45 406

|
Люди, Вы наверное будите смеяться, но у меня снова получился полный бред, вот код: CODE int bin2bcd(int v) { int out; int i1,i2; i1=(v>>4)*10; i2=v%10; out = i1+i2; return out; }
|
|
|
|
|
Oct 17 2009, 17:38
|
Участник

Группа: Участник
Сообщений: 53
Регистрация: 26-02-09
Пользователь №: 45 406

|
странно конечно, но правильно не работает... может проблема в переменных, которые я поставил, вместо uintl6_t и предположит, что это unsigned int
|
|
|
|
|
Oct 17 2009, 18:56
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(Neytrino @ Oct 17 2009, 23:38)  странно конечно, но правильно не работает... Что именно не работает? На входе бинарное число, на выходе бинарно-десятичное. Т.е. каждый полубайт (4 бита) содержит число, не превышающее основания 10 (от 0 до 9). Допустим на входе число 1234=0x04D2, на выходе получаем 0x1234. После этого достаточно выделить каждый из полубайтов, прибавить к нему ASCII-код символа '0'=0x30 и можно выводить на экран число в привычном десятичном виде. Цитата(Neytrino @ Oct 17 2009, 23:38)  может проблема в переменных, которые я поставил, вместо uintl6_t и предположит, что это unsigned int В стандарте Си нет конкретной размерности у типов переменных. Размерность типов переменных задается в стандартном хедере limits.h и может отличаться на разных кристаллах и компиляторах. А стандарт лишь гарантирует их отношение char ≤ short int ≤ int ≤ long int. Чтобы избежать неоднозначности я использовал конкретный тип uint16_t, который соответствует 16-и битному unsigned int.
|
|
|
|
|
Oct 17 2009, 19:26
|
Участник

Группа: Участник
Сообщений: 53
Регистрация: 26-02-09
Пользователь №: 45 406

|
Простите за глупый вопрос, но как выделить полубайт? Цитата(Rst7 @ Oct 17 2009, 21:50)  Вы бы задачу конкретизировали. А то совсем не ясно, какой результат Вам надо получить. Ну мне надо вывести значения в десятичной системе, которые выдает мне DS1307
|
|
|
|
|
Oct 17 2009, 22:37
|

I WANT TO BELIEVE
     
Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751

|
Цитата Чтобы избежать неоднозначности я использовал конкретный тип uint16_t, который соответствует 16-и битному unsigned int. Я вот тут книгу читал: Цитата 46. Не пользуйтесь именами из стандарта ANSI Cи Идентификаторы, начинающиеся с символа подчеркивания, и имена типов, оканчивающиеся на _t, были зарезервированы стандартом ANSI Cи для использования разработчиками компиляторов. Не используйте эти символы. Информация устарела? (книга старая)
--------------------
The truth is out there...
|
|
|
|
|
Oct 18 2009, 00:57
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(sigmaN @ Oct 18 2009, 04:37)  Я вот тут книгу читал:
Информация устарела? (книга старая) Дык вы не просто читайте, а еще и в смысл прочитанного вникайте  Написано же Цитата Не используйте эти символы. Потому что эти типы описаны в стандарте С99 (раздел 7.18 Integer types) и являются стандартными. Для использования их достаточно подключить хедер stdint.h.
|
|
|
|
|
Oct 18 2009, 06:58
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(Neytrino @ Oct 17 2009, 23:26)  Простите за глупый вопрос, но как выделить полубайт? Код uint8_t x = 0x12;
uint8_t bcd_l = x & 0x0f; // младший (единицы) uint8_t bcd_h = x>>4; // старший (десятки) Вот так. После чего будет: bcd_l = 2, а bcd_h = 1.
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Oct 18 2009, 11:15
|

I WANT TO BELIEVE
     
Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751

|
Цитата Дык вы не просто читайте, а еще и в смысл прочитанного вникайте Оооо, дошло наконец! Автор имел ввиду не использовать - т.е. не определять своих имен, оканчивающихся на "_t" или начинающихся с "_"  Ну а по делу: Ув. топикстартер, мне кажется Вам нужно заново перечитать все ответы и ЧЕТКО сформулировать проблему, которая сейчас преграждает вам путь к победе. Прямо не стесняясь, от начала и до конца. Что уже сделано, что не понятно, что уже хоть как-то работает и как оно работает. И тогда, возможно, кто-нибудь вам поможет. Возьмем хотя-бы этот совет rezident: Цитата Накладыванием маски и сдвигами. С этим всё ясно? Потому что может так случиться, что смысл Вами до конца был не понят, а от того, что дважды спросить одно и то-же бывает неудобно - вы можете остановиться на пол пути. P.S. ну это я для примера взял именно этот совет, возможно тут какраз Вам всё понятно.
--------------------
The truth is out there...
|
|
|
|
|
Oct 18 2009, 15:44
|
Участник

Группа: Участник
Сообщений: 53
Регистрация: 26-02-09
Пользователь №: 45 406

|
Цитата(sigmaN @ Oct 18 2009, 15:15)  Возьмем хотя-бы этот совет rezident: С этим всё ясно? Потому что может так случиться, что смысл Вами до конца был не понят, а от того, что дважды спросить одно и то-же бывает неудобно - вы можете остановиться на пол пути. Честно говоря, Вы правы, я толком не могу понять, что значит наложить маску... я так понимаю, что сдвигая часть бит, маска как бы восполняет недостающие биты, причем в нужном мне порядке, верно? например 00001111 сдвигаем влево на 4 бита - получаем 11110000 и добавляем маску 00001111, то получится 11111111 верно?
|
|
|
|
|
Oct 18 2009, 16:25
|

I WANT TO BELIEVE
     
Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751

|
Отлично. Начнем. Предположим, из порта(или откуда-то ещё) мы считали значение 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. Что для этого нужно? Какая маска и какая логическая операция должна быть использована?
--------------------
The truth is out there...
|
|
|
|
|
Oct 18 2009, 17:02
|
Участник

Группа: Участник
Сообщений: 53
Регистрация: 26-02-09
Пользователь №: 45 406

|
Кажется до меня дошло!!!!!!!!! Сейчас попробую!!!
|
|
|
|
|
Oct 18 2009, 19:41
|
Участник

Группа: Участник
Сообщений: 53
Регистрация: 26-02-09
Пользователь №: 45 406

|
CODE int bcd2dec (int bcd) { int x,y; x = (bcd & 0xf); y = ((bcd & 0xf0)>>4)*10; return x+y; }
Вот что получилось! Отлично работает! А вот с обратным преобразованием как-то не получилось, вот код CODE int dec2bcd (int dec) { int w,x,y; while ( dec >= 10) { dec -=10; w++; } x = dec; y = (w<<4); return y+x; } Что я не так сделал? Я хотя бы правильным путем пошел?
|
|
|
|
|
Oct 18 2009, 20:02
|
    
Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731

|
Цитата(Neytrino @ Oct 18 2009, 23:41)  ... Что я не так сделал? Не прочитали статью в википедии, рекомендованную Вам на первой странице треда: Цитата ... При сложении двоично-десятичных чисел каждый раз, когда происходит перенос бита в старший полубайт, необходимо к полубайту, от которого произошёл перенос, добавить корректирующее значение 0110. При сложении двоично-десятичных чисел каждый раз, когда встречается недопустимая для полубайта комбинация, необходимо к каждой недопустимой комбинации добавить корректирующее значение 0110 с разрешением переноса в старшие полубайты. При вычитании двоично-десятичных чисел, для каждого полубайта, получившего заём из старшего полубайта, необходимо провести коррекцию, отняв значение 0110
|
|
|
|
|
Oct 19 2009, 10:16
|
Участник

Группа: Участник
Сообщений: 53
Регистрация: 26-02-09
Пользователь №: 45 406

|
Цитата(xemul @ Oct 19 2009, 00:02)  Не прочитали статью в википедии, рекомендованную Вам на первой странице треда: А можно, если конечно не сложно, разжевать это мне, я что-то не совсем понял данной статьи, если быть точнее как производить коррекцию и как вычислить в функции те самые недопустимые комбинации
|
|
|
|
|
Oct 19 2009, 13:43
|
    
Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731

|
Цитата(Neytrino @ Oct 19 2009, 14:16)  А можно, если конечно не сложно, разжевать это мне, я что-то не совсем понял данной статьи, если быть точнее как производить коррекцию и как вычислить в функции те самые недопустимые комбинации В стандартном BCD (с весами битов 8-4-2-1) каждая десятичная цифра однозначно представляется 4-мя битами (тетрадой): 0 - 0000 1 - 0001 2 - 0010 ... 9 - 1001 Остальные 6 комбинаций (1010, ... , 1111) являются недопустимыми. (угадайте, почему коррекция выполняется именно на 6?)  Если расписать (на бумажке), н-р, сложение двух BCD-чисел Код BCD BIN 11 0001 0001 + 22 0010 0010 = 33 0011 0011 // без переносов между тетрадами вообще никакой разницы с обычным двоичным сложением
35 0011 0101 + 74 0111 0100 = 1010 1001 // если в какой-то тетраде цифра>9, то приключился BCD-перенос + 0110 0000 // добавляем коррекцию к каждой тетраде, в которой приключился перенос = 109 0001 0000 1001 // и не забываем про перенос в следующий BCD-разряд, вес которого, естесно, уже 100 Вычитание - аналогично. Да и для любого произвольного основания системы счисления тоже аналогично. Как уже сказал rezident, развлекаться арифметикой непосредственно в BCD смысла нет - проще BCD перевести в обычный двоичный формат, выполнить необходимые вычисления, и перевести результат обратно в BCD. В конфе уже не раз обсуждались способы BIN->BCD. Самое неприятное в таких преобразованиях (на контроллерах без аппаратного деления) - деление на 10. Для целочисленной арифметики жизнь можно облегчить, н-р, таким образом: Код Деление на 10: 8 bit: Y = (X * 0xCD) >> 11; 16 bit: Y = (X * 0xCCCD) >> 19; 32 bit: Y = (X * 0xCCCCCCCD) >> 35;
|
|
|
|
|
Oct 19 2009, 19:45
|
Участник

Группа: Участник
Сообщений: 53
Регистрация: 26-02-09
Пользователь №: 45 406

|
Так, кажется понял  буду пробовать, о результатах отпишусь!
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|