Миландр

Ключевым подразделением нашей компании является Центр Проектирования интегральных микросхем
Текущее время: 2017-окт-19 08:38

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 8 ] 
Автор Сообщение
 Заголовок сообщения: Интерфейс 1-Wire
СообщениеДобавлено: 2016-апр-12 11:32 
Не в сети

Зарегистрирован: 2016-апр-12 11:16
Сообщения: 3
Есть ли готовые примеры реализации интерфейса 1-Wine (Onw Wire) для микроконтроллеров Миландр?

Конкретно интересует случай с датчиком температуры DS18b20 и МК 1986BE93. Более общие случаи тоже интересны.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Интерфейс 1-Wire
СообщениеДобавлено: 2016-май-06 13:06 
Не в сети

Зарегистрирован: 2016-апр-12 11:16
Сообщения: 3
Переделал код для STM'a: работает. Если кому интересно, пишите - выложу получившийся код.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Интерфейс 1-Wire
СообщениеДобавлено: 2016-май-16 09:29 
Не в сети

Зарегистрирован: 2016-апр-07 15:28
Сообщения: 6
Andry, интересен исходный код. Поделитесь, пожалуйста.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Интерфейс 1-Wire
СообщениеДобавлено: 2016-май-18 11:12 
Не в сети

Зарегистрирован: 2016-апр-12 11:16
Сообщения: 3
Данный код это переделка с примера для STM'a

Открыть onewire.c
onewire.c
Код:

#include "onewire.h"

#define ONEWIRE_DELAY(x)   Delay1(x)

PORT_InitTypeDef PORT_InitStructure1;

volatile uint32_t mult;
uint8_t TM_DELAY_Initialized = 0;


void TM_OneWire_Init(void)
{
   /* Initialize delay if it was not already */
   TM_DELAY_Init();
   
   
   PORT_InitStructure1.PORT_FUNC = PORT_FUNC_PORT;
   PORT_InitStructure1.PORT_GFEN = PORT_GFEN_OFF;
   PORT_InitStructure1.PORT_MODE = PORT_MODE_DIGITAL;
   PORT_InitStructure1.PORT_OE = PORT_OE_IN;
   PORT_InitStructure1.PORT_PD = PORT_PD_DRIVER;
   PORT_InitStructure1.PORT_PD_SHM = PORT_PD_SHM_OFF;
   PORT_InitStructure1.PORT_Pin = PORT_Pin_0;
   PORT_InitStructure1.PORT_PULL_DOWN = PORT_PULL_DOWN_OFF;
   PORT_InitStructure1.PORT_PULL_UP = PORT_PULL_UP_OFF;
   PORT_InitStructure1.PORT_SPEED = PORT_SPEED_MAXFAST;
   PORT_Init(MDR_PORTC, &PORT_InitStructure1);
   
   
   
   
   
   /* Save settings */
}

void TM_DELAY_Init(void) {

   /* Set Systick interrupt every 1ms */
   if (SysTick_Config(SystemCoreClock / 1000)) {
      /* Capture error */
      while (1);
   }
   
   
   //0.01785714285714285714285714285714
      /* Set multiplier for delay under 1us with pooling mode = not so accurate */
      mult = SystemCoreClock *7 / 7000000;

      /* Set multiplier for delay under 1us with pooling mode = not so accurate */
      mult = SystemCoreClock *7 / 3000000;

   
   /* Set initialized flag */
   TM_DELAY_Initialized = 1;
}


void Delay1(uint32_t micros) {

   uint32_t amicros;

   mult = 14;
   
   /* Multiply micro seconds */
   amicros = (micros) * (mult);
   /* While loop */
   while (amicros--);

}



void ONEWIRE_LOW(void)
{
   PORT_ResetBits(MDR_PORTC, PORT_Pin_0);
}
   
void ONEWIRE_HIGH(void)
{
   PORT_SetBits(MDR_PORTC, PORT_Pin_0);
}

