Jump to content

    
Sign in to follow this  
iiv

Atmega328P и DS18B20 в фоновом режиме

Recommended Posts

Всем привет,

 

имеется атмега328п, хочется к ней прикрутить несколько, от одного до четырех, датчиков температуры DS18B20 по 1-wire. Незадачка в том, что эта атмега должна в реальном времени выполнять кучу другой работы, которую нельзя прерывать 100мкс-750мс ожиданиями протокола 1-wire.

 

В то же время, как я понимаю из прочтения исходников протокола общения с этими датчиками, большую часть времени микроконтроллер должен ждать.

 

Возникает идея, что этот протокол может быть реализован на прерываниях таймера и int0 (я могу повесить 1-wire на эту ножку) и практически не занимать время процессора, но программировать это может быть довольно не тривиально.

 

Скажите, пожалуйста, может кто-то уже такое запрограммировал, и такие исходники существуют в сети? Если да, тыкните, пожалуйста, пальцем где скачать. Если нет, может я в чем-то ошибаюсь и это не так просто, как мне кажется?

 

Знаю, что есть еще решение - поставить на плату тиньку или еще одну ардуину, которая будет 100% занята опросами этой температуры, но очень не хотелось бы это делать.

 

Спасибо

 

ИИВ

Share this post


Link to post
Share on other sites

Вариантов реализации 1-Wire довольно много - выбирай любой. И ждать там совсем незачем, принцип простой: раз в секунду (например) прочитали температуру, потом сразу же отправили команду на преобразование. К следующей секунде преобразование как раз будет готово.

А вообще, прерывания там желательно запрещать только на время приема/отправки одного бита.

Edited by birden

Share this post


Link to post
Share on other sites

100 мкс - 750 мкс ждать никогда не нужно с запрещенными прерываниями. запрет прерываний требуется на 15-60 мкс максимум, так что сколько-нибудь заметного влияния на фоновые процессы обмен 1-wire не должен оказать

Share this post


Link to post
Share on other sites
Возникает идея, что этот протокол может быть реализован на прерываниях таймера и int0 (я могу повесить 1-wire на эту ножку) и практически не занимать время процессора, но программировать это может быть довольно не тривиально.

Да, такая реализация вполне возможна. Я не представляю: зачем Вам int0 ? Я без него обошелся, одним таймером... Надавно встретилась в инете статья про использование в целях работы по 1-wire USART (если есть свободный). Работает USART фактически как таймер (скорость передачи настраивается так, что время передачи байта - нужное для реализации протокола 1-wire), но, ещё и импульсы на Tx формирует...

Share this post


Link to post
Share on other sites
100 мкс - 750 мкс ждать никогда не нужно с запрещенными прерываниями. запрет прерываний требуется на 15-60 мкс максимум, так что сколько-нибудь заметного влияния на фоновые процессы обмен 1-wire не должен оказать

на сколько понимаю, 5-10мкс (или все-таки 60 мкс?) мне надо ждать для передачи одного бита, а передавать надо где-то 16 байт, то есть на момент коммуникации мне надо выделить 1-2 милисекунду. Вот их-то я и не готов выделить, так как в реальном времени у меня с 6 портов идут конвертации с АЦП и на результаты мне надо реагировать незамедлительно.

 

Термодатчики хочу вкрячить на силовые модули, чтобы мониторить нагрев мосфетов во время работы...

Share this post


Link to post
Share on other sites
Надавно встретилась в инете статья про использование в целях работы по 1-wire USART (если есть свободный). Работает USART фактически как таймер (скорость передачи настраивается так, что время передачи байта - нужное для реализации протокола 1-wire), но, ещё и импульсы на Tx формирует...

 

Изумительно хорошо работает. При этом можно точно определить, когда датчик готов выдать результат на гора. Обычно он делает это быстрее , чем 750мс

 

 

раз в секунду (например) прочитали температуру

 

Это перебор , если конечно датчик чем-то не нагревать в течении секунды

Share this post


Link to post
Share on other sites
или все-таки 60 мкс?

 

Если делать всё корректно, то 60 мкс. Тайм-слот надо полностью закончить, а только потом разрешать прерывания, иначе передача нуля может затянуться и это будет воспринято как сброс. Ну и после сброса чтение ответа устройства делается примерно через 65 мкс, тут без запрещенных прерываний никак.

 

