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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> DS18B20 + WinAVR, не инициализируется датчик :(
Labinskiy Nikola...
сообщение Jul 22 2006, 07:20
Сообщение #1


Участник
*

Группа: Новичок
Сообщений: 27
Регистрация: 5-07-06
Из: Украина, Донецк
Пользователь №: 18 606



DQ подтянут 4к7 на +5 вольт. Датчик один, питание полное(на датчик тоже идет +5В)
Код
#include <avr/io.h>
#include <avr/eeprom.h>
#include <inttypes.h>
#include <stdio.h>
#include <string.h>

#define F_CPU 1000000UL  // 1 MHz
#include <util/delay.h>


void delay_us(uint16_t t)
{
  int i;
  if (t > 10)
    for (i=0;i<t/10;i++)
      _delay_us(10);
  else
    _delay_us(t);
}

void delay_ms(uint16_t t)
{
  int i;
  if (t > 10)
    for (i=0;i<t/10;i++)
      _delay_ms(10);
  else
    _delay_ms(t);
}

int ds_reset()
{
  int r=0;
  PORTA &= ~(1<<4);
  DDRA |= (1<<4);        // DQ = 0;
  delay_us(500);        // 480us minimum
  DDRA &= ~(1<<4);        // DQ in
  delay_us(80);            // waits 15-60us and then
  r = (PINA & (1<<4));    //   capture the presence pulse (60-240us)
  delay_us(400);        
  return !r;
}

все время возвращает 0. В чем может быть проблема?
Если в датчике то как его можно быстро и просто проверить?


--------------------
If you can't make it good - don't make it look good ;)
Go to the top of the page
 
+Quote Post
xemul
сообщение Jul 22 2006, 09:24
Сообщение #2



*****

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



Цитата(Labinskiy Nikolay @ Jul 22 2006, 11:20) *
DQ подтянут 4к7 на +5 вольт. Датчик один, питание полное(на датчик тоже идет +5В)
Код
#include <avr/io.h>
#include <avr/eeprom.h>
#include <inttypes.h>
#include <stdio.h>
#include <string.h>

#define F_CPU 1000000UL  // 1 MHz
#include <util/delay.h>


void delay_us(uint16_t t)
{
  int i;
  if (t > 10)
    for (i=0;i<t/10;i++)
      _delay_us(10);
  else
    _delay_us(t);
}

void delay_ms(uint16_t t)
{
  int i;
  if (t > 10)
    for (i=0;i<t/10;i++)
      _delay_ms(10);
  else
    _delay_ms(t);
}

int ds_reset()
{
  int r=0;
  PORTA &= ~(1<<4);
  DDRA |= (1<<4);        // DQ = 0;
  delay_us(500);        // 480us minimum
  DDRA &= ~(1<<4);        // DQ in

  delay_us(80);            // waits 15-60us and then

  r = (PINA & (1<<4));    //   capture the presence pulse (60-240us)
  delay_us(400);        
  return !r;
}

все время возвращает 0. В чем может быть проблема?
Если в датчике то как его можно быстро и просто проверить?

Проблема в 80 мкс задержке. В даташитах на ванварь черным по английски сказано:
Presence Detect Sample Time tMSP min=60us, max=75us
со сноской: Note 1: System requirement.

В функции delay_us не учитываются задержки на вызов и возврат из функции. Это делает ее совершенно бессмысленной для задержек менее 10 мкс и относительно разумной для задержек менее 30-40 мкс при F_CPU 1000000UL.

Сообщение отредактировал xemul - Jul 22 2006, 09:25
Go to the top of the page
 
+Quote Post
Labinskiy Nikola...
сообщение Jul 22 2006, 09:43
Сообщение #3


Участник
*

Группа: Новичок
Сообщений: 27
Регистрация: 5-07-06
Из: Украина, Донецк
Пользователь №: 18 606



Цитата(xemul @ Jul 22 2006, 12:24) *
Проблема в 80 мкс задержке. В даташитах на ванварь черным по английски сказано:
Presence Detect Sample Time tMSP min=60us, max=75us
со сноской: Note 1: System requirement.

В функции delay_us не учитываются задержки на вызов и возврат из функции. Это делает ее совершенно бессмысленной для задержек менее 10 мкс и относительно разумной для задержек менее 30-40 мкс при F_CPU 1000000UL.



