We examined the 3-wire SPI protocol and the 2-wire I2C protocol. The next protocol we will look at is the One Wire (OW) protocol. The One Wire protocol developed by Maxim is a protocol which uses only one wire for communication with devices on the bus. In this post we will look at the One Wire Protocol and use it to read and write to a temperature sensor.

The One Wire Protocol

The One Wire or 1-wire protocol is a propriety protocol that is controlled by Maxim Integrated. The protocol is a master slave protocol where one master device can communicate with more than one slave device. Unlike SPI, I2C and UART however, the PIC32 lacks an onboard One Wire module and for that reason we will use a software implementation of the protocol.

The One Wire protocol uses an open-drain master/slave configuration with a resistor used with a pull-up resistor. The value of this resistor is 4.7k. Though I have seen implementations where persons used both 1k and 10k values for the pull up resistors, 4.7k works well on both a 3.3 volt supply and a 5 volt supply.

What makes the protocol nice is that there is no need to handle clocking as the parts using one wire has an internal oscillator that takes care of all the clocking required.

The one wire protocol has provisions to allow for multiples slaves to be connected as each slave device is given a unique 64-bit serial number and code can be written to address each device individually, in our example however we do not add the complexity of multiple devices in an effort to keep the example as simple as possible.

The One Wire protocol is a half duplex protocol, allowing communication between master and slave device in only one direction at a time.

For one wire communication to take place the master sends a reset signal that gets the bus in sync, if there are multiple slaves on the bus, the master determines which device to read and communicates with the slave on the bus.

In this example we will use the One wire protocol to read the temperature of a DS1820 temperature sensor, which can also be replaced by a DS18S20 device without any adjustment to the code.

 


Connections

The DS1820 temperature sensor is connected to PINC0 of the device. The PIC32 is also connected to the CP2014 USB-UART bridge.


C Program

/*
 * File: Main.c
 * Author: Armstrong Subero
 * Processor: PIC32MX270F256D w/Ext OSC @ 4MHz, PLL to 48 MHz, 3.3v
 * Program: 22_One Wire
 * Compiler: XC32 (v1.44, MPLAX X v5.05)
 * Program Version: 1.0
 *                             
 * Program Description: This Program Allows PIC32MX270F256D to use the One Wire
 *                      protocol to read a DS1820 microcontroller. 
 * 
 * Hardware Description: A DS1820 Temperature sensor is connected to PIN RC0
 * 
 * Change History:
 *
 * Author             Rev     Date          Description
 * Armstrong Subero   1.0     26/09/2018    Initial Release.
 * 
 *                      
 * Created September 26th, 2018, 9:57 PM
 */

/*******************************************************************************
 Includes and defines
*******************************************************************************/
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include "PIC32MX270_STD.h"
#include "Delay.h"
#include "uart1.h"
#include "onewire.h"

// program variables
char getDat[10];
char TEMP_LSB;
char TEMP_MSB;
int  loop_var;
char far_temp;
char cel_temp;


/*******************************************************************************
* Function Name: void initMain (void)
*
* Specification: initializes main
*
*******************************************************************************/
void initMain(void)
{  
    uc_init();              // initialize microcontroller
    TRISBbits.TRISB14 = 0;  // set PINB1 as output
    
    // unlock PPS
    systemReg_Unlock();
    CFGCONbits.IOLOCK = 0;

    RPC5Rbits.RPC5R = 0x0001;   //RC5->UART1 TX

    // lock PPS
    CFGCONbits.IOLOCK = 1; 
    systemReg_Lock();
    
    UART1_Initialize(); 
}


/*******************************************************************************
* Function Name: void main (void)
*
* Specification: main function
*
*******************************************************************************/
void main(void) {
    
    initMain();   // initializes main function
    OW_Init();    // initialize OW

    int present;  //var to check for device presence
    
    
    while(1)
    {
        // configure printf to use UART1
        __XC_UART = 1; 
        
        present = OW_Reset();  // see if device is present
        
        if (present == 0)
        {
            printf("Device is Present");
        }
        
        else
        {
            printf("Device not present");
            return;
        }
        
        OW_Reset();                     // reset device
        OW_WriteByte(SKIP_ROM);         //Skip ROM
        OW_WriteByte(START_CONVERSION); // Start Conversion
        delay_ms(5);
        
        OW_Reset();                    // reset device
        OW_WriteByte(SKIP_ROM);        // Skip ROM
        OW_WriteByte(READ_SCRATCHPAD); // Read Scratch Pad
        
        // read scratchpad data
        for(loop_var=0;loop_var<9;loop_var++)
        {
            getDat[loop_var] = OW_ReadByte();
        }
        
        // print scratchpad data
        printf("\n Scratchpad DATA = %X%X%X%X%X\n",getDat[8],getDat[7],getDat[6],
                getDat[5],getDat[4],getDat[3],getDat[2],getDat[1],getDat[0]);
        
        
        // get temperature data
        TEMP_MSB = getDat[1]; // Sign byte + lsbit
        TEMP_LSB = getDat[0]; // Temp data plus lsb
        
        
        if (TEMP_MSB <= 0x80)
        {
            TEMP_LSB = (TEMP_LSB/2); // shift to get whole degree
        } 
        
        TEMP_MSB = TEMP_MSB & 0x80;   // mask all but the sign bit
        
        if (TEMP_MSB >= 0x80)
        {
            TEMP_LSB = (~TEMP_LSB)+1;  // two's complement
        } 
        
       if (TEMP_MSB >= 0x80) 
       {
           TEMP_LSB = (TEMP_LSB/2);    // shift to get whole degree
       }

       if (TEMP_MSB >= 0x80) 
       {
           TEMP_LSB = ((-1)*TEMP_LSB);  // add sign bit
       } 
       
       // print temp in Celsius
       printf( "\nTempC= %d degrees C\n", (int)TEMP_LSB ); 
       
       // convert to Fahrenheit
       cel_temp = TEMP_LSB;         
       far_temp = (((int)cel_temp)* 9)/5 + 32;
       
       // print temp in Farenheit
       printf( "\nTempF= %d degrees F\n", (int)far_temp ); // print temp. F
       
       delay_ms(1000);
 } 
   
}


In this program we read the DS1820 scratchpad value and send it via UART. We also read the temperature data and convert it into Celcius and Farenheit values which are then sent via UART.


Link to Project

You can download the entire project here!

One Wire Project

Leave a Reply

Your email address will not be published. Required fields are marked *