Можно поделить работу с датчиками на элементарные операции, каждая из которых будет не длиннее 60 мкс. Ведь между тайм-слотами задержка не ограничивается. Я делал что-то подобное, но делил на байты, Вам же нужно поделить на биты:

 

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

//DSS-90
//Модуль обслуживания термометра 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);	 //запись/чтение бита

//--------------------- Инициализация термометра: ----------------------------

void DS18B20_Init(void)
{
 Temp = T_NORDY;	  //результат измерения не готов
 TState = 0;		  //начало процесса
}

//----------------------- Измерение температуры: -----------------------------

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);
}

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

Edited by IgorKossak
[codebox]

Share this post


Link to post
Share on other sites
на сколько понимаю, 5-10мкс (или все-таки 60 мкс?)

можно глянуть тут исходники, они на ассемблере, зато сама программа в реальном времени сканирует

клавиатурную матрицу 4х4, с помощью динамической индикации работает со светодиодной матрицей 4х4х2 двухцветные диоды,

читает таблетку 1-wire,

сама прикидывается подчинееным 1-wire устройством,

все одновременно без паразитных подмаргиваний индикации при работе 1-wire интерфейсов.

http://electronix.ru/forum/index.php?showt...st&p=672770

Share this post


Link to post
Share on other sites
Если делать всё корректно, то 60 мкс. Тайм-слот надо полностью закончить, а только потом разрешать прерывания, иначе передача нуля может затянуться и это будет воспринято как сброс. Ну и после сброса чтение ответа устройства делается примерно через 65 мкс, тут без запрещенных прерываний никак.

 

Можно поделить работу с датчиками на элементарные операции, каждая из которых будет не длиннее 60 мкс. Ведь между тайм-слотами задержка не ограничивается. Я делал что-то подобное, но делил на байты, Вам же нужно поделить на биты:

 

Огромное Вам спасибо, Леонид Иванович,

 

я чувствовал, что так оно и должно быть, но, не сильно хорошо владея предметом, возможно не совсем понятно задал вопрос...

 

Надеюсь, что в 45мкс задержку смогу положить несколько других важных операций, длительность которых мне полностью известна. Опрашивать по-видимому надо будет 5 датчиков, буду разбираться хватит ли у меня свободных ног для этого...

Share this post


Link to post
Share on other sites
Изумительно хорошо работает.

Для проектов, где есть свободный UART у Maxim из AN214 можно позаимствовать идею использования UART для реализации 1-wire Bus Master

Share this post


Link to post
Share on other sites
Для проектов, где есть свободный UART у Maxim из AN214 можно позаимствовать идею использования UART для реализации 1-wire Bus Master

У MAXIM чего только нет. Так например для Ds18x20 отдельный application, но я делал по ATMEL - хорошо расписан USART для 1- wire / И даже где-то встречал русский перевод какого-то из этих applications.

Applications.rar

Share this post


Link to post
Share on other sites

По одному проводу 4 датчика часто читать нельзя, перегреваются они, да и не получится физически, на каждый уйдет примерно 1 сек.

Я бы поставил отдельно тиньку и загрузил бы ее этой работой, после этого через UART уже командовать ней.

 

Share this post


Link to post
Share on other sites
По одному проводу 4 датчика часто читать нельзя, перегреваются они, да и не получится физически, на каждый уйдет примерно 1 сек.
не на каждый уйдет 1 сек, а на все сразу. думаю, пару десятков датчиков за 1 секунду можно успеть опросить :)

Share this post


Link to post
Share on other sites
не на каждый уйдет 1 сек, а на все сразу. думаю, пару десятков датчиков за 1 секунду можно успеть опросить :)

ага, я уже 5 прикрутил, без основного софта на основе one-wire.cpp и все в секунду укладывается, но вот в параллель-то конечно надо все аккуратно расписать...

Share this post


Link to post
Share on other sites
ага, я уже 5 прикрутил, без основного софта на основе one-wire.cpp и все в секунду укладывается, но вот в параллель-то конечно надо все аккуратно расписать...

 

Почему параллель? До начала чтения данных с датчиков , Вы работаете со всеми сразу игнорируя ID микросхем, а вот чтение для каждого своё.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this