void ONEWIRE_INPUT(void)
{
   PORT_InitStructure1.PORT_FUNC = PORT_FUNC_PORT;
   PORT_InitStructure1.PORT_GFEN = PORT_GFEN_OFF;
   PORT_InitStructure1.PORT_MODE = PORT_MODE_DIGITAL;
   PORT_InitStructure1.PORT_OE = PORT_OE_IN;
   PORT_InitStructure1.PORT_PD = PORT_PD_DRIVER;
   PORT_InitStructure1.PORT_PD_SHM = PORT_PD_SHM_OFF;
   PORT_InitStructure1.PORT_Pin = PORT_Pin_0;
   PORT_InitStructure1.PORT_PULL_DOWN = PORT_PULL_DOWN_OFF;
   PORT_InitStructure1.PORT_PULL_UP = PORT_PULL_UP_OFF;
   PORT_InitStructure1.PORT_SPEED = PORT_SPEED_MAXFAST;
   PORT_Init(MDR_PORTC, &PORT_InitStructure1);
}

void ONEWIRE_OUTPUT(void)
{
   PORT_InitStructure1.PORT_FUNC = PORT_FUNC_PORT;
   PORT_InitStructure1.PORT_GFEN = PORT_GFEN_OFF;
   PORT_InitStructure1.PORT_MODE = PORT_MODE_DIGITAL;
   PORT_InitStructure1.PORT_OE = PORT_OE_OUT;
   PORT_InitStructure1.PORT_PD = PORT_PD_DRIVER;
   PORT_InitStructure1.PORT_PD_SHM = PORT_PD_SHM_OFF;
   PORT_InitStructure1.PORT_Pin = PORT_Pin_0;
   PORT_InitStructure1.PORT_PULL_DOWN = PORT_PULL_DOWN_OFF;
   PORT_InitStructure1.PORT_PULL_UP = PORT_PULL_UP_OFF;
   PORT_InitStructure1.PORT_SPEED = PORT_SPEED_MAXFAST;
   PORT_Init(MDR_PORTC, &PORT_InitStructure1);
}








uint8_t TM_OneWire_Reset(void) {
   uint8_t i;
   
   /* Line low, and wait 480us */
   ONEWIRE_LOW();
   ONEWIRE_OUTPUT();
   ONEWIRE_DELAY(480);
   
   /* Release line and wait for 80us */
   ONEWIRE_INPUT();
   ONEWIRE_DELAY(60);
   
   /* Check bit value */
   
   i = PORT_ReadInputDataBit(MDR_PORTC,PORT_Pin_0);
   
   /* Delay for 420 us */
   ONEWIRE_DELAY(420);
   
   /* Return value of presence pulse, 0 = OK, 1 = ERROR */
   return i;
}



uint8_t TM_OneWire_ReadBit(void) {
   uint8_t bit = 0;
   
   /* Line low */
   ONEWIRE_LOW();
   ONEWIRE_OUTPUT();
   ONEWIRE_DELAY(1);
   
   /* Release line */
   ONEWIRE_INPUT();
   ONEWIRE_DELAY(14);
   
   /* Read line value */
   if (PORT_ReadInputDataBit(MDR_PORTC,PORT_Pin_0)) {
      /* Bit is HIGH */
      bit = 1;
   }
   
   /* Wait 45us to complete 60us period */
   ONEWIRE_DELAY(45);
   
   /* Return bit value */
   return bit;
}

uint8_t TM_OneWire_ReadByte(void) {
   uint8_t i = 8, byte = 0;
   while (i--) {
      byte >>= 1;
      byte |= (TM_OneWire_ReadBit() << 7);
   }
   
   return byte;
}

void TM_OneWire_WriteBit(uint8_t bit) {
   /* Set line low */
   ONEWIRE_LOW();
   ONEWIRE_OUTPUT();
   ONEWIRE_DELAY(1);
   
   /* If we want high bit */
   if (bit) {
      ONEWIRE_INPUT();
   }
   
   /* Wait for 59 us and release the line */
   ONEWIRE_DELAY(59);
   ONEWIRE_INPUT();
}

void TM_OneWire_WriteByte( uint8_t byte) {
   uint8_t i = 8;
   /* Write 8 bits */
   while (i--) {
      /* LSB bit is first */
      TM_OneWire_WriteBit( byte & 0x01);
      byte >>= 1;
   }
}



uint8_t TM_OneWire_First(TM_OneWire_t* OneWireStruct) {
   /* Reset search values */
   TM_OneWire_ResetSearch(OneWireStruct);

   /* Start with searching */
   return TM_OneWire_Search(OneWireStruct, ONEWIRE_CMD_SEARCHROM);
}


uint8_t TM_OneWire_Next(TM_OneWire_t* OneWireStruct) {
   /* Leave the search state alone */
   return TM_OneWire_Search(OneWireStruct, ONEWIRE_CMD_SEARCHROM);
}

