Динамическая индикация и датчик DS18B20
Добрый день. Возник вопрос. Есть светодиодный 7-сегментный индикатор. Динамически вывожу цифры, все нормально, а вот в момент опроса датчика, индикация гаснет, так как МК работает с датчиком. Как это победить. Если общаюсь с датчиком в обработчике прерывания по таймеру, та же шляпа. Может я что-то не догоняю?
Я не волшебник, я только лечусь
- Реклама
Нужно прерывания от таймера заточить под индикацию. Тогда не зависимо от работы с датчиком цифры будут выводиться.
Только во время расчета температуры(преобразования полученных данных от датчика) прерывание это отключать во избежании не верного преобразования.
Только во время расчета температуры(преобразования полученных данных от датчика) прерывание это отключать во избежании не верного преобразования.
Что значит "общаюсь"?Gurvinok писал(а):общаюсь с датчиком в обработчике прерывания по таймеру
Процедуру запускаете, или каждый тайм-слот?
ICQ нет, и, в ближайшее время, не будет.
Я раньше дел с динамической индикацией не имел. Отсюда и возник вопрос. Я пытался каждую секунду в обработчике прерывания по таймеру получить температуру из датчика. Как я понял надо делать все на оборот. Температура в основном цикле, индикация в прерывании. Единственная засада в том что я использую готовую библиотеку для работы с датчиком. Терзают смутные сомнения что придется все делать самому.
Я не волшебник, я только лечусь
Тему модно закрывать. В библиотеке было так.
Я не понял зачем там такая задержка. После ее выкидывания все заработало.
Код: Выделить всё
w1_write(0x44);
delay_ms(550);
Я не волшебник, я только лечусь
- Реклама
Вообще-то для более правильного ответа ТС не помешало-бы выложить исходник, и уже опираясь на него (исходник) вести дальнейшую дискуссию ИМХО....
Порой мне кажется, что я делаю какое-то дерьмо, но когда я вижу, что делают другие, то я чувствую себя гением...
Я уже писал, что разобрался. Сочинители библиотеки в CVAVR с перепугу вогнали задержку в пол секунды. Зачем она нужна я так и не понял. В общем перехожу на AVRStudio и буду все с низов писать. CVAVR фигня какая-то.
Я не волшебник, я только лечусь
120% поддерживаюGurvinok писал(а):В общем перехожу на AVRStudio и буду все с низов писать. CVAVR фигня какая-то.
Порой мне кажется, что я делаю какое-то дерьмо, но когда я вижу, что делают другие, то я чувствую себя гением...
Вы, батенька, оказывается "либерал". А я тут про тайм-слоты распинаюсь.Gurvinok писал(а):После ее выкидывания все заработало.
А если посмотреть в ДШ, что означает команда 0x44, а после этого во временнЫе характеристики?Gurvinok писал(а):Я не понял зачем там такая задержка.
Выяснится, что, например для 12-битного преобразования, задержка нужна вообще не менее 750ms.
Хотя такая реализация, это - "решение в лоб", или для "паразитного" питания. При всех других условиях, его можно реализовать гораздо правильней.
P.S.: Ну, а что бы получать равные временнЫе интервалы (что необходимо для нормальной динамической индикации), надо научиться пользоваться такими вещами, как прерывания от таймера.
ICQ нет, и, в ближайшее время, не будет.
Я столкнулся с такой проблемой в часах на неоновом индикаторе ГИПС-16. Там нужно разворачивать строку из 111 столбцов по 7 точек в высоту. Вывод на индикацию завязан на прерывания от таймера, а нарушения последовательности заметны сразу. Если дать приоритет прерываний на индикацию, датчик DS18B20 может неправильно среагировать на нарушенную временную диаграмму. В итоге он иногда даёт чушь, а не температуру. Если часто опрашивать датчик, глуша прерывания, На индикации заметны "бяки" и моргания.
Сделал опрос редким, раз в пол-минуты. Не глуша прерывания, шлю команды: reset bus, затем &HCC (skip rom), затем &H44 (Convert).
Далее, через несколько секунд, глушу прерывания и шлю &HCC и &HBE. Получаю температуру. Запускаю прерывания. На индикаторе, при тщательном рассмотрении, может что-то и мигает. Не особо заметно. Вся математика преобразования 2-х байт в градусы и другие дела, происходят в фоне, не мешая динамической индикации.
Сделал опрос редким, раз в пол-минуты. Не глуша прерывания, шлю команды: reset bus, затем &HCC (skip rom), затем &H44 (Convert).
Далее, через несколько секунд, глушу прерывания и шлю &HCC и &HBE. Получаю температуру. Запускаю прерывания. На индикаторе, при тщательном рассмотрении, может что-то и мигает. Не особо заметно. Вся математика преобразования 2-х байт в градусы и другие дела, происходят в фоне, не мешая динамической индикации.
Стандартное решение подсчет строк на длительность межопросного интервала и передача/прием данных в "мертвом окне" в конце строки. 
Когда сделал динамическую индикацию не по прерываниям, а в основном цикле, тоже возник конфликт с DS18B20. Пришлось обмен разбить на элементарные операции:
Спойлер
Код: Выделить всё
//----------------------------------------------------------------------------
//Модуль обслуживания термометра DS18B20
//Цифровой датчик температуры DS18B20 подключен по 1-проводному
//интерфейсу, который реализован программно.
//Для подключения датчика используется порт OWP.
//Порт должен быть настроен на ввод,
//внутренний подтягивающий резистор должен быть отключен,
//используется внешний подтягивающий резистор 4.7 кОм.
//Во время измерения обеспечивается сильноточная
//подтяжка линии данных (порт переключается на вывод ВЫСОКОГО уровня),
//поэтому возможно использование термометра с паразитным питанием.
//Должны быть определены следующие макросы:
//#define OWP (1 << Pxn)
//#define Port_OWP_OUT (DDRx |= OWP)
//#define Port_OWP_IN (DDRx &= ~OWP)
//#define Pin_OWP (PINx & OWP)
//Датчик DS18B20 должен быть запрограммирован в 12-разрядный режим
//(биты R0, R1 в регистре конфигурации равны единице,
//это заводская установка).
//Дискретность измерения температуры составляет 0.1°C.
//Из датчика считываются только 2 байта, CRC не проверяется.
//Для инициализации модуля один раз в начале программы должна
//вызываться функция DS18B20_Init(). Функция DS18B20_Exe() должна
//вызываться в основном цикле, она осуществляет запуск преобразования,
//формирует в фоновом режиме временную задержку и производит считывание
//температуры во внутреннюю переменную Temp.
//Поскольку обмен по однопроводной шине довольно медленный (чтение или
//запись одного байта занимает около 0.5 мс), целиком выполнять
//чтение температуры и запуск преобразования за один вызов DS18B20_Exe()
//нельзя. Это может нарушить выполнение других задач. Поэтому процесс
//обмена с термометром разбит на элементарные операции, каждая из
//которых включает в себя обмен не более чем одним байтом.
//Значение температуры в любой момент может быть считано с помощью функции
//DS18B20_GetT(). Значение представлено в виде 16-разрядного целого числа
//со знаком и представляет собой температуру в десятых долях градуса.
//До того, как закончится первое преобразование температуры, возвращается
//значение T_NORDY. В случае отсутствия ответа термометра возвращается
//код ошибки T_ERROR.
//----------------------------------------------------------------------------
#include "Main.h"
#include "DS18B20.h"
//------------------------------ Константы: ----------------------------------
#define TCONV 800 //время преобразования температуры, мс
//----------------------------- Переменные: ----------------------------------
static int Temp; //текущая температура
static char TState; //состояние процесса измерения
//-------------------------- Прототипы функций: ------------------------------
bool TReset(void); //формирование импульса сброса
char TByte(char dat); //запись/чтение байта
bool TBit(bool b); //запись/чтение бита
//--------------------- Инициализация термометра: ----------------------------
;вызывается 1 раз
void DS18B20_Init(void)
{
Temp = T_NORDY; //результат измерения не готов
TState = 0; //начало процесса
}
//----------------------- Измерение температуры: -----------------------------
;вызывается в цикле, t устанавливается в обработчике
;системного таймера раз в 0.5 мс
void DS18B20_Exe(bool t)
{
static int TTimer = 0; //таймер термометра
static int T; //код температуры
if(t)
{
if(TTimer) //если интервал таймера не истек,
{
TTimer--; //ожидание (и декремент таймера)
}
else //иначе выполнение шага
{
switch(TState)
{
case 0: if(TReset()) //команда RESET
TState++; //если выполнена успешно, следующий шаг
else TState = 0xFF; //если ошибка, переход на задержку
break;
case 1: TByte(0xCC); //команда SKIP ROM
TState++; //следующий шаг
break;
case 2: TByte(0x44); //команда START CONVERSION
TTimer = ms2sys(TCONV); //загрузка задержки преобразования
TState++; //следующий шаг
break;
case 3: if(TReset()) //команда RESET
TState++; //если выполнена успешно, следующий шаг
else TState = 0xFF; //если ошибка, переход на задержку
break;
case 4: TByte(0xCC); //команда SKIP ROM
TState++; //следующий шаг
break;
case 5: TByte(0xBE); //команда READ SCRATCHPAD
TState++; //следующий шаг
break;
case 6: T = TByte(0xFF); //чтение TL
TState++; //следующий шаг
break;
case 7: T |= TByte(0xFF) << 8; //чтение TH
TState++; //следующий шаг
break;
case 8: Temp = 10 * T / 16; //вычисление температуры
TState = 0; //переход на первый шаг
break;
default: TTimer = ms2sys(TCONV); //загрузка задержки
Temp = T_ERROR; //код ошибки
TState = 0; //переход на первый шаг
}
}
}
}
//--------------------- Генерация импульса сброса: ---------------------------
bool TReset(void)
{
char si;
Port_OWP_0;
Port_OWP_OUT; //OWP <- 0
Delay_us(500); //delay 500 uS
si = __save_interrupt();
__disable_interrupt(); //запрещение прерываний
Port_OWP_IN; //OWP <- 1
Delay_us(14); //delay 14 uS
if(Pin_OWP) //если OWP = 0, то ошибка
{
Delay_us(52); //delay 52 uS
if(!Pin_OWP) //если OWP = 1, то ошибка
{
__restore_interrupt(si); //восстанавление прерываний
Delay_us(250); //delay 250 uS
if(Pin_OWP) //если OWP = 0, то ошибка
{
return(1); //если ошибок нет, термометр присутствует
}
}
}
__restore_interrupt(si); //восстанавление прерываний в случае ошибки
return(0);
}
//-------------- Запись/чтение байта по однопроводной шине: ------------------
char TByte(char dat)
{
char res;
for(char i = 0; i < 8; i++)
{
res = res >> 1;
if(TBit(dat & 1)) res |= 0x80;
else res &= ~0x80;
dat = dat >> 1;
}
return(res);
}
//--------------- Запись/чтение бита по однопроводной шине: ------------------
bool TBit(bool b)
{
char si;
si = __save_interrupt();
__disable_interrupt(); //запрещение прерываний
Port_OWP_0;
Port_OWP_OUT; //OWP <- 0
Delay_us(2); //delay 2 uS
if(b) Port_OWP_IN; //bit = 1, OWP <- 1
Delay_us(13); //delay 13 uS
bool owp = Pin_OWP; //чтение порта
Delay_us(45); //delay 45 uS
Port_OWP_1; //force pullup
Port_OWP_OUT;
__restore_interrupt(si); //восстанавление прерываний
Delay_us(2); //delay 2 uS
return(owp);
}
//------------------------- Чтение температуры: ------------------------------
int DS18B20_GetT(void)
{
return(Temp);
}
//----------------------------------------------------------------------------
BOB51 так действительно не будет костылей в цикле индикации. Будет время - переделаю. Сейчас цикл опроса никак не связан с индикацией. Индикация только по таймеру, другое по циклу и счётчику в программе. Лениво переделывать то, что работает пару лет без вмешательства...
А если еще посмотреть, то можно увидеть что если используем внешнее питание то после команды 0х44 можно забить на временнЫе интервалы. Пока датчик думает и раскладывает все по своим полкам, шину прижимает к нулю, а когда все готово отпускает.А если посмотреть в ДШ, что означает команда 0x44, а после этого во временнЫе характеристики?
Может я и ошибаюсь, но CVAVR запрещает прерывания при работе функций 1-wire. Где находится библиотека я так и не понял. Только хедоровый файл с объявленными функциями. Еще раз повторяю! CVAVR это какое-то недоразумение. Переписал все в Студии 6.1 и все работает.Ну, а что бы получать равные временнЫе интервалы (что необходимо для нормальной динамической индикации), надо научиться пользоваться такими вещами, как прерывания от таймера.
Я не волшебник, я только лечусь
А если посмотреть ещё внимательней, то можно обнаружить, что про это уже давно сказано.Gurvinok писал(а):А если еще посмотреть, то можно увидеть что если используем внешнее питание то после команды 0х44 можно забить на временнЫе интервалы
ICQ нет, и, в ближайшее время, не будет.
Где?про это уже давно сказано
Лан, хорош.
Я не волшебник, я только лечусь
Да вот же:Gurvinok писал(а):Где?
Dmitry Dubrovenko писал(а):Хотя такая реализация, это - "решение в лоб", или для "паразитного" питания. При всех других условиях, его можно реализовать гораздо правильней.
ICQ нет, и, в ближайшее время, не будет.


