реклама на сайте
подробности

 
 
2 страниц V  < 1 2  
Reply to this topicStart new topic
> Датчик DS18B20, Нужен совет
ARV
сообщение Sep 15 2010, 18:01
Сообщение #16


Профессионал
*****

Группа: Свой
Сообщений: 1 143
Регистрация: 30-09-08
Из: Новочеркасск
Пользователь №: 40 581



у меня вообще сложилось впечатление, что Code Vision-овские библиотечные функции для работы с 1-wire сделаны как-то криво... прерывания надо запрещать на все время обмена - бред какой-то... я-то с WinAVR работаю, и сам не один вариант написал для обмена 1-wire, в том числе и для "многопортового" подключения нескольких датчиков... если надо - поищу исходники - но портировать в CVAVR не буду - это уже самостоятельно вы...


--------------------
Я бы взял частями... но мне надо сразу.
Go to the top of the page
 
+Quote Post
ILYAUL
сообщение Sep 15 2010, 21:12
Сообщение #17


Профессионал
*****

Группа: Свой
Сообщений: 1 940
Регистрация: 16-12-07
Из: Москва
Пользователь №: 33 339



zalg Вы создайте свою тему всё таки.


--------------------
Закон Мерфи:

Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
Go to the top of the page
 
+Quote Post
alexeyv
сообщение Sep 16 2010, 03:04
Сообщение #18


Местный
***

Группа: Участник
Сообщений: 298
Регистрация: 26-01-09
Из: Пермь
Пользователь №: 43 940



to zalg
Цитата(zalg @ Sep 15 2010, 23:04) *
У меня такая проблема. Писал код "с нуля" на ассемблере, все согласно даташиту. В итоге датчик реагирует, но как то странно. При включении показывает температуру +85 С(0550h в первых двух считанных байтах, затем считывание прекращаю, подавая "ресет" ). Насколько я понял, так и должно быть, НО затем он начинает фиксировать изменения температуры относительно этого значения, как будто калибруется при подаче питания. И еще одна странность - младший бит байта 0 - всегда ноль, т.е. при нагреве (если коснуться датчика пальцами) температура начинает расти так - 0550h,0552h,0554h и т.д. Перепроверял все по нескольку раз, симулировал в Proteus - работает как надо, уже грешу на датчик. Может кто сталкивался?

1. При чтении значения (тем более при первом) необходимо дождаться завершения измерения температуры, но перед этим необходимо подать команду на старт
2. Скажите какой датчик, может у него точность измерения температуры по умолчанию задана с дискретом в один градус?
3. Лучше сделать новый топик!

To Letis.
Пишу с использованием WinAVR (на AVR-асме не пишу более 5 лет)
В одной проге было два ds18s20 на одном порту
Вот моя реализация.

В вашем случае достаточно переделать макросы onew_input, onew_out_hi, onew_out_lo под большее количество датчиков

В ds18s20.h
Код
    #define DS18S_PORT               PORTE
    #define DS18S_DDR                DDRE
    #define DS18S_PIN                PINE
    #define PIN_DS18S_1WR     (_BV(2))
    #define PIN_DS18S_1RD     (_BV(3))
    #define PIN_DS18S_2WR     (_BV(4))
    #define PIN_DS18S_2RD     (_BV(5))

  #define onew_input(par)   (DS18S_PIN  &   (par ? PIN_DS18S_2RD : PIN_DS18S_1RD))
  #define onew_out_hi(par)   DS18S_PORT &= ~(par ? PIN_DS18S_2WR : PIN_DS18S_1WR)
  #define onew_out_lo(par)   DS18S_PORT |=  (par ? PIN_DS18S_2WR : PIN_DS18S_1WR)