void TM_OneWire_ResetSearch(TM_OneWire_t* OneWireStruct) {
   /* Reset the search state */
   OneWireStruct->LastDiscrepancy = 0;
   OneWireStruct->LastDeviceFlag = 0;
   OneWireStruct->LastFamilyDiscrepancy = 0;
}

uint8_t TM_OneWire_Search(TM_OneWire_t* OneWireStruct, uint8_t command) {
   uint8_t id_bit_number;
   uint8_t last_zero, rom_byte_number, search_result;
   uint8_t id_bit, cmp_id_bit;
   uint8_t rom_byte_mask, search_direction;

   /* Initialize for search */
   id_bit_number = 1;
   last_zero = 0;
   rom_byte_number = 0;
   rom_byte_mask = 1;
   search_result = 0;

   // if the last call was not the last one
   if (!OneWireStruct->LastDeviceFlag) {
      // 1-Wire reset
      if (TM_OneWire_Reset()) {
         /* Reset the search */
         OneWireStruct->LastDiscrepancy = 0;
         OneWireStruct->LastDeviceFlag = 0;
         OneWireStruct->LastFamilyDiscrepancy = 0;
         return 0;
      }

      // issue the search command
      TM_OneWire_WriteByte(command); 

      // loop to do the search
      do {
         // read a bit and its complement
         id_bit = TM_OneWire_ReadBit();
         cmp_id_bit = TM_OneWire_ReadBit();

         // check for no devices on 1-wire
         if ((id_bit == 1) && (cmp_id_bit == 1)) {
            break;
         } else {
            // all devices coupled have 0 or 1
            if (id_bit != cmp_id_bit) {
               search_direction = id_bit;  // bit write value for search
            } else {
               // if this discrepancy if before the Last Discrepancy
               // on a previous next then pick the same as last time
               if (id_bit_number < OneWireStruct->LastDiscrepancy) {
                  search_direction = ((OneWireStruct->ROM_NO[rom_byte_number] & rom_byte_mask) > 0);
               } else {
                  // if equal to last pick 1, if not then pick 0
                  search_direction = (id_bit_number == OneWireStruct->LastDiscrepancy);
               }
               
               // if 0 was picked then record its position in LastZero
               if (search_direction == 0) {
                  last_zero = id_bit_number;

                  // check for Last discrepancy in family
                  if (last_zero < 9) {
                     OneWireStruct->LastFamilyDiscrepancy = last_zero;
                  }
               }
            }

            // set or clear the bit in the ROM byte rom_byte_number
            // with mask rom_byte_mask
            if (search_direction == 1) {
               OneWireStruct->ROM_NO[rom_byte_number] |= rom_byte_mask;
            } else {
               OneWireStruct->ROM_NO[rom_byte_number] &= ~rom_byte_mask;
            }
            
            // serial number search direction write bit
            TM_OneWire_WriteBit(search_direction);

            // increment the byte counter id_bit_number
            // and shift the mask rom_byte_mask
            id_bit_number++;
            rom_byte_mask <<= 1;

            // if the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask
            if (rom_byte_mask == 0) {
               //docrc8(ROM_NO[rom_byte_number]);  // accumulate the CRC
               rom_byte_number++;
               rom_byte_mask = 1;
            }
         }
      } while (rom_byte_number < 8);  // loop until through all ROM bytes 0-7

      // if the search was successful then
      if (!(id_bit_number < 65)) {
         // search successful so set LastDiscrepancy,LastDeviceFlag,search_result
         OneWireStruct->LastDiscrepancy = last_zero;

         // check for last device
         if (OneWireStruct->LastDiscrepancy == 0) {
            OneWireStruct->LastDeviceFlag = 1;
         }

         search_result = 1;
      }
   }

   // if no device found then reset counters so next 'search' will be like a first
   if (!search_result || !OneWireStruct->ROM_NO[0]) {
      OneWireStruct->LastDiscrepancy = 0;
      OneWireStruct->LastDeviceFlag = 0;
      OneWireStruct->LastFamilyDiscrepancy = 0;
      search_result = 0;
   }

   return search_result;
}


void TM_OneWire_SelectWithPointer(TM_OneWire_t* OneWireStruct, uint8_t *ROM) {
   uint8_t i;
   TM_OneWire_WriteByte(ONEWIRE_CMD_MATCHROM);
   
   for (i = 0; i < 8; i++) {
      TM_OneWire_WriteByte(*(ROM + i));
   }   
}

