USART - ATMega8 - DS18B20

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Закрыто
Открыл глаза
Сообщения: 52
Зарегистрирован: Чт июл 03, 2008 12:34:48
Откуда: Волгоград

Сообщение Shutilla »

И еще раз здравствуйте, уважаемые коты.
Так сказать, в продолжении вот этой темы.
Есть МК, подключенный к COM-порту. Есть кучка датчиков DS18B20, подключенных к МК. По запросу от компьютера надо выдать значение температуры того или иного датчика.
Протокол использует такой формат пакетов: известный всем заголовок (4 байта) - длина пакета (1 байт) - данные. Пока МК не ответит на предыдущий пакет, следующий не посылается. Предусмотрен таймаут ожидания, во избежание "затыков" из-за потерь пакетов.
Пишу в cvavr. Основной цикл:

Код: Выделить всё

while (1)
{
  // Старт измерения!
  #asm("cli")
  measure_start_all();
  #asm("sei")
  // Ждем, пока померяется (~800мс)
  i = 0;
  while (i++ < 800)
  {
    delay_ms(1);
    if (is_recive)
      do_cmd();
  }
  // читаем, чего намеряли
  for (i = 0; i < thermo_count; i++)
  {
    #asm("cli")
    thermo_values[i] = read_temperature(i);
    #asm("sei")
  }
}
Флаг is_recive выставляется по корректному принятию пакета, в функции do_cmd собирается и высылается ответ. Значения измеряются постоянно, заносятся в буфер thermo_values, откуда их по надобности читает функция do_cmd. В прерывании USART по принятию байта я переписываю его в буфер и перезапускаю таймер таймаута. По прерыванию таймера таймаута (100 мс) происходит проверка целостности пакета: в случае успеха выставляется флаг is_recive, в случае неудачи высылается уведомление о "битости" пакета.
Для общения с датчиками использую библиотеку 1-wire из cvavr.

Код: Выделить всё

// Служебная процедура инициализации линии 1wire
unsigned char wire_init(void)
{
  if (w1_init() == 0)
  {
    return 0;
  }
  w1_write(0xCC);
  return 1;
}

// Служебная процедура выбора канала мультиплексора
unsigned char set_thermo(unsigned char index)
{
  unsigned char i = 8;
  unsigned char state = index;
  while (i > 0)
  {
    IN_DATA_PIN = (state >> (i - 1)) & 1;
    IN_CLOCK_PIN = 0;
    delay_us(5);
    IN_CLOCK_PIN = 1;
    delay_us(5);
    --i;
  }
  IN_STROBE_PIN = 1;
  delay_us(10);
  IN_STROBE_PIN = 0;
  IN_DATA_PIN = 0;
  IN_CLOCK_PIN = 0;
  delay_ms(1);
  return wire_init();
}

void measure_start_all(void)
{
  unsigned char i;
  for (i = 0; i < thermo_count; i++)
  {
    if (set_thermo(i) == 0)
    {
       set_bit_longint(&thermo_states,i,0); // термометр не отвечает
       continue;
    }
    set_bit_longint(&thermo_states,i,1); // термометр в порядке
    w1_write(0x44); // Команда начала измерения
    w1_init();
  }
}

int read_temperature(unsigned char index)
{
  unsigned char i;
  unsigned char *p;
  if (set_thermo(index) == 0)
  {
    set_bit_longint(&thermo_states,index,0);
    return thermo_values[index];
  }
  i = 0;
  p = (char*)&__ds18b20_mem;
  w1_write(0xBE);
  do
    *(p++) = w1_read();
  while (++i < 9);
  w1_init();
  if (!w1_dow_crc8(&__ds18b20_mem,9) == 0)
  {
    set_bit_longint(&thermo_states,index,0);
    return thermo_values[index];
  }
  return (*((int*)&__ds18b20_mem.temp_lsb));
}
Но работает сей монстр не вполне стабильно - термометры могут хаотически "отваливаться" или показывать "магические" значения, типа 85 градусов. Как выяснилось в предыдущей теме, проблема все же не в железе, а в коде. Возможно, дело в слишком долгом выполнении кода между cli и sei, когда теряется какой-нибудь байт пакета, или в каком-нибудь месте работы с шиной 1-wire - у меня, если честно, уже кончились предположения.

Простите за длинный пост и заранее спасибо за помощь!
Реклама
Открыл глаза
Сообщения: 52
Зарегистрирован: Чт июл 03, 2008 12:34:48
Откуда: Волгоград

Сообщение Shutilla »

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

Всем спасибо, особенно тов. _noise, за то что взял на себя часть модераторских функций. Видимо, они сами не справляются с ними.
Реклама
Закрыто

Вернуться в «Микроконтроллеры и ПЛИС»