В ds18s20.c
Код
//*****************************************************************************
// Layer 1 - Transmit/Receive Bit
void onew_set_lo(byte ch)
{
  byte s = SREG;
  cli();
  onew_out_lo (ch);
  _delay_us   (65);
  onew_out_hi (ch);
  _delay_us   (10); //5
  SREG = s;
}
//=============================================================================
void onew_set_hi(byte ch)
{
  byte s = SREG;
  cli();
  onew_out_lo (ch);
  _delay_us   (7); //
  onew_out_hi (ch);
  _delay_us   (70); // 65
  SREG = s;
}
//=============================================================================
byte onew_get_bit(byte ch)  
{
  byte t = 0;
  byte s = SREG;
  cli();
  onew_out_lo (ch);
  _delay_us   (2);
  onew_out_hi (ch);
  _delay_us   (12); //11
  if(onew_input(ch)) t=1;
  SREG = s;
  _delay_us   (60); //45
  return t;
}
//=============================================================================
byte onew_reset(byte ch)
{
  byte t = 0;
  byte s = SREG;
  cli();
  onew_out_lo (ch);
  _delay_us   (480);
  onew_out_hi (ch);
  _delay_us   (65);
  if(!onew_input(ch)) t=1;
  sei();
  SREG = s;
  _delay_us   (415);
  return t;
}
//*****************************************************************************


Сообщение отредактировал alexeyv - Sep 16 2010, 03:06
Go to the top of the page
 
+Quote Post
serge71
сообщение Sep 16 2010, 08:04
Сообщение #19


Участник
*

Группа: Участник
Сообщений: 18
Регистрация: 19-11-08
Из: Moscow region
Пользователь №: 41 766



to zalg:
Если младший бит "0", может всё же проверить кофигурационную ячейку разрешения датчика
Go to the top of the page
 
+Quote Post
Letis
сообщение Sep 16 2010, 09:20
Сообщение #20


Частый гость
**

Группа: Участник
Сообщений: 124
Регистрация: 10-07-07
Пользователь №: 29 027



Цитата
и сам не один вариант написал для обмена 1-wire, в том числе и для "многопортового" подключения нескольких датчиков... если надо - поищу исходники - но портировать в CVAVR не буду - это уже самостоятельно вы...

Виложите пожалуста код
Go to the top of the page
 
+Quote Post
ARV
сообщение Sep 16 2010, 11:42
Сообщение #21


Профессионал
*****

Группа: Свой
Сообщений: 1 143
Регистрация: 30-09-08
Из: Новочеркасск
Пользователь №: 40 581



Цитата(Letis @ Sep 16 2010, 13:20) *
Виложите пожалуста код
ну как бы вот... комментариев много - разберетесь, надеюсь.

Прикрепленные файлы
Прикрепленный файл  MyLib.rar ( 7.79 килобайт ) Кол-во скачиваний: 72
 


--------------------
Я бы взял частями... но мне надо сразу.
Go to the top of the page
 
+Quote Post
Letis
сообщение Sep 16 2010, 21:18
Сообщение #22


Частый гость
**

Группа: Участник
Сообщений: 124
Регистрация: 10-07-07
Пользователь №: 29 027



Код несколько не понятен в силу того что пишу в Code Vision.
І вот первый вопрос.
/// УКАЗАТЕЛЬ НА ПОРТ ВВОДА-ВЫВОДА
typedef volatile uint8_t* io_ptr;

ошибка: declaration syntax error.
Как мне переписать под мою программу.
Go to the top of the page
 
+Quote Post
ARV
сообщение Sep 17 2010, 06:17
Сообщение #23


Профессионал
*****

Группа: Свой
Сообщений: 1 143
Регистрация: 30-09-08
Из: Новочеркасск
Пользователь №: 40 581



Цитата(Letis @ Sep 17 2010, 01:18) *
Как мне переписать под мою программу.
не имею понятия - я вас предупреждал сразу: CodeVision не использую и нет желания даже пробовать


--------------------
Я бы взял частями... но мне надо сразу.
Go to the top of the page
 
