Home > electronics > 1-Wire (OneWire) C18 library

1-Wire (OneWire) C18 library

So yesterday I wanted to get some temperature measurements from a DS18S20 thermometer to my PIC prototyping board. This thermometer uses the 1-Wire communication protocol so I searched around to find a 1-Wire library for the C18 compiler I am using. Maybe I am wrong but I couldn’t find any. So I created one, hence this post.

I had a post about the 1-Wire protocol a while back so you can read that if you are not familiar with it. To implement this protocol we need to work with precision timing. Ideally this could be written in asm. However, for convenience reasons I wrote this in C. I don’t really mind the minor performance penalty 🙂

Just to be clear, this is a library for the 1-Wire protocol, not for any of the supported devices. The library contains 3 main functions:

  • 1-Wire Reset
  • 1-Wire Write
  • 1-Wire Read

Using these three operations we can have full communication with any 1-Wire device. Let me demonstrate first and then I will write about how you can use it in your project.

A brief demonstration

To demonstrate this operation, I connected a DS18S20 thermometer and connected the DQ line on my PIC’s Port C Pin 1. The procedure I will follow is:

  • Issue a Reset pulse and observe the Presence of the thermometer
  • Issue the Skip Rom command (0xCC)
  • Issue the Convert T command (0x44)
  • Wait for 1+ second
  • Issue a Reset pulse and observe the Presence of the thermometer
  • Issue the Skip Rom command (0xCC)
  • Issue the Read Scratchpad command (0xBE)
  • And read the next two bytes which represent the temperature

Lets see the C code I loaded on my board

#pragma config OSC = HSPLL
#pragma config WDT = OFF
#pragma config PWRT = ON
#pragma config LVP = OFF
#pragma config PBADEN = OFF
 
#define OW_LAT LATCbits.LATC1
#define OW_PIN PORTCbits.RC1
#define OW_TRIS TRISCbits.TRISC1
 
#include <p18cxxx.h>
#include <p18f4520.h>
#include <delays.h>
#include "ow.h"
 
void main(void) {
    char testdata1,testdata2;
    TRISCbits.TRISC0=0;
    LATCbits.LATC0 = ow_reset();
    Delay100TCYx(30);
    ow_write_byte(0xCC);
    Delay100TCYx(1);
    ow_write_byte(0x44);
    Delay10KTCYx(255);
    Delay10KTCYx(255);
    ow_reset();
    Delay100TCYx(30);
    ow_write_byte(0xCC);
    Delay100TCYx(1);
    ow_write_byte(0xBE);
    Delay100TCYx(1);
    testdata1=ow_read_byte();
    Delay10TCYx(1);
    testdata2=ow_read_byte();
    ow_reset();
    Delay10KTCYx(255);
    ow_write_byte(testdata1);
    ow_write_byte(testdata2);
 
    while(1){}
 
    return;
}

Don’t mind the last couple of commands , they are not needed, I will explain later. Notice the required delays between the issuing of commands. To observe what is going on (and to show you) between the PIC and the thermometer I used this little logic analyzer which I fully recommend. It’s cheap and really useful. Lets see the screenshot

1-Wire library in action

The screenshot shows the second part of the demonstration where we read the temperature from the DS18S20. You can see the that all starts with the Reset pulse and the successful response from the thermometer using the Presence pulse. After while the 0xCC (Skip Rom) and 0xBE (Read Scratchpad) commands are issued. Just after that we issue the Reading phase where the thermometer successfully responds. It responds with 0x3D and 0x00 which if I am right converts to 30.5 degrees Celsius (it a bit high because I was holding the thermometer in my palm).

So we proved that Reset and Write commands work !!! Its time to prove that the Read commands also work !!! and that is where the last two commands come in. I just used them there to spit out the temperature that was read earlier just to check that the function read them correctly. See the screenshot

Writing the temperature back on the DQ line

As you can see the PIC write the 0x3D and 0x00 back so we confirm that reading works!

That’s it 🙂

How you can use it