Прикрепленное изображение


Как тогда корректно делать задержки?


--------------------
If you can't make it good - don't make it look good ;)
Go to the top of the page
 
+Quote Post
beer_warrior
сообщение Jul 22 2006, 09:54
Сообщение #4


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

Группа: Свой
Сообщений: 1 065
Регистрация: 8-10-05
Из: Kiev, UA
Пользователь №: 9 380



Цитата
Как тогда корректно делать задержки?

Прерыванием.
Еще частота низковата 1МГц - 1(2)мкс на команду, 5-7 команд на процедуру, тут дай бог на асме уложиться.


--------------------
Вони шукають те, чого нема,
Щоб довести, що його не існує.
Go to the top of the page
 
+Quote Post
virtuality
сообщение Jul 22 2006, 10:11
Сообщение #5


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

Группа: Свой
Сообщений: 83
Регистрация: 17-05-06
Пользователь №: 17 190



Вставлю свою лепту - у меня, да и судя по постам у других людей на форуме была проблема с датчиком из-за того, что контроллер работал на внутреннем RC-генераторе на частоте 1 МГц, а программа была настроена на 8 МГц. Зажгите светодиод на 1 секунду, и проверьте, соответствует ли...
Go to the top of the page
 
+Quote Post
aesok
сообщение Jul 22 2006, 10:22
Сообщение #6


Знающий
****

Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484



Цитата(Labinskiy Nikolay @ Jul 22 2006, 11:20) *
Код
#include <avr/io.h>

void delay_us(uint16_t t)

  int i;
  if (t > 10)
    for (i=0;i<t/10;i++)
      _delay_us(10);
  else
    _delay_us(t);
}

}


В этой функции 2 ошибки:
1. Вы используете деление в цикле: "for (i=0;i<t/10;i++)", на эту операцию требуеться примернр 200 циклов (AVR200: Multiply and Divide Routines). Следовательно вы получаете дополнительную задежку в 200us к каждым 10.

2. _delay_us(t); -так нельзя. Используйте '_delay_us' (и '_delay_мs') только с константами, или вы получите дополнительную задежку на несколько операций с плавуещей точкой:

Код
    \note When using _delay_us() and _delay_ms(), the expressions
    passed as arguments to these functions shall be compile-time
    constants, otherwise the floating-point calculations to setup the
    loops will be done at run-time, thereby drastically increasing
    both the resulting code size, as well as the time required to
    setup the loops.


В вашем случае вы можете применять '_delay_us' для задежек до 768us. Читайте описание '_delay_us'.

Анатолий.

Сообщение отредактировал aesok - Jul 22 2006, 10:37
Go to the top of the page
 
+Quote Post
xemul
сообщение Jul 22 2006, 10:31
Сообщение #7



*****

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



Цитата(Labinskiy Nikolay @ Jul 22 2006, 13:43) *
Цитата(xemul @ Jul 22 2006, 12:24) *

Проблема в 80 мкс задержке. В даташитах на ванварь черным по английски сказано:
Presence Detect Sample Time tMSP min=60us, max=75us
со сноской: Note 1: System requirement.

В функции delay_us не учитываются задержки на вызов и возврат из функции. Это делает ее совершенно бессмысленной для задержек менее 10 мкс и относительно разумной для задержек менее 30-40 мкс при F_CPU 1000000UL.



Прикрепленное изображение


Как тогда корректно делать задержки?

Извините, не посмотрел, что для датчиков температуры ворота по Presence Pulse гораздо шире, чем для iButton. Тем не менее, если программу написать под стандартные тайминги для iButton, она будет работать и с остальными ванварными девайсами.
Посмотрите AN126.pdf
Я делал задержки более 70 мкс кратными этим самым 70 мкс (т.е., н-р, сброс = 7*70) и отрабатывал их по 70-мкс таймерному прерыванию. Мелкие задержки при Fclk=1MHz приходилось делать nop'ами, goto $+1 (синтаксис PIC'ов) и циклами ожидания.
Go to the top of the page
 
+Quote Post
Labinskiy Nikola...
сообщение Jul 22 2006, 11:04
Сообщение #8


Участник
*

Группа: Новичок
Сообщений: 27
Регистрация: 5-07-06
Из: Украина, Донецк
Пользователь №: 18 606



