Как обрабатывать переменную с DS18B20 для десятых долей °С ?

Обсуждаем контроллеры компании Atmel.
Ответить
Прорезались зубы
Сообщения: 213
Зарегистрирован: Вт сен 09, 2008 18:17:27

Сообщение DENIS451 »

Как дешевле обрабатывать переменную с DS18B20 для получения числа -55.0...125.0 , то есть выводить знак
и десятые доли °С на C/C++ для AVR?

Можно ли обойтись без плавающей точки?

Сейчас я нашёл такой пример (байты выводятся на экранчик):

Код: Выделить всё

sendchar(tt/10+0x30);//Преобразуем число в код числа 
sendchar(tt%10+0x30);//Преобразуем число в код числа
sendchar('*');
sendchar('C');
(в перемменную tt получем 12-и разрядное значение, отбрасываем четыре младших бита - получаем диапазон 0...99 °С)

Прилагаю формат переменной из датащита:
Изображение
Вложения
Формат переменной.png
(49.33 КБ) 1355 скачиваний
Реклама
afz
Опытный кот
Аватара пользователя
Сообщения: 744
Зарегистрирован: Сб дек 22, 2012 08:17:42
Откуда: Караганда, Казахстан

Сообщение afz »

Это же где-то недавно обсуждалось. Плавучка тут и даром не нужна, все делается в целых числах. Берем число, полученное из 18b20 (типа int), отделяем от него знак и превращаем в положительное. Затем умножаем его на 10, прибавляем 8 и делим на 16 (две последних операции - это округление). Полученное число градусов переводим в десятичное и приписываем перед ним знак. Все.

Код: Выделить всё

    uint8_t sgn;
    uint16_t temper;

    sgn = ' ';
    temper = temp1820;
    if(temp1820 < 0)
    {
        sgn - '-';
        temper = -temp1820;
    }
    trmper *= 10;
    temper += 8;
    temper /= 16;
Да, учитывая, что температура может быть от -55 до 125, необязательно использовать полноценную программу перевода 2-10. Вполне достаточно разделить температуру на 1000, частное будет первой цифрой. Остаток делим на 100, частное будет второй цифрой. Остаток делим на 10, частное будет третьей цифрой, остаток - четвертой (десятые доли). И весь хрен до копейки. Если эти коды предназначены на вывод через что-то семисегментное, то полученные три частных и один остаток можно использовать непосредственно (тогда и знак в переменной sgn надо будет отмечать другими кодами, например, ноль - плюс, единица - минус), если же надо в ASCII, то к каждому из кодов частных и остатку надо будет логически прибавить 0x30 ('0'), ну и вставить точку между третьей и четвертой цифрами.
Последний раз редактировалось afz Вс авг 12, 2018 15:00:15, всего редактировалось 1 раз.
Кто мешает тебе выдумать порох непромокаемый? (К. Прутков, мысль № 133)
Реклама
Прорезались зубы
Сообщения: 213
Зарегистрирован: Вт сен 09, 2008 18:17:27

Сообщение DENIS451 »

Спасибо, скоро попробую.

Добавлено after 6 hours 44 minutes 3 seconds:
Re: Как обрабатывать переменную с DS18B20 для десятых долей °С ?
Вот что получилось:

Код: Выделить всё

tt = dt_check(); //Получаем значение температуры

uint8_t sgn;
uint16_t temper;
sgn = ' ';
temper = tt;
if(tt < 0)
  {
  sgn = '-';
  temper = -tt;
  }
temper *= 10;
temper += 7;
temper /= 16;
	   
setpos(0,0);
sendchar(sgn);
sendchar(temper/1000+0x30);
sendchar((temper%1000)/100+0x30);
sendchar((temper%100)/10+0x30);
sendchar('.');  
sendchar((temper%10)+0x30);
sendchar('*');
sendchar('C');
sendchar(' '); 
Незначащие нули пока не гасил.
Переменная tt у меня типа int (AtmelStudio 6.2) но почему то код работает, она не 32 битная что ли?
Точно ли нужно прибавлять восмёрку а не семёрку (в Протеусе происходит завышение на 0.1 °С)?
afz
Опытный кот
Аватара пользователя
Сообщения: 744
Зарегистрирован: Сб дек 22, 2012 08:17:42
Откуда: Караганда, Казахстан

Сообщение afz »

Что-то ты путаешь. Или Протеус врёт. Вот я посчитал на Визуальном Си.

Код: Выделить всё

  10          1.0000    1.0   10
  11          1.0625    1.1   11
  12          1.1250    1.1   11
  13          1.1875    1.2   12
  14          1.2500    1.3   13
  15          1.3125    1.3   13
  16          1.3750    1.4   14
  17          1.4375    1.4   14
  18          1.5000    1.5   15
  19          1.5625    1.6   16
  1A          1.6250    1.6   16
  1B          1.6875    1.7   17
  1C          1.7500    1.8   18
  1D          1.8125    1.8   18
  1E          1.8750    1.9   19
  1F          1.9375    1.9   19
Первая колонка - код, якобы от 1820, от 1.0000 градусов до 1.9375 (1.F hex). Вторая - точное значение, третья - округленное значение (простой вывод числа из 2-й колонки по шаблону %6.1f, четвертая - результат предложенного мной алгоритма. Ну и где больше на 0.1 ?

Добавлено after 43 minutes:
Re: Как обрабатывать переменную с DS18B20 для десятых долей °С ?
Да, преобразование в десятичное и выдачу я не проверял, может там косяк? Я бы, кстати, делал это немного не так. Что-то, вроде

Код: Выделить всё

     num = temper / 1000;
     temper %= 1000;
<манипулируем num - это первая цифра>
     num = temper / 100;
     temper %= 100;
< и т.д.>
Здесь же можно будет подумать на тему гашения ведущих нулей.
Кто мешает тебе выдумать порох непромокаемый? (К. Прутков, мысль № 133)
Реклама
Эиком - электронные компоненты и радиодетали
Прорезались зубы
Сообщения: 213
Зарегистрирован: Вт сен 09, 2008 18:17:27

Сообщение DENIS451 »

Ок, значит Протеус посылает байты завышенные на 0,1 °С от задаваемого значения.
Реклама
afz
Опытный кот
Аватара пользователя
Сообщения: 744
Зарегистрирован: Сб дек 22, 2012 08:17:42
Откуда: Караганда, Казахстан

Сообщение afz »

Элементарно - посмотри переменную temper после команды temper = tt; а затем пройди пошагово всё вычисление.
Кто мешает тебе выдумать порох непромокаемый? (К. Прутков, мысль № 133)
Реклама
Ответить

Вернуться в «AVR»