Go and download the library. I put it on GitHub. Put the ow.h file in your project folder where you other C files are located. Then include the file using

#include "ow.h"

Then you need to define three things:

  • The Latch address
  • The Pin address
  • and the Tris address

See how I defined them in the code above, for the Pin 1 of Port C.

And that’s it. You can use the commands to communicate via 1-Wire

Enjoy and let me know if you need any help.


Related Posts:



Incoming search terms:

  • ds18b20 c18 (18)
Categories: electronics Tags: , ,
  1. David
    July 31st, 2013 at 20:35 | #1

    Hey there! I’m trying to use the ds1820 .h that you have in GitHub and I keep getting back -1. Can you give me a working example? I’m using a 18F4580 in a PICDem 2 Plus demoboard, 10MHz osc and ICD 3 with MPLAB 8 (with C18). I’ve connected VCC and GND to the ds sensor, and connected the middle pin to RC1. There is also a 4.7k resistor from VCC to the middle pin.

    I’m using this in the config:
    #pragma config OSC=HSPLL
    #pragma config WDT=OFF
    #pragma config LVP=OFF

    I’m including this:
    #include
    #include
    #include
    #include “ds18s20.h”

    And I’m configuring the pins in the ow.h:
    #define OW_LAT LATCbits.LATC1
    #define OW_PIN PORTCbits.RC1
    #define OW_TRIS TRISCbits.TRISC1

  2. psychoul
    August 6th, 2013 at 09:27 | #2

    Hi David,
    If I remember correctly, the ow.h library works with 10MHz x 4 PLL = 40MHz. Actually the delay functions are based on instruction cycle which should be 0.1usec. To to start with make sure this is your setup.

  3. David
    August 6th, 2013 at 15:02 | #3

    Hey there, I believe that OSC=HSPLL with a 10MHz osc should do the trick, even though I haven’t confirmed it. Anyway, I’ve noticed that when I try to pull down the pin, the DQ pin voltage drops from 5V to about 4V, but not any lower, which means that the temperature sensor never sees a low state bus. Any tip?

  4. Pesho
    July 21st, 2015 at 15:41 | #4

    Hi, there I really like your code and would like to ask about implementation of several sensors instead of 1.

  5. psychoul
    July 31st, 2015 at 10:05 | #5

    @Pesho
    Hi Pesho. In order to have more than one sensors you have to enable addressing. To do that you need to replace the SKIP ROM command in the code above (0xCC) with MATCH ROM command (0x55). After issuing that command you need to include the 64-bit address of the device you want to access. If you don’t know the address of the device, you can issue the READ ROM (0x33) command and the device will respond with its address. In order for this to work, itf has to be the only device connected on the bus. Alternatively you can use the SEARCH ROM (0xF0) command for multiple devices.

  6. Jim
    January 28th, 2017 at 00:55 | #6

    I’m working through your code and using it as a base for an 18B20 implementation. I’m a little puzzled by the time delays at the highest level of the code, between calls to the onewire driver. For example, you have this in the ‘main’ procedure:
    LATCbits.LATC0 = ow_reset();
    Delay100TCYx(30);
    ow_write_byte(0xCC);

    You issue the reset command, then you delay 300 usec, then issue the SkipROM command. I can’t see anything in the 18S20 or 10B20 datasheets, or in Maxim AN126, that calls for the 300usec delay between reset and SkipRom. Did you find this to be necessary? Can you point me to some spec that perhaps I’m overlooking about the timing? I did notice in looking at the code for Reset, that you don’t wait in the reset procedure to finish out the second half of the reset, but instead you exit as soon as the presence indication has been read, and I’m think that this is what the 300 usec delay in main is about – is that right? But then I also see ‘Delay100TCYx(1);’, a 10usec delay, between each step in main. Did you find these to be necessary?

    From everything I can see, it’s ok to execute reads and writes without any delays, except for the actual conversion delay and, if playing with writing the NV rom, a delay for that.

    Thanks for your code – it’s clear and easy to follow, and that’s nice.
    Best,
    Jim

  1. No trackbacks yet.