Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

DS18B20 + OneWire + PIC18F4550 code query

Status
Not open for further replies.

Giedrius.S

Newbie level 4
Joined
Jun 1, 2016
Messages
6
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
74
Hello all,

In the last three days I was struggling to read temperature data from a single DS18B20 when using non-parasitic OneWire protocol and a PIC18F4550. Finally I had a break-trough (at least I think I have), when I decided to take baby steps and : 1. Read a presence pulse; 2. Read device family code; 3. Attempt to read temperature data. So far points 1 and 2 were accomplished successfully, I was able to read the presence pulse (0) and a family code (0x28). But the last point, I am still struggling bad. I understand that in order to read temperature values, I first need to write a command to convert temperature (0x44), then reset the OneWire, give a 0.75s delay for the conversion to be completed, and then write to the scratchpad 0xBE to read from the register. I've tried combining the codes I found in maxim website and as well some other codes I found all over the web. LCD now displays Temperature: 11, when my room temperature is currently ~27 degrees C. Please can someone check my codes to see whether there is an issue somewhere? Thanks!

DS18B20 header file:
Code:
#define __XTAL_FREQ 8000000

#define Data_pin RB2
#define Data_bus TRISB2
#define Skip_ROM 0xCC                // 0b11001100
#define Convert_temperature 0x44    // 0b01000100
#define Read_scratchpad 0xBE            // 0b10111110
#define Read_deviceFamily 0x33

int OneWire_reset()
{
    Data_bus = 0;        //Set as output
	Data_pin = 0;        //Drive Low
    __delay_us(480);
    Data_bus = 1;        //Release, Set back as input
    __delay_us(70);
   
if (Data_pin == 0)        // Sample bus
    {
        __delay_us(410);
        return 0;        // Device present
    }
    else
    {
        __delay_us(410);
        return 1;        // No device present
    }
}

int OneWire_readByte(void)
{
    int l, result = 0;
    for(l=0;l<8;l++)
    {
        result >>= 1;
        if(OneWire_readBit())
            result |= 0x80;
    }
    return result;
}

int OneWire_readBit(void)
{
    unsigned int Read_state = 0;
    
    Data_bus = 0;        //Set as output
	Data_pin = 0;        //Drive low
    __delay_us(6);
    Data_bus = 1;        //Release, set as input
    __delay_us(9);
    Read_state = Data_pin;
    
    return Read_state;
}

void OneWire_writeBit(unsigned int b)
{
    Data_bus = 0;        //Set as output
   	Data_pin = 0;        //Drive low

    if(b == 1)
    {
        __delay_us(3);
        Data_bus = 1;    //Release, set as input
        __delay_us(62);
    }
    else
    {
        __delay_us(57);
        Data_bus = 1;    //Release, set as input
        __delay_us(7);
    }
}

void OneWire_writeByte(unsigned int data)
{
    int l;
    for(l=0;l<8;l++)
    {
        OneWire_writeBit(data & 0x01);
        data >>= 1;
    }
}

And the main code:
Code:
#define _XTAL_FREQ 8000000

#include <xc.h>
#include <stdio.h>
#include "LCD_4bit_config.h"
#include "DS18B20_config.h"
#include "delay.h"

OneWire_init()
{
	int i;
	char buf1[10];
	char buf2[10];
		
	LCD_setCursor(1,1);
    	LCD_writeString("Presence:");
        
        i = OneWire_reset();
        	
        sprintf(buf1,"%d",i);
        LCD_setCursor(2,1);
        LCD_writeString(buf1);
        
        delay_ms(3000);
        LCD_clr();
        	
        OneWire_reset();
        
        LCD_setCursor(1,1);
        LCD_writeString("Device family:");
        	
        OneWire_writeByte(Read_deviceFamily);
        	
        i = OneWire_readByte();
        	
        sprintf(buf2,"%d",i);
        LCD_setCursor(2,1);
        LCD_writeString(buf2);
        	
        delay_ms(3000);
        LCD_clr();
        	
       	OneWire_reset();
}

void main()
{	
	char temp_lsb,temp_msb,temp;
	
	char buf3[10];
	
	char getBit[10];

	int k;
	 
	OSCCON = 0b11110010;    // Set PIC18F4550 internal oscillator at 8MHz
	
	ADCON1 = 0x0F;            // Set all pins as digital I/O
        CMCON = 0x07;             // Set all comparators as digital I/O
    
	LATD = 0;			    // Clear port D
	TRISD = 0b00000000;		// Set all port D pins as digital outputs
	
	LATB = 0;
	TRISB = 0x00;
	
        LCD_init();				// Initialize LCD
        OneWire_init();
        	    
    while(1)
    {
       		
       	if (!OneWire_reset())
       	{
       	    LCD_setCursor(1,1);
    	    LCD_writeString("Temperature:");
    	    
    	    OneWire_writeByte(Skip_ROM);          
            OneWire_writeByte(Convert_temperature);
		
			OneWire_reset();
			delay_ms(750);
    	    
    	    OneWire_writeByte(Skip_ROM);
    	    OneWire_writeByte(Read_scratchpad);
    	    
    	    for (k=0;k<9;k++)
    	    	{
	    	    	getBit[k] = OneWire_readByte();	
	    	    }
	    	    
	    	temp_msb = getBit[1];
	    	temp_lsb = getBit[0];
	    	    			
	    	temp = (temp_msb << 8) + temp_lsb;
	    	
	    	temp = temp >> 4;
	    	
			sprintf(buf3,"%d",temp);
        	LCD_setCursor(2,1);
        	LCD_writeString(buf3);
        	
        	delay_ms(1000);
    	   	}
   	}
}
 
Last edited:

You can't use PORT registers. This interface require pull-up and open collector logic output. You have to use LAT register to set low level on output and TRIS register to force it to low or to release.
 

Thanks for a reply. I have tried setting the Port_pin to LATB0, but then the presence pulse is 0, family code is 0, and the returned temperature value is as well 0. Am I doing something wrong?
 

Can you please elaborate, because I'm really lost here..
 

Once again, there are 3 possible logic types are used:
1. push-pull
2. open collector/open emitter
3. tri-state
You have to use second one. You will use LAT register to latch zero value, then switching the TRIS register you will be able to change between two pin states:
1. Forced low by low side mosfet
2. Released tri-state pushed hi by pull-up resistor
 

Thanks for the clarification on the registers. But still I have some doubts... a day ago I found a post : https://www.edaboard.com/threads/347686/ , comment #17, in which, as I can see, you are using PORTD.B2 pin for the Data_pin, not LATD...
 
Last edited:

How do you think sensor will pull down data line if it forced hi by hi side mosfet?
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top