void TM_OneWire_GetFullROM(TM_OneWire_t* OneWireStruct, uint8_t *firstIndex) {
   uint8_t i;
   for (i = 0; i < 8; i++) {
      *(firstIndex + i) = OneWireStruct->ROM_NO[i];
   }
}


uint8_t TM_OneWire_CRC8(uint8_t *addr, uint8_t len) {
   uint8_t crc = 0, inbyte, i, mix;
   
   while (len--) {
      inbyte = *addr++;
      for (i = 8; i; i--) {
         mix = (crc ^ inbyte) & 0x01;
         crc >>= 1;
         if (mix) {
            crc ^= 0x8C;
         }
         inbyte >>= 1;
      }
   }
   
   /* Return calculated CRC */
   return crc;
}


Закрыть


Открыть onewire.h
onewire.h
Код:
#ifndef ONEWIRE_H
#define ONEWIRE_H

#include "MDR32F9Qx_port.h"
#include "MDR32Fx.h"

/* OneWire commands */
#define ONEWIRE_CMD_RSCRATCHPAD         0xBE
#define ONEWIRE_CMD_WSCRATCHPAD         0x4E
#define ONEWIRE_CMD_CPYSCRATCHPAD      0x48
#define ONEWIRE_CMD_RECEEPROM         0xB8
#define ONEWIRE_CMD_RPWRSUPPLY         0xB4
#define ONEWIRE_CMD_SEARCHROM         0xF0
#define ONEWIRE_CMD_READROM            0x33
#define ONEWIRE_CMD_MATCHROM         0x55
#define ONEWIRE_CMD_SKIPROM            0xCC


typedef struct {
   uint8_t LastDiscrepancy;
   uint8_t LastFamilyDiscrepancy;
   uint8_t LastDeviceFlag;
   uint8_t ROM_NO[8];
} TM_OneWire_t;



void TM_OneWire_Init(void);
void TM_DELAY_Init(void);   
void Delay1(uint32_t micros);
void ONEWIRE_LOW(void);
void ONEWIRE_HIGH(void);
void ONEWIRE_INPUT(void);
void ONEWIRE_OUTPUT(void);
uint8_t TM_OneWire_Reset(void);
uint8_t TM_OneWire_ReadBit(void);
uint8_t TM_OneWire_ReadByte(void);
void TM_OneWire_WriteBit(uint8_t bit);
void TM_OneWire_WriteByte( uint8_t byte);
uint8_t TM_OneWire_First(TM_OneWire_t* OneWireStruct);
uint8_t TM_OneWire_Next(TM_OneWire_t* OneWireStruct);
void TM_OneWire_ResetSearch(TM_OneWire_t* OneWireStruct);
uint8_t TM_OneWire_Search(TM_OneWire_t* OneWireStruct, uint8_t command);

void TM_OneWire_SelectWithPointer(TM_OneWire_t* OneWireStruct, uint8_t *ROM);
void TM_OneWire_GetFullROM(TM_OneWire_t* OneWireStruct, uint8_t *firstIndex);
uint8_t TM_OneWire_CRC8(uint8_t *addr, uint8_t len);

#endif //ONEWIRE_H
Закрыть


В мейне

Открыть
Код:
uint8_t g_device_onewire[8] = {0};
uint8_t g_dev_one_wire = 0;
uint16_t Temperature = 0;

вызвать TM_OneWire_Init() для инициализации порта

void readTemperature()
{

   Delay1(100);

   g_dev_one_wire = TM_OneWire_First(&OneWireStruct);

   if(g_dev_one_wire == 1)
   {
      TM_OneWire_GetFullROM(&OneWireStruct, g_device_onewire);

      TM_DS18B20_SetResolution(&OneWireStruct, g_device_onewire, 0.0625);

      TM_DS18B20_Start(&OneWireStruct, g_device_onewire);
      
      while (!TM_DS18B20_AllDone(&OneWireStruct));

      TM_DS18B20_Read(&OneWireStruct, g_device_onewire, &Temperature);

   }
}




Преобразовать температуру можно так
Код:
float MyClass::convert_Temperature_u16_to_float(quint16 temperature)
{
    int digit, minus = 0;
    float decimal;

    /// Check if temperature is negative

    if (temperature & 0x8000)
    {
    /// Two's complement, temperature is negative
        temperature = ~temperature + 1;
        minus = 1;
    }

    // Store temperature integer digits and decimal digits
    digit = temperature >> 4;
    digit |= ((temperature >> 8) & 0x7) << 4;

    //Store decimal digits
    decimal = temperature & 0x0F;
    decimal *= (float)0.0625;

    // Check for negative part
    decimal = digit + decimal;
    if (minus)
    {
        decimal = 0 - decimal;
    }

    // Set to pointer

    return decimal;
}
Закрыть


