//функция определения датчика на шине char dt_testdevice(void) //dt - digital termomether | определим, есть ли устройство на шине { //char stektemp=SREG;// сохраним значение стека cli(); //запрещаем прерывание char dt; DDRTEMP |= 1<<BITTEMP; //притягиваем шину _delay_us(485); //задержка как минимум на 480 микросекунд DDRTEMP &= ~(1<<BITTEMP); //отпускаем шину _delay_us(65); //задержка как максимум на 60 микросекунд if ((PINTEMP & (1<<BITTEMP))==0)//проверяем, ответит ли устройство { dt=1;//устройство есть } else dt=0;//устройства нет //SREG = stektemp;// вернем значение стека _delay_us(420); //задержка как минимум на 480 микросекунд, но хватит и 420, тк это с учетом времени прошедших команд return dt; //вернем результат }
//функция записи бита на устройство void dt_sendbit(char bt) { //char stektemp=SREG;// сохраним значение стека cli(); //запрещаем прерывание DDRTEMP |= 1<<BITTEMP; //притягиваем шину _delay_us(2); //задержка как минимум на 2 микросекунды if(bt) DDRTEMP &= ~(1<<BITTEMP); //отпускаем шину _delay_us(65); //задержка как минимум на 60 микросекунд DDRTEMP &= ~(1<<BITTEMP); //отпускаем шину //SREG = stektemp;// вернем значение стека } //функция записи байта на устройство void dt_sendbyte(unsigned char bt) { char i; for(i=0;i<8;i++)//посылаем отдельно каждый бит на устройство { if((bt & (1<<i)) == 1<<i)//посылаем 1 dt_sendbit(1); else //посылаем 0 dt_sendbit(0); } }
//функция чтения бита с устройства char dt_readbit(void) { //char stektemp=SREG;// сохраним значение стека cli(); //запрещаем прерывание char bt; //переменная хранения бита DDRTEMP |= 1<<BITTEMP; //притягиваем шину _delay_us(2); //задержка как минимум на 2 микросекунды DDRTEMP &= ~(1<<BITTEMP); //отпускаем шину _delay_us(13); bt = (PINTEMP & (1<<BITTEMP))>>BITTEMP; //читаем бит _delay_us(45); // SREG = stektemp;// вернем значение стека return bt; //вернем результат }
//функция чтения байта с устройства unsigned char dt_readbyte(void) { char c=0; char i; for(i=0;i<8;i++) c|=dt_readbit()<<i; //читаем бит return c; }
//функция преобразования показаний датчика в температуру int dt_check(void) { unsigned char bt;//переменная для считывания байта unsigned int tt=0; if(dt_testdevice()==1) //если устройство нашлось { dt_sendbyte(NOID); //пропустить идентификацию, тк у нас только одно устройство на шине dt_sendbyte(T_CONVERT); //измеряем температуру _delay_ms(750); //в 12битном режиме преобразования - 750 милисекунд dt_testdevice(); //снова используем те же манипуляции с шиной что и при проверке ее присутствия dt_sendbyte(NOID); //пропустить идентификацию, тк у нас только одно устройство на шине dt_sendbyte(READ_DATA); //даем команду на чтение данных с устройства bt = dt_readbyte(); //читаем младший бит tt = dt_readbyte(); //читаем старший бит MS tt = (tt<<8)|bt;//сдвигаем старший влево, младший пишем на его место, тем самым получаем общий результат } return tt; } uint8_t ds18b20_GetSign(uint16_t dt) { //Проверим 11-й бит if (dt&(1<<11)) return 1; else return 0; } //преобразование температуры в единицы char converttemp (unsigned int tt) { char t = tt>>4;//сдвиг и отсечение части старшего байта return t; }
uint16_t l = r[0], m = r[1], v; int32_t t; if(r[4] == 0xff){ // DS18S20 t = ((uint32_t)l) * 10; t >>= 1; }else{ // DS18B20 v = ((m & 7) << 8)| l; t = ((uint32_t)v)*10; t >>= 4; } if(m & 0x80) t = -t;
_________________ Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда. Я на гитхабе, в ЖЖ
uint16_t l = r[0], m = r[1], v; int32_t t; if(r[4] == 0xff){ // DS18S20 t = ((uint32_t)l) * 10; t >>= 1; }else{ // DS18B20 v = ((m & 7) << 8)| l; t = ((uint32_t)v)*10; t >>= 4; } if(m & 0x80) t = -t;
У вас много переменных вы хоть бы закоментировали обозначили а и б сидели на трубе. А у меня нет варнингов Микрочип студию использываю для AVR. Я всё понимаю что программу мою нужно переработать.Так откуда начать перерабатывать.?Я понимаю что нужно две переменные для положительной температуры и для отрицательной.А дальше поплыл мозгами.
extern uint8_t ow_Answ[9]; // Внешняя глобальная (мне хвостом, что это не кошерно!) переменная, которая хранит полный ответ датчика (значение из его Scratch Pad), включая температуру и настройки предупреждений. // Код в другом файле исходника просто циклически отправляет команду оцифровки температуры и производит чтение данных.
УСЁ. В переменной находится целочисленное(!) значение температуры в градусах цельсия, домноженное на 10. 0° = 0 12,3° = 123 -55° = -550
Почему-то все начали биться с дополнительными битами температуры, а DS уже возвращает число в формате INT16, знаковом. Откройте даташит на датчик, долистайте до таблицы 1 `Table 1. Temperature/Data Relationship`, возьмите отрицательную температуру из примера, вбейте в калькулятор, который умеет переводить системы счисления и... И вдруг сходится!
... Я понимаю что нужно две переменные для положительной температуры и для отрицательной.
The temperature data is stored as a 16-bit sign-extended two’s complement number in the temperature register (see Figure 4). The sign bits (S) indicate if the temperature is positive or negative: for positive numbers S = 0 and for negative numbers S = 1.
Нет. Она одна, со знаком. (см. как обозначается знак в 16-битных целочисленных выражениях - бинарная математика).
пример (стр. 6 из pdf-а DS18B20): -10.125 oC = 0b1111 1111 0101 1110 = 0xFF5E
-------
попробуйте:
Код:
//функция преобразования показаний датчика в температуру int dt_check(void) { int bt; //переменная для считывания байта int tt = 0;
if (dt_testdevice() == 1) { //если устройство нашлось dt_sendbyte(NOID); //пропустить идентификацию, тк у нас только одно устройство на шине dt_sendbyte(T_CONVERT); //измеряем температуру _delay_ms(750); //в 12битном режиме преобразования - 750 милисекунд dt_testdevice(); //снова используем те же манипуляции с шиной что и при проверке ее присутствия dt_sendbyte(NOID); //пропустить идентификацию, тк у нас только одно устройство на шине dt_sendbyte(READ_DATA); //даем команду на чтение данных с устройства bt = dt_readbyte(); //читаем младший бит tt = dt_readbyte(); //читаем старший бит MS } return ((tt << 8) | bt); //сдвигаем старший влево, младший пишем на его место, тем самым получаем общий результат }
затем используйте функцию: int temp = dt_check() * 5 / 8; Будет температура * 10 со знаком (+ или -).
Примеры: 256 = 25,6 оC -54 = -5,4 оC
Последний раз редактировалось veso74 Пн июн 13, 2022 18:19:18, всего редактировалось 2 раз(а).
У вас много переменных вы хоть бы закоментировали обозначили а и б сидели на трубе.
Не нужны там комментарии: и так все ясно же! Кстати, я там сильно перемудрил: достаточно было сделать температуру int16_t, и не пришлось бы эти пляски с масками устраивать!
_________________ Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда. Я на гитхабе, в ЖЖ
Eddy_Em, tnx за идею обработки ниже нуля. При t * 5 / 8 с отрицательным числом иногда теряю 0,1 через шаг например. (По первой идее - от переполнения?)
Последний раз редактировалось veso74 Пн июн 13, 2022 20:52:40, всего редактировалось 4 раз(а).
Учитывая то, что у DS18 точность - хуже ±0.5℃, вообще не нужно на десятые заморачиваться. Можно сразу в целых градусах Цельсия выводить результат, все равно брехня!
_________________ Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда. Я на гитхабе, в ЖЖ
Учитывая то, что у DS18 точность - хуже ±0.5℃, вообще не нужно на десятые заморачиваться. Можно сразу в целых градусах Цельсия выводить результат, все равно брехня!
Так покажите полную картину вывода на экран LCD?.А то кусочек секса не интересно. И вообще СССР мертвое государство как Атлантида.
А, нееет, мне нужны показания. DS18B20 можно исползовать даже как датчик присутствия! Зима например, вношу чашку горячее кофе в комнате, на 1 метр и уже через 3 минуты могу сказать, что есть кофе в комнате . Есть рост t + 0,2 оC. --- То ли Протеус грешит при -t, то ли другого, еще не исправил неточность ...
Последний раз редактировалось veso74 Пн июн 13, 2022 20:54:56, всего редактировалось 1 раз.
veso74, согласен: относительную температуру вроде бы более-менее измеряет. Но вот воспроизводимость никакущая. Хоть калибруй — все равно ±0.1℃ не получить. Поэтому я и советовал обычный дешевый терморезистор. Тот, правда, по какому-нибудь хорошему термометру нужно будет откалибровать, зато тоже ±0.5℃ получим. Я себе делал контроллер домашней файлопомойки: 4 точки измерения температуры, для упрощения вычислений - кусочно-линейная аппроксимация калибровочной кривой.
_________________ Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда. Я на гитхабе, в ЖЖ
Ну, это до поры — до времени, пока не нужно будет измерять температуры за пределами возможностей DS18. Скажем, температуру вблизи кипения азота я измерял платиновыми терморезисторами (на 2010г стоили почти по 1000р за штучку), для температур выше кипения воды при н.у. нужны будут тоже или терморезисторы или термопары. В общем, помимо простейших вариантов всегда полезно в загашнике иметь разнообразие.
_________________ Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда. Я на гитхабе, в ЖЖ
УСЁ. В переменной находится целочисленное(!) значение температуры в градусах цельсия, домноженное на 10.
Хорошее решение. Я делал так:
Код:
uint16_t t; uint8_t s, d; if(temperature < 0) { s = 1; t = -temperature; } else { s = 0; t = temperature; } d = t & 0b1111; // *5, /8 с округлением d += d << 2; d += 4; d >>= 3; t >>= 4; sprintf(aTextOut, " Temperature = %s%u.%u", s ? "-" : "+", t, d);
Последний раз редактировалось Карбофос Пн июн 13, 2022 21:22:30, всего редактировалось 1 раз.
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 17
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения