STM Урок 92. Датчик температуры DS18B20. Часть 3

 

 

 

 

Урок 92

 

Часть 3

 

Датчик температуры DS18B20

 

 

В предыдущей части урока мы познакомились с организацией памяти датчика, а также написали ещё несколько нужных функций.

 

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

 

//----------------------------------------------------------

void ds18b20_ReadStratcpad(uint8_t mode, uint8_t *Data, uint8_t DevNum)

{

  uint8_t i;

  ds18b20_Reset();

  if(mode==SKIP_ROM)

  {

    //SKIP ROM

    ds18b20_WriteByte(0xCC);

  }

  //READ SCRATCHPAD

  ds18b20_WriteByte(0xBE);

  for(i=0;i<8;i++)

  {

    Data[i] = ds18b20_ReadByte();

  }

}

//----------------------------------------------------------

 

Функция данная тоже в особом объяснении не нуждается. Входные аргументы — это адрес массива, в который мы будем читать 8 байтов памяти, следующий — это режим, и последний — номер устройства.

Мы также сначала перезагружаем наш датчик, по условию режима даём команду пропустить чтение ROM, а затем подаём команду 0xBE, которая заставляет устройство передать нам байти памяти, которые мы затем читаем в цикле в наш массив.

Вот объяснение команды чтения памяти из технической документации

 

Image26

 

Добавим на эти две функции прототипы в заголовочном файле.

Перейдём в функцию main() и добавим там ещё ряд локальных переменных

 

uint8_t status;

uint8_t dt[8];

uint16_t raw_temper;

float temper;

char c;

 

Затем там добавим следующий код в бесконечном цикле

 

/* USER CODE BEGIN 3 */

ds18b20_MeasureTemperCmd(SKIP_ROM, 0);

HAL_Delay(800);

ds18b20_ReadStratcpad(SKIP_ROM, dt, 0);

sprintf(str1,"STRATHPAD: %02X %02X %02X %02X %02X %02X %02X %02X; ",

dt[0], dt[1], dt[2], dt[3], dt[4], dt[5], dt[6], dt[7]);

HAL_UART_Transmit(&huart1,(uint8_t*)str1,strlen(str1),0x1000);

sprintf(str1,"rn");

HAL_UART_Transmit(&huart1,(uint8_t*)str1,strlen(str1),0x1000);

HAL_Delay(150);

}

/* USER CODE END 3 */

 

Мы сначала даём команду на измерение и конвертацию температуры, ждём 800 милисекунд (на всякий случай, положено не менее 750 при нашей дискретности), Потом даём команду на чтении памяти и отображаем её в шестнадцатеричном виде в терминальной программе. Затем мы пока отдельно переносим строку и переводим каретку, а также ждём ещё немного до следующего чтения. Всё вместе получится приблизительно секунда. Для такого точного чтения температуры очень даже неплохо.

Соберём код, прошьём контроллер и посмотрим результат в терминале

 

Image27

 

Вот что мы прочитали. Первые два байта — это значение температуры. В нашем случае 0x9101. можно даже свободно вычислить температуру. В двоичном выражении эти 2 байта будут выглядеть как 0000000110010001. Получается что температура у нас положительная, так как первые пять старших бит у нас в нулях. В следующих семи битах у нас результат 0011001, что в десятично выражении будет 25, а в самых младших четырёх битах — 0001, это значт 1/16 доля градуса. получается что температура равна 25 и 1/16 градуса. У меня стоит термометр в часах, который приблизительно столько и показывает, можен немного побольше. Так что показания похожи на правду.

 

 

Посмотрим также считывание байтов в программе логического анализа. Вот наш Strathpad

 

Image28

 

Также помомтрим как именно выглядят считанные биты на графике

 

Image29

 

А выглядят они аналогично записываемых.

Здесь мы прочитали 0x93, что в двоичном вражении будет 10010011. Читаем справа налево. Так оно и есть. Единички опять у нас в виде коротеньких импульсов направленных вниз, а нолики — длинные.

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

 

//----------------------------------------------------------

uint8_t ds18b20_GetSign(uint16_t dt)

{

  //Проверим 11-й бит

  if (dt&(1<<11)) return 1;

  else return 0;

}

//----------------------------------------------------------

 