Цитата(virtuality @ Jul 22 2006, 13:11) *
Вставлю свою лепту - у меня, да и судя по постам у других людей на форуме была проблема с датчиком из-за того, что контроллер работал на внутреннем RC-генераторе на частоте 1 МГц, а программа была настроена на 8 МГц. Зажгите светодиод на 1 секунду, и проверьте, соответствует ли...

все ок

aesok, xemul, спасибо.


--------------------
If you can't make it good - don't make it look good ;)
Go to the top of the page
 
+Quote Post
xemul
сообщение Jul 22 2006, 11:27
Сообщение #9



*****

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



Цитата(Labinskiy Nikolay @ Jul 22 2006, 15:04) *
все ок

И это здОровоsmile.gif.
Кста, длительность Presence Pulse и время выборки все-таки одинаковы для всех ванварных девайсов
для стандартной скорости обмена:
Presence Detect High Time 15-60 us
Presence Detect Low Time 60-240 us
Presence Detect Sample Time 60-75 us
Go to the top of the page
 
+Quote Post
Labinskiy Nikola...
сообщение Jul 22 2006, 11:55
Сообщение #10


Участник
*

Группа: Новичок
Сообщений: 27
Регистрация: 5-07-06
Из: Украина, Донецк
Пользователь №: 18 606



вот что получилось:
Код
#include <avr/io.h>
#include <avr/eeprom.h>
#include <inttypes.h>
#include <stdio.h>
#include <string.h>

#define F_CPU 1000000UL  // 1 MHz
#include <util/delay.h>


void delay_ms(uint16_t t)
{
  uint8_t i;
  if (t > 10)
    for (i=0;i<t/10;i++)
      _delay_ms(10);
  else
    _delay_ms(t);
}

int ds_reset()
{
  uint8_t r=0;
  PORTA &= ~(1<<4);
  DDRA |= (1<<4);        // DQ = 0;
  _delay_us(480);
  DDRA &= ~(1<<4);        // DQ pull up
  _delay_us(70);
  r = (PINA & (1<<4));    // Capture the presence pulse
  _delay_us(410);        
  return !r;
}

void ds_write_bit(uint8_t b)
{
  if (b)
    {
        PORTA &= ~(1<<4);
      DDRA |= (1<<4);        // DQ = 0;
        _delay_us(6);
        DDRA &= ~(1<<4);        // DQ pull up
        _delay_us(64);    
    }
  else
    {
      PORTA &= ~(1<<4);
      DDRA |= (1<<4);        // DQ = 0;
      _delay_us(60);
      DDRA &= ~(1<<4);        // DQ pull up
      _delay_us(10);
    };
}

uint8_t ds_read_bit()
{
  uint8_t r=0;
  PORTA &= ~(1<<4);
  DDRA |= (1<<4);        // DQ = 0;
  _delay_us(6);
  DDRA &= ~(1<<4);        // DQ pull up
  _delay_us(9);
  r = (PINA & (1<<4));
  _delay_us(55);
  if (r)
    return 1;
  else
    return 0;
}

void ds_write_byte(uint8_t data)
{
  uint8_t loop;
  // Loop to write each bit in the byte, LS-bit first
  for (loop = 0; loop < 8; loop++)
    {
      ds_write_bit(data & 0x01);
      // shift the data byte for the next bit
      data >>= 1;
    }
}

uint8_t ds_read_byte()
{
  uint8_t loop, result=0;
  for (loop = 0; loop < 8; loop++)
    {
      // shift the result to get it ready for the next bit
      result >>= 1;
      // if result is one, then set MS bit
      if (ds_read_bit())
        result |= 0x80;
    }
  return result;
}

int16_t ds_read_temperature()
{
  int16_t r = -1;
  int i;
  uint8_t buf[9]={0};

  if (ds_reset())
    {
      ds_write_byte(0xCC);    //Skip ROM command
      ds_write_byte(0x44);    //Convert T command
      delay_ms(1000);        // lame :)
      ds_write_byte(0xBE);    //Read Scratchpad
      for (i=0; i < 10; i++)
        buf[i] = ds_read_byte();
      r = (buf[0] | (buf[1] << 8)) >> 4;

    };
  return r;
}

но инициализация все равно не проходит...
может что-то с датчиком?


--------------------
If you can't make it good - don't make it look good ;)
Go to the top of the page
 