Как видно код конкретизирован для ножки PC0, довольно деревянный и с нелогичными операциями, но переделывать нет времени, тем более что работает и так =)

Надо вызвать TM_OneWire_Init(), а потом читать температуру функцией readTemperature()

mult = 14; - множитель для деления частоты для задержки.

Если будут вопросы, пишите!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Интерфейс 1-Wire
СообщениеДобавлено: 2016-июн-30 15:25 
Не в сети

Зарегистрирован: 2016-июн-27 12:53
Сообщения: 7
Если у процессора есть ещё работа, кроме ожидания в delay, то вот тут я выкладывал исходники для работы с несколькими DS18B20 используя прерывание по Compare и ногодрыг. Работают в нескольких проектах на разных типах процессоров (STM32 и MSP430). Я использовал от 2-х до 8 DS18B20. Проблем никаких.
http://electronix.ru/forum/index.php?sh ... try1089884
Я думаю, вполне переделывается для 1986BE93.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Интерфейс 1-Wire
СообщениеДобавлено: 2016-июл-21 07:51 
Не в сети

Зарегистрирован: 2016-фев-26 09:54
Сообщения: 22
Вот мои 5 копеек: Неблокирующая процедура в виде автомата состояний (конечного автомата) для опроса одного датчика на линии. Используется прерывание по таймеру. Номер таймера и ножку можно настраивать через #define.
Для работы с несколькими датчиками на 1 линии есть блокирующая(на тупых задержках) процедура поиска адресов, которую можно запустить 1 раз при инициализации, а в автомат нужно будет вставить выбор микросхемы по адресу вместо SkipRom.
Так-же там есть (используются) макросы Аскольда Волкова для работы с пинами, с добавленной поддержкой 1986ВЕ9х.
В main перед вечным циклом пишем OWInit(); а в цикле OW_Thread(void); .
Тайминг каждого бита отрабатывается через прерывание по таймеру, а вот между битами пауза может плавать в зависимости от частоты вызова OW_Thread в главном цикле. Но протокол это допускает.


Вложения:
DS18B20.ZIP [9.2 КБ]
Скачиваний: 111
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Интерфейс 1-Wire
СообщениеДобавлено: 2016-окт-24 12:44 
Не в сети

Зарегистрирован: 2016-окт-24 12:30
Сообщения: 3
Вопрос


Последний раз редактировалось Loader 2016-окт-24 12:46, всего редактировалось 1 раз.

Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Интерфейс 1-Wire
СообщениеДобавлено: 2016-окт-24 12:45 
Не в сети

Зарегистрирован: 2016-окт-24 12:30
Сообщения: 3
MWaso писал(а):
Вот мои 5 копеек: Неблокирующая процедура в виде автомата состояний (конечного автомата) для опроса одного датчика на линии. Используется прерывание по таймеру. Номер таймера и ножку можно настраивать через #define.
Для работы с несколькими датчиками на 1 линии есть блокирующая(на тупых задержках) процедура поиска адресов, которую можно запустить 1 раз при инициализации, а в автомат нужно будет вставить выбор микросхемы по адресу вместо SkipRom.
Так-же там есть (используются) макросы Аскольда Волкова для работы с пинами, с добавленной поддержкой 1986ВЕ9х.
В main перед вечным циклом пишем OWInit(); а в цикле OW_Thread(void); .
Тайминг каждого бита отрабатывается через прерывание по таймеру, а вот между битами пауза может плавать в зависимости от частоты вызова OW_Thread в главном цикле. Но протокол это допускает.



MWaso, добрый день!
А можно уточнить по коду:
Там есть процедура OW_STANDBY, но она отсутствует в машине состояний и мне пока не ясно, что она делает. Можете пояснить?
А так же процедура Delayus. Это просто задержка на микросекунду? Вы её делаете на другом таймере или как? Она тоже не расписана.
Я только начинаю работать с этим датчиком температуры, но сделать нужно срочно, поэтому попытался найти готовый код.
Когда начал разбираться - появился вопрос..
С уважением, Олег.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 8 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB