|
Преобразовать данные с DS18B20 в строку printf |
|
|
|
Oct 2 2013, 14:52
|
Группа: Участник
Сообщений: 14
Регистрация: 19-01-08
Пользователь №: 34 227

|
Здравствуйте. Сразу хочу извиниться что для многих мой вопрос покажется примитивным, но всё же. Считал я температуру с термометра DS18B20 в 2 регистра temp1 (char) и temp2 (char) . Младшая тетрада temp1 и старшая тетрада temp2 имеют значение целой части температуры. Младшая тетрада temp2 имеет дробную часть температуры. Я хочу строчкой printf("...") вывести в уарт МК данные чтобы у меня показывало температуру в формате 25.4 Голову сломал не знаю как сделать  Помогите пожалуйста. Понятно что вопрос дилетанта. Работаю в CodeVisionAVR. МК atmega8. Спасибо.
Сообщение отредактировал Pilot134 - Oct 2 2013, 14:54
|
|
|
|
|
Oct 2 2013, 15:24
|
Гуру
     
Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702

|
Цитата(Pilot134 @ Oct 2 2013, 18:52)  Здравствуйте. Сразу хочу извиниться что для многих мой вопрос покажется примитивным, но всё же. Считал я температуру с термометра DS18B20 в 2 регистра temp1 (char) и temp2 (char) . Младшая тетрада temp1 и старшая тетрада temp2 имеют значение целой части температуры. Младшая тетрада temp2 имеет дробную часть температуры. Я хочу строчкой printf("...") вывести в уарт МК данные чтобы у меня показывало температуру в формате 25.4 Голову сломал не знаю как сделать  Помогите пожалуйста. Понятно что вопрос дилетанта. Работаю в CodeVisionAVR. МК atmega8. Спасибо. printf("temp=%2x.%d", temp1, temp2); Но что делать с отрицательной температурой?
|
|
|
|
|
Oct 2 2013, 15:36
|
Группа: Участник
Сообщений: 14
Регистрация: 19-01-08
Пользователь №: 34 227

