Page 1 of 1

one-wire bus driver

Posted: Thu Feb 12, 2015 12:51 am
by dash
A long time ago I wrote a 1-wire bus driver and now decided to share :)
my driver tested on STM32F107, but I think it is platform-independent,
since it uses the UART driver (imho finest bus timing).
the driver is configurable by next #define's

Code: Select all

#define HAL_USE_ONEWIRE        TRUE   // enable driver code

#define ONEWIRE_USE_OW1        TRUE     // 1wire bus #1
#define ONEWIRE_USE_OW2        FALSE    // 1wire bus #2
#define ONEWIRE_USE_SEARCH     FALSE    // compile 1wire search algorithm
#define ONEWIRE_USE_READROM    FALSE    // compile owReadRom
#define ONEWIRE_USE_CRC8       TRUE     // compile owCrc8
#define ONEWIRE_USE_SELECT     FALSE    // compile selective device support
#define ONEWIRE_USE_OVERDRIVE  FALSE    // compile OverDrive speed support


simple example - read TM on PB10 (there must be external pull-up)

Code: Select all

int main(void) {

  halInit();
  chSysInit();
  owInit();

// setup onewire bus
// set half-duplex mode & open-drain output
  palSetPadMode( GPIOB, 10, PAL_MODE_STM32_ALTERNATE_OPENDRAIN );
  OWD1.cfg.cr3 = USART_CR3_HDSEL;
  owStart( &OWD1, &UARTD3 );
   
  while (TRUE)
  {
    uint8_t rxbuf[8];

    if( RDY_OK == owReadRom( &OWD1, rxbuf ) )   // READ_ROM command
    {
      chprintf( syscon, "rx %02X %02X %02X %02X %02X %02X %02X %02X ",
        rxbuf[0], rxbuf[1], rxbuf[2], rxbuf[3], rxbuf[4], rxbuf[5], rxbuf[6], rxbuf[7] );

      if( 0 == owCrc8( rxbuf, sizeof(rxbuf) ) )    chprintf( syscon, "[crc ok]" );
      chprintf( syscon, "\r\n" );
    }
      
    chThdSleepMilliseconds(100);
  }
}


more complex example - read temperature sensor

Code: Select all

(init skipped)

  while(TRUE)
  {
    if( RDY_OK == owCommand( &OWD1, 0x44, NULL, 0 ) )
    {
      chThdSleepMilliseconds( 750 );
      if( RDY_OK == owCommand( &OWD1, 0xBE, rxbuf, -sizeof(rxbuf) ) )   // negative size - we will read bus
      {
        if( 0 == owCrc8( rxbuf, sizeof(rxbuf) ) )
        {
          int tempr = *((uint16_t*)rxbuf) >> 2;

          sprintf( txt, "T = %d.%d", tempr >> 2, (tempr & 3) * 25 );

(other code skipped)
        }
      }
    }

    chThdSleepSeconds( 2 );
  }


bus scan example

Code: Select all

(init skipped)

  owSearchStart( &OWD1, 0 );
  chprintf( (BaseSequentialStream *)&SD2, "Start search\r\n" );

  while(TRUE)
  {
    rom_id_t dev;

    result = owSearch( &OWD1, &dev );
    if( RDY_OK == result )
    {
      chprintf( (BaseSequentialStream *)&SD2, "found device =" );
      for( i = 0; i < 8; i++ )      chprintf( (BaseSequentialStream *)&SD2, " %02x", dev.arr[i] );
      chprintf( (BaseSequentialStream *)&SD2, "\r\n" );
               
      if( dev.arr[0] == 0x28 )   // temp sensor?
        test = dev;
    }
    else
      break;
  }

  if( RDY_RESET == result )
    chprintf( (BaseSequentialStream *)&SD2, "bus error\r\n" );
  else
  {
    owSelect( &OWD1, &test, FALSE );
         
    result = owCommand( &OWD1, 0x44, NULL, 0, FALSE );
    chprintf( (BaseSequentialStream *)&SD2, "result = %d\r\n", result );
  }


I will be glad if someone will find it useful :)

Re: one-wire bus driver

Posted: Sun Jul 19, 2015 4:41 pm
by Alexte
Hello Dash.
How to read the data on the same bus if several temperature sensors?

Re: one-wire bus driver

Posted: Mon Oct 12, 2015 12:33 am
by dash
Alexte wrote:Hello Dash.
How to read the data on the same bus if several temperature sensors?


If you know the serial numbers of your sensors, you can use owSelect to select the desired sensor. All subsequent commands will be addressed to the selected sensor.
To return to the "broadcast mode" select "device" with serial number 0.
If you do not know the serials of your sensors you need to scan the bus as in the last example.