+Quote Post
xemul
сообщение Jul 22 2006, 14:05
Сообщение #11



*****

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



Цитата(Labinskiy Nikolay @ Jul 22 2006, 15:55) *
вот что получилось:
[skipped]
но инициализация все равно не проходит...
может что-то с датчиком?

Вряд ли.
На сайте господина protoss'а лежат его сорцы для борьбы с ванварью:
1Wire.C
1Wire.Asm
за что ему большое спасибо.
Я на AVR только переползаю и пока не владею особенностями генерации кода компиляторами для этой архитектуры. Тем не менее, общие соображения:
1) посмотрите ассемблерный текст и вручную посчитайте время выполнения/выполните профилирование по ванварным функциям.
2) если в программе используются прерывания, на время выполнения коротких задержек и связанных с ними манипуляций со входами/выходами их придется запрещать.

И для упрощения жизни компилятору и контроллеру я бы сделал так:
Код
void delay_ms(uint16_t t)
{
   uint8_t i;
   if (t > 10)
      for (i=t/10;i;i--)
         _delay_ms(10);
      else
         _delay_ms(t);
}


или так
Код
void delay_ms(uint16_t t)
{
   uint8_t i;
   if (t >= 256)
   {
      for (i=t/256;i;i--)
         _delay_ms(256);
      t &= 255;
   }
   _delay_ms(t);
}


Сообщение отредактировал xemul - Jul 22 2006, 14:07
Go to the top of the page
 
+Quote Post
Labinskiy Nikola...
сообщение Jul 22 2006, 15:03
Сообщение #12


Участник
*

Группа: Новичок
Сообщений: 27
Регистрация: 5-07-06
Из: Украина, Донецк
Пользователь №: 18 606



Спасибо за ссылки, ну а delay_ms у меня только и осталась чтобы сделать одну большую задержку на ~1 секунду, ну а где нужно поточнее использовал _delay_us(const)...
З.Ы. прерывания не используются...

Сообщение отредактировал Labinskiy Nikolay - Jul 22 2006, 15:07


--------------------
If you can't make it good - don't make it look good ;)
Go to the top of the page
 
+Quote Post
WHALE
сообщение Jul 22 2006, 17:17
Сообщение #13


Знающий
****

Группа: Свой
Сообщений: 902
Регистрация: 2-01-06
Из: Краснодар
Пользователь №: 12 768



Вручную считать задержки-нафига? cranky.gif Тот самый случай,когда симулятор-то,что доктор прописал


--------------------
"Hello, word!" - 17 errors 56 warnings
Go to the top of the page
 
+Quote Post
xemul
сообщение Jul 22 2006, 17:50
Сообщение #14



*****

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



Цитата(WHALE @ Jul 22 2006, 21:17) *
Вручную считать задержки-нафига? cranky.gif Тот самый случай,когда симулятор-то,что доктор прописал

Если там пять команд, то почему бы и нет? Заодно можно подивиться разумности компилятора. Или наоборотsmile.gif.
Go to the top of the page
 
+Quote Post
Labinskiy Nikola...
сообщение Jul 25 2006, 18:20
Сообщение #15


Участник
*

Группа: Новичок
Сообщений: 27
Регистрация: 5-07-06
Из: Украина, Донецк
Пользователь №: 18 606



Ничего не понимаю...
PORTA.4(нумерация с нуля) Mega16(внутренний 1 МГц) подключон через 4к7 к +5 и от туда же (прямо от порта перед резистором) подключон DQ DS18B20, еще две ножки датчика подключены на +5 и землю (непаразитное питание).. Ошибок в схеме вроде нету, но вот на этом коде оч странные напряжения на выходе порта (меряю между землей и ножкой порта)

Код
int ow_reset()
{
  uint8_t r=0;
  PORTA &= ~(1<<4); // +4.95В
  DDRA |= (1<<4);        // DQ = 0;
r = (PORTA & (1<<4));    //+4.28В        как такое может быть???
  _delay_us(480);
  DDRA &= ~(1<<4);        // DQ pull up
  _delay_us(70);
  r = (PORTA & (1<<4));    // Capture the presence pulse
  _delay_us(410);        
  return r;                        // +4.95В
}

как такое возможно?


--------------------
If you can't make it good - don't make it look good ;)
Go to the top of the page
 
+Quote Post

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

 


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


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