|
Цитата(adnega @ Oct 2 2013, 21:24)  printf("temp=%2x.%d", temp1, temp2); До отрицательной ещё не добрался. Вставил Ваш вариант и не заработало  Цитата(megajohn @ Oct 2 2013, 21:18)  все домой ушли, так что если вечер свободен то можете этот кусок подправить для вывода дробной части Код #ifdef DS18B20 #define DS18X20_SHIFT 4 #endif
lsb = OneWireReadByte( mask ); msb = OneWireReadByte( mask ); s16 curr_temper_cels = (msb << 8) + lsb; if( curr_temper_cels & (1 << 15) ) { curr_temper_cels = -curr_temper_cels; curr_temper_cels = (curr_temper_cels * 10) >> DS18X20_SHIFT; curr_temper_cels = -curr_temper_cels; // Restore sign. } else { curr_temper_cels = (curr_temper_cels * 10) >> DS18X20_SHIFT; }
printf( "temper=%d", curr_temper_cels ); Посмотрел код и у меня вопрос. Строчка: s16 curr_temper_cels = (msb << 8) + lsb; - переменная формата sig int curr_temper_cels. Мы в неё записываем старший байт (temp1) сдвинутый 8 раз влево и прибавляем младший байт. ___ Строчка: curr_temper_cels = (curr_temper_cels * 10) >> DS18X20_SHIFT; - берёт переменную curr_temper_cels и умножает её на 10, сдвигает 4-е раза вправо и вновь вписывает в переменную curr_temper_cels Правильно я понимаю? Спасибо.
|
|
|
|
|
Oct 2 2013, 15:43
|
Гуру
     
Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702

|
Цитата(Pilot134 @ Oct 2 2013, 19:36)  До отрицательной ещё не добрался. Вставил Ваш вариант и не заработало  А тут работает http://codepad.org/eTaPDzDXА в чем неработоспособность заключается? printf("Hello World") работает?
|
|
|
|
|
Oct 2 2013, 16:00
|
Группа: Участник
Сообщений: 14
Регистрация: 19-01-08
Пользователь №: 34 227

|
Цитата(adnega @ Oct 2 2013, 21:43)  printf("Hello World") работает? Это работает  Вопрос в том чтобы преобразовать значение с термометра DS18B20 в строчку printf("...") и чтобы температура выводилась в виде 25.6 Я считал температуру с датчика DS18B20 и она содержится в 2-х байтах. В старшем (temp1) и младшем (temp2). Я уже научился выводить целую часть температуры: Код temperatura = ((temp1)<<4)|(temp2>>4); printf("temp = %d C\r\n",temperatura); и вижу на компе текст (комп с микроконтроллером общаются по усарту) temp = 26 С А вот с дробной частью пока проблема  Отрицательные температуры ещё не делал  Цитата(adnega @ Oct 2 2013, 21:43)   там то работает. Дело в том что у термометра DS18B20 температура считывается определённым образом. Как видно из скрина старший байт только в младшей тетраде содержит значения целой части температуры. А младший - старшая тетрада содержит также целую часть, а младшая тетрада младшего байта содержит только лишь дробную часть. Спасибо что отозвались!
Сообщение отредактировал Pilot134 - Oct 2 2013, 16:03
Эскизы прикрепленных изображений
|
|
|
|
|
Oct 3 2013, 04:14
|
Группа: Участник
Сообщений: 14
Регистрация: 19-01-08
Пользователь №: 34 227

|
Цитата(adnega @ Oct 2 2013, 22:39)  Как температура выдается DS18B20 и то, как описали Вы в первом посте вещи, мягко говоря, не эквивалентные. Виноват Цитата(adnega @ Oct 2 2013, 22:39)  Спасибо! То что нужно
|
|
|
|
|
Oct 4 2013, 16:16
|
Группа: Участник
Сообщений: 14
Регистрация: 19-01-08
Пользователь №: 34 227

|
Очень сильно извиняюсь! Но появился ещё один вопрос - как можно перевести двоично-десятичное число в двоичное. Причём двоично-десятичное содержит 3 значящих тетрады. Т.е. число типа int 0000 0011 0100 0101 (2dec) нужно преоборазовать в int 0000 0001 0101 1001 (Bin) где 0000 0011 0100 0101 - число 0345 двоично-десятичное а 0000 0001 0101 1001 - двоичное число 345. Спасибо.
|
|
|
|
|
Oct 5 2013, 14:40
|
Группа: Участник
Сообщений: 14
Регистрация: 19-01-08
Пользователь №: 34 227

|
Цитата(Палыч @ Oct 4 2013, 22:33)  Так - как этому учат в школе: первую тетраду умножаем на 100, складываем со второй тетрадой умноженной на 10, и всё это складываем с третьей тетрадой... Спасибо!
|
|
|
|
|
Oct 7 2013, 07:10
|
Группа: Участник
Сообщений: 14
Регистрация: 19-01-08
Пользователь №: 34 227

|
Только пожалуйста не ругайтесь. Но что-то немного не понял  У устройства есть вывод значений температуры (порог) на дисплей. Кнопками я могу редактировать это значение и вписываю (например) цифры 26,5. Всего 3 цифры. Мне нужно чтобы при достижении этой температуры включалось реле и сигнализировало (т.е. сравнивать значения на дисплее с показаниями с термометра). Соответственно у меня есть переменные zifr_1 = 0x02, zifr_2 = 0x06, zifr_3 = 0x05 (двоично-десятичный код) У термометра DS18B20 этой температуре соответствует код 0000 0001 1010 1000 (двоичный код) Как я могу перейти в одинаковую систему единиц для их сравнения? Я сначала думал что нужно: 0x02(hex) * 100(dec) = 0b1100 1000 + 0x06(hex) * 10(dec) = 0b0011 1100 + 0b00000101 = 1 0000 1001 Что ни как не равно показаниям термометра (0000 0001 1010 1000). Зашёл в тупик  Помогите пожалуйста.
Сообщение отредактировал Pilot134 - Oct 7 2013, 07:32
|
|
|
|
|
Oct 7 2013, 07:57
|

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

|
Цитата(Pilot134 @ Oct 7 2013, 11:10)  Зашёл в тупик  Помогите пожалуйста. 1. Пусть у нас есть три цифры: А - десятки единиц, В - единицы, С - десятые доли 2. Следует получить двоичное число, где запятая стоит перед четвертым разрядом (т.е. умноженное на 16 = 2 в степени 4) - см. документацию на м/с. 3. Из А,В и С получаем число АВС, выраженное в десятых долях (т.е. 10 раз большее чем есть на самом деле): А*100 + В*10 + С 4. Вспоминаем (см.п2), что нам нужно число, умноженное на 16 (А*100 + В*10 + С) * 16 5. У нас же было число увеличенное в 10 раз (см.п3), поэтому делим на 10: (А*100 + В*10 + С) * 16 / 10
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|