+Quote Post
xemul
сообщение Sep 17 2010, 09:56
Сообщение #24



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(Letis @ Sep 17 2010, 01:18) *
Код несколько не понятен в силу того что пишу в Code Vision.
І вот первый вопрос.
/// УКАЗАТЕЛЬ НА ПОРТ ВВОДА-ВЫВОДА
typedef volatile uint8_t* io_ptr;

ошибка: declaration syntax error.

Посмотрите в мануале Code Vision, понимает ли он uint8_t.
Если не понимает, то или
typedef unsigned char uint8_t;
или замените все uint8_t на unsigned char.
Go to the top of the page
 
+Quote Post
Леонид Иванович
сообщение Sep 17 2010, 17:59
Сообщение #25


Местный
***

Группа: Участник
Сообщений: 318
Регистрация: 21-07-06
Из: Минск
Пользователь №: 18 986



Для нескольких термометров делал так:

Код
//----------------------------------------------------------------------------
//--------------------------- Цифровые датчики: ------------------------------
//----------------------------------------------------------------------------

//Используются термометры DS18B20 (S20), которые подключены к портам OWPn.
//Считывание и повторный запуск преобразования производится
//в момент считывание таходатчика того же канала.
//Считываются только два байта температуры, CRC не проверяется.
//Суммарное время опроса всех термометров должно быть больше
//времени преобразования, т.е. длительность интервала счета тахометра
//не должна быть меньше 750 мс / CHANNELS.
//Считанное значение температуры заносится в массив Temp[],
//температура представлена в десятых долях градуса.
//Диапазон возможных температур составляет от TEMP_MIN до TEMP_MAX
//градусов. При отсутствии термометра показания равны TEMP_MIN.

//------------------------------- Константы: ---------------------------------

  #define OWP0   (1 << PC0) //порт цифрового термометра 0
  #define OWP1   (1 << PC1) //порт цифрового термометра 1
  #define OWP2   (1 << PC2) //порт цифрового термометра 2
  #define OWP3   (1 << PC3) //порт цифрового термометра 3
  #define OWP4   (1 << PC4) //порт цифрового термометра 4
  #define OWP5   (1 << PC5) //порт цифрового термометра 5
  
  //Направление:
  #define I_DDRC  (0)
  //Подтягивающие резисторы / начальное состояние:
  #define I_PORTC (0)
  //Макроопределения для работы с портами:
  #define Port_OWP_0(m)   (DDRC |= m)
  #define Port_OWP_Z(m)   (DDRC &= ~m)
  #define Pin_OWP(m)      (PINC & m)

//Маски термометров:
const __flash char Masks[CHANNELS] = {OWP0, OWP1, OWP2, OWP3, OWP4, OWP5};

//------------------------------- Переменные: --------------------------------

static int Temp[CHANNELS];     //текущая температура
static bool Present[CHANNELS]; //флаги присутствия термометров

//---------------------------- Прототипы функций: ----------------------------

void Start(char n);         //старт термометра
void Read(char n);          //чиение термометра
void TReset(char n);        //генерация импульса сброса
char TByte(char n, char dat); //запись/чтение байта
bool TBit(char n, bool b);  //запись/чтение бита
void Do_Crc(char b, char *crc); //вычисление CRC

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

void Therm_Init(void)
{
  ACSR = (1<<ACD);          //запрещение аналогового компаратора
  for(char i = 0; i < CHANNELS; i++)
  {
    Temp[i] = TEMP_MIN;     //инициализация температуры
    Start(i);               //старт всех термометров
  }
}

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

void Therm_Exe(char n)
{
  Read(n);                  //чтение термометра - самое первое измерение
  Start(n);                 //старт термометра
}

//-------------------------- Старт термометра: -------------------------------

void Start(char n)
{
  TReset(n);                //импульс сброса
  if(Present[n])
  {
    TByte(n, 0xCC);         //skip ROM
    TByte(n, 0x44);         //convert T
  }
}

//------------------------- Чтение термометра: -------------------------------