Здесь всё просто. Нам достаточно проверить любой из 5 старших битов. проверим 11-й. Тем более уж его-то проверять мы давно умеем, у нас ведь и ножка порта 11-я (магия, ничего не скажешь). И если он в единице, то её и вернём, иначе вернём ноль.

Также напишем ещё функцию преобразования самого значения температуры в результат с плавающей запятой

 

//----------------------------------------------------------

float ds18b20_Convert(uint16_t dt)

{

  float t;

  t = (float) ((dt&0x07FF)>>4); //отборосим знаковые и дробные биты

  //Прибавим дробную часть

  t += (float)(dt&0x000F) / 16.0f;

  return t;

}

//----------------------------------------------------------

 

Здесь также всё просто. Отключим все знаковые биты маской, сдвинем всю последовательность затем на 4 пункта вправо, отбробсив дробную часть, затем значение 4 младших бит разделим на 16 и прибавим к результату. Вот и всё. Очень даже легко.

Добавим на наши функции прототипы в заголовочный файл и перейдём в бесконечный цикл функции main().

Удалим там код перевода каретки и переноса строки и добавим вместо него следующий код

 

HAL_UART_Transmit(&huart1,(uint8_t*)str1,strlen(str1),0x1000);

raw_temper = ((uint16_t)dt[1]<<8)|dt[0];

if(ds18b20_GetSign(raw_temper)) c='-';

else c='+';

temper = ds18b20_Convert(raw_temper);

sprintf(str1,"Raw t: 0x%04X; t: %c%.2frn", raw_temper, c, temper);

HAL_UART_Transmit(&huart1,(uint8_t*)str1,strlen(str1),0x1000);

HAL_Delay(150);

 

Соберём код, прошьём контроллер и посмотрим результат в терминальной программе

 

Image30

 

Вот теперь всё понятно!

Я докоснулся до датчика пальцем руки и подержал. Температура начала расти.

Итак. Мы сегодня научились работать с датчиком температуры DS18B20, подключенному по шине 1-WIRE к контроллеру STM32 безо всякой аппаратной поддержки путём дрыганья ножкой порта. Также мы изучили ряд команд этого датчика, смогли считать с него температуру. Пока это единственный датчик на шине, но я надеюсь, что мы справимся и с несколькими. Тем более я уже подготовил такой датчик.

Ждите следующих уроков.

Всем спасибо за внимание!

 

Предыдущая часть Программирование МК STM32 Следующий урок

 

Исходный код

 

 

Отладочную плату можно приобрести здесь STM32F103C8T6

Логический анализатор можно приобрести здесь Логический анализатор на 8 каналов

Датчик температуры в экране с проводом можно приобрести здесь DS18B20 в экране с проводом

Переходник USB to TTL можно приобрести здесь ftdi ft232rl

 

 

Смотреть ВИДЕОУРОК (нажмите на картинку)

 

STM Датчик температуры DS18B20

8 комментариев на “STM Урок 92. Датчик температуры DS18B20. Часть 3
  1. Александр:

    Добрый день.
    Столкнулся с проблемой — датчик не работает. Точнее не совсем верно. При работе считывается не верно карта памяти — адекватные показания первых 8-ми разрядов (правда они не соответствуют реальным) и соответственно выводит ахинею… Есть такое чувство что вопрос по временным задержкам. Может поможете, или подскажете как решить проблему…
    И еще. В одном из уроков проскочила фраза о возможности использования прерывания от таймера для формирования задержек. Может в одном из следующих уроков поднимется данный вопрос. Буду благодарен, и наверное не только я.
    Спасибо за вашу работу…

  2. Зачем дробную часть делить на 16?

  3. И кстати если тип переменной значения температуры объявить как целое со знаком, то никаких манипуляций с определением знака не потребуется. Единица в старшем разряде для чисел со знаком автоматически считается знаком.

  4. Сергей:

    У меня DS18B20 в стальном, герметичном исполнении. При переходе к отрицательным температурам датчик переходит к инверсным данным. Т.е. если при 0 градусов первые два байта 00 00, то самый маленький минус это FF FE, при этом написанная программа преобразует их в -127 градусов. Если при проверке знака температуры, ещё и вычитать первые два байта при отрицательной температуре из FF FF, то температура преобразуется правильно.

  5. Сергей:

    неправильно написал не FF FE а FE FF, сперва младший байт, затем старший.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*