void Read(char n)
{
  if(Present[n])
  {
    TReset(n);              //импульс сброса
    if(Present[n])
    {
      TByte(n, 0xCC);       //skip ROM
      TByte(n, 0xBE);       //read scratchpad
#ifdef DS18B20      
      char l = TByte(n, 0xFF); //чтение младшего байта
      char h = TByte(n, 0xFF); //чтение старшего байта
      int t = WORD(h, l);   //температура с дискретностью 0.0625°C
      t = (t * 10) / 16;    //температура с дискретностью 0.1°C
#else
      char Data[9];               //данные термометра
      char Crc = 0;               //инициализация CRC
      for(char i = 0; i < 9; i++)
      {
        char b = TByte(n, 0xFF);  //чтение данных
        Do_Crc(b, &Crc);          //обновление CRC
        Data[i] = b;              //сохранение данных
      }
      int t = TEMP_MIN;
      if(!Crc)
      {
        t = WORD(Data[1], Data[0]) / 2;
        t = (t * 20 - 5 + (int)(Data[7] - Data[6]) * 20 / Data[7]) / 2;
      }
#endif      
      Temp[n] = t;
      return;
    }
  }
  Temp[n] = TEMP_MIN;       //термометр отсутствует
  return;
}

//--------------------- Генерация импульса сброса: ---------------------------

void TReset(char n)
{
  char m = Masks[n];
  char si;
  Present[n] = 0;              //сброс флага присутствия термометра
  Port_OWP_0(m);               //OWP <- 0
  Delay_us(500);               //delay 500 uS
  si = __save_interrupt();
  __disable_interrupt();       //запрещение прерываний
  Port_OWP_Z(m);               //OWP <- 1
  Delay_us(14);                //delay 14 uS
  if(Pin_OWP(m))               //если OWP = 0, то ошибка
  {
    Delay_us(52);              //delay 52 uS
    if(!Pin_OWP(m))            //если OWP = 1, то ошибка
    {
      __restore_interrupt(si); //восстанавление прерываний
      Delay_us(250);           //delay 250 uS
      if(Pin_OWP(m))           //если OWP = 0, то ошибка
      {
        Present[n] = 1;        //если ошибок нет, термометр присутствует
      }
    }
  }
  __restore_interrupt(si);     //восстанавление прерываний в случае ошибки
}

//-------------- Запись/чтение байта по однопроводной шине: ------------------

char TByte(char n, char dat)
{
  char res;
  char m = Masks[n];
  for(char i = 0; i < 8; i++)
  {
    res = res >> 1;
    if(TBit(m, dat & 1)) res |= 0x80;
     else res &= ~0x80;
    dat = dat >> 1;
  }
  return(res);
}

//--------------- Запись/чтение бита по однопроводной шине: ------------------

bool TBit(char m, bool b)
{
  char si;
  si = __save_interrupt();
  __disable_interrupt();       //запрещение прерываний
  Port_OWP_0(m);               //OWP <- 0
  Delay_us(2);                 //delay 2 uS
  if(b) Port_OWP_Z(m);         //bit = 1, OWP <- 1
  Delay_us(13);                //delay 13 uS
  bool owp = Pin_OWP(m);       //чтение порта
  Delay_us(45);                //delay 45 uS
  Port_OWP_Z(m);               //OWP <- 1
  __restore_interrupt(si);     //восстанавление прерываний
  Delay_us(2);                 //delay 2 uS
  return(owp);
}

//--------------------- Вычисление контрольной суммы: ------------------------

void Do_Crc(char b, char *crc)
{
  for(char i = 0; i < 8; b = b >> 1, i++)
    if((b ^ *crc) & 1) *crc = ((*crc ^ 0x18) >> 1) | 0x80;
     else *crc = (*crc >> 1) & ~0x80;
}


--------------------
Go to the top of the page
 
+Quote Post

2 страниц V  < 1 2
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 11:03
Рейтинг@Mail.ru


Страница сгенерированна за 0.01429 секунд с 7
ELECTRONIX ©2004-2016