Maker Pro
Maker Pro

µC - Temperature Sensor DS18B20

Sadlercomfort

Ash
Feb 9, 2013
424
Joined
Feb 9, 2013
Messages
424
Hi all,

I'm really stuck trying to get my code to work and read temperature from the DS18B20.

After I've parsed the temperature reading I seem to get 0b01111111 in whole degress C.

I used this website to help me: https://www.maximintegrated.com/en/app-notes/index.mvp/id/2420



Code:
#include <htc.h>
#include <pic.h>
#include "LCD 4-BIT.h"
#define _XTAL_FREQ 4000000
__CONFIG(FOSC_XT & WDTE_OFF & PWRTE_OFF & CP_OFF & BOREN_OFF );

#define    DQ    PORTCbits.RC0

unsigned char presence;
char temp_lsb,temp_msb,temp_c,temp_sign;

unsigned char ow_reset(void)
{
    TRISC0=1;
    DQ = 0;             //pull DQ line low
    TRISC0=0;
    __delay_us(480);     // leave it low for 480us
    TRISC0=1;            //Release to return high
    DQ = 1;             // allow line to return high
    __delay_us(60);     // wait for presence
    presence = DQ;         // get presence signal
    __delay_us(430);     // wait for end of timeslot
    return(presence);     // presence signal returned
}                         // 0=presence, 1 = no part


unsigned char read_bit(void)
{
    DQ = 0;             // pull DQ low to start timeslot
    TRISC0=0;            //Lower the port
    TRISC0=1;            //Release to return high
    DQ = 1;             // then return high
    __delay_us(15);     // delay 15us from start of timeslot
    return(DQ);            // return value of DQ line
}

void write_bit(char bitval)
{
    DQ = 0;                // pull DQ low to start timeslot
    TRISC0=0;
    if(bitval==1) DQ =1;// return DQ high if write 1
    __delay_us(104);     // hold value for remainder of timeslot
    TRISC0=1;            //Release to return high
    DQ = 1;
}                        // Delay provides 104us

unsigned char read_byte(void)
{
    unsigned char i;
    unsigned char value = 0;
    for (i=0;i<8;i++)
    {
    if(read_bit()) value|=0x01<<i;    // reads byte in, one byte at a time and then
    // shifts it left
    __delay_us(120);                 // wait for rest of timeslot
    }
    return(value);
}

void write_byte(char val)
{
    unsigned char i;
    unsigned char temp;
    for (i=0; i<8; i++) // writes byte, one bit at a time
    {
    temp = val>>i; // shifts val right 'i' spaces
    temp &= 0x01; // copy that bit to temp
    write_bit(temp); // write bit in temp into
    }
    __delay_us(104);
}


void Convert_Temp(void)
{
    while(!DQ)
    {
    read_bit();
    }
}

void Read_Temperature(void)
{
    char get[10];
    int k;
//    char temp_f,temp_c;
    ow_reset();
    write_byte(0xCC); //Skip ROM
    write_byte(0x44); // Start Conversion
    __delay_ms(200);
    ow_reset();
    write_byte(0xCC); // Skip ROM
    write_byte(0xBE); // Read Scratch Pad
    for (k=0;k<9;k++){get[k]=read_byte();}
//printf("\n ScratchPAD DATA = %X%X%X%X%X\n",get[8],get[7],get[6],get[5],get[4],get[3],get[2],get[1],get[0]);
    temp_msb = get[1]; // Sign byte + lsbit
    temp_sign= get[1];
    temp_lsb = get[0]; // Temp data plus lsb
    temp_lsb = temp_lsb>>4;
    temp_msb = temp_msb<<5;
    temp_msb = temp_msb>>1;
    temp_sign=temp_sign>>3;
    temp_sign=temp_sign<<3;
    temp_c = temp_lsb|temp_msb;
/*    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;} // twos 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
//printf( "\nTempC= %d degrees C\n", (int)temp_lsb ); // print temp. C
    temp_c = temp_lsb; // ready for conversion to Fahrenheit
    temp_f = (((int)temp_c)* 9)/5 + 32;
//printf( "\nTempF= %d degrees F\n", (int)temp_f ); // print temp. F

*/
}

void Read_ScratchPad(void)
{
    int j;
    char pad[10];
//printf("\nReading ScratchPad Data\n");
    write_byte(0xBE);
    for (j=0;j<9;j++){pad[j]=read_byte();}
//printf("\n ScratchPAD DATA = %X%X%X%X%X%X\n",pad[8],pad[7],pad[6],pad[5],pad[4],pad[3],pad[2],pad[1],pad[0]);
}

void Read_ROMCode(void)
{
    int n;
    char dat[9];
//printf("\nReading ROM Code\n");
    ow_reset();
    write_byte(0x33);
    for (n=0;n<8;n++){dat[n]=read_byte();}
//printf("\n ROM Code = %X%X%X%X\n",dat[7],dat[6],dat[5],dat[4],dat[3],dat[2],dat[1],dat[0]);
}


void main()
{

    TRISB = 0x00;
    PORTB = 0x00;
    TRISC0 = 0;
    __delay_ms(1000);
    LCD_init();


    while(1){
     ow_reset();            //Reset Device
    write_byte(0xCC);    //Skip ROM Command
    write_byte(0x4E);    //Write Scratchpad command
    write_byte(0xFF);    //Set TH alarm +125
    write_byte(0x7F);    //Set TL alarm value -55
    write_byte(0x1F);    //Set config to 9-bit resolution

    ow_reset();            //Reset Device
    write_byte(0xCC);    //Skip ROM Command
    Read_ScratchPad();    //Read Scratchpad Command

    ow_reset();            //Reset Device
    write_byte(0xCC);    //Skip ROM Command
    write_byte(0x48);    //Copy Scratchpad command */
    __delay_ms(10);

    Read_Temperature(); //Read Temperature


    LCD_cmd(LCD_LINE1);
    LCD_string("Temp=");
    LCD_data(temp_c);
    }
   
}
 

DatLe

May 31, 2016
15
Joined
May 31, 2016
Messages
15
Hi Sadlercomfort,

I send to you current source code I using in my projects.
Hope its helpful for you.


Here is library:
DS18B20.h

Code:
/**
  ******************************************************************************
  * @file   :ds18b20
  * @author :DatLe
  * @version:v1_00
  * @date   :   
  * @brief  :Header file for ds18b20.c module.
  ******************************************************************************
  ****************************************************************************** 
  */
 
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __DS18B20_H
#define __DS18B20_H

#ifdef __cplusplus
extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
   #include "stm32f4xx.h"
   #include "common.h"
   #include "onewire.h"

/**
@code 
@endcode
*/
/* Every onewire chip has different ROM code, but all the same chips has same family code */
/* in case of DS18B20 this is 0x28 and this is first byte of ROM address */
#define DS18B20_FAMILY_CODE                    0x28
#define DS18B20_CMD_ALARMSEARCH              0xEC

/* DS18B20 read temperature command */
#define DS18B20_CMD_CONVERTTEMP              0x44     /* Convert temperature */
#define DS18B20_DECIMAL_STEPS_12BIT        0.0625
#define DS18B20_DECIMAL_STEPS_11BIT        0.125
#define DS18B20_DECIMAL_STEPS_10BIT        0.25
#define DS18B20_DECIMAL_STEPS_9BIT        0.5

/* Bits locations for resolution */
#define DS18B20_RESOLUTION_R1                6
#define DS18B20_RESOLUTION_R0                5

/* CRC enabled */
#ifdef DS18B20_USE_CRC   
#define DS18B20_DATA_LEN                      9
#else
#define DS18B20_DATA_LEN                      2
#endif
/**
  * @}
  */
 
/** @defgroup Exported_Types
  * @{
  */
typedef enum {
    DS18B20_RESOLUTION_9BITS = 9,   /*!< DS18B20 9 bits resolution */
    DS18B20_RESOLUTION_10BITS = 10, /*!< DS18B20 10 bits resolution */
    DS18B20_RESOLUTION_11BITS = 11, /*!< DS18B20 11 bits resolution */
    DS18B20_RESOLUTION_12BITS = 12  /*!< DS18B20 12 bits resolution */
} DS18B20_Resolution_TypeDef;
/**
  * @}
  */
 
/** @defgroup Exported_Constants
  * @{
  */
/**
  * @}
  */

/** @defgroup Exported_Macros
  * @{
  */
/**
  * @}
  */

/** @defgroup Exported_Functions
  * @{
  */

/**
* @brief  Starts temperature conversion for specific DS18B20 on specific onewire channel
* @param  *OneWireStruct: Pointer to @ref TM_OneWire_t working structure (OneWire channel)
* @param  *ROM: Pointer to first byte of ROM address for desired DS12B80 device.
*         Entire ROM address is 8-bytes long
* @retval 1 if device is DS18B20 or 0 if not
*/
uint8_t DS18B20_Start(OneWire_IOTypeDef OneWireEnum,uint8_t* ROM);

/**
* @brief  Starts temperature conversion for all DS18B20 devices on specific onewire channel
* @note   This mode will skip ROM addressing
* @param  *OneWireStruct: Pointer to @ref TM_OneWire_t working structure (OneWire channel)
* @retval None
*/
void DS18B20_StartAll(OneWire_IOTypeDef OneWireEnum);

/**
* @brief  Reads temperature from DS18B20
* @param  *OneWireStruct: Pointer to @ref TM_OneWire_t working structure (OneWire channel)
* @param  *ROM: Pointer to first byte of ROM address for desired DS12B80 device.
*         Entire ROM address is 8-bytes long
* @param  *destination: Pointer to float variable to store temperature
* @retval Temperature status:
*            - 0: Device is not DS18B20 or conversion is not done yet or CRC failed
*            - > 0: Temperature is read OK
*/
uint8_t DS18B20_Read(OneWire_IOTypeDef OneWireEnum,uint8_t* ROM, float* destination);

/**
* @brief  Gets resolution for temperature conversion from DS18B20 device
* @param  *OneWireStruct: Pointer to @ref TM_OneWire_t working structure (OneWire channel)
* @param  *ROM: Pointer to first byte of ROM address for desired DS12B80 device.
*         Entire ROM address is 8-bytes long
* @retval Resolution:
*            - 0: Device is not DS18B20
*            - 9 - 12: Resolution of DS18B20
*/
uint8_t DS18B20_GetResolution(OneWire_IOTypeDef OneWireEnum,uint8_t* ROM);

/**
* @brief  Sets resolution for specific DS18B20 device
* @param  *OneWireStruct: Pointer to @ref TM_OneWire_t working structure (OneWire channel)
* @param  *ROM: Pointer to first byte of ROM address for desired DS12B80 device.
*         Entire ROM address is 8-bytes long
* @param  resolution: Resolution for DS18B20 device. This parameter can be a value of @ref TM_DS18B20_Resolution_t enumeration.
* @retval Success status:
*            - 0: Device is not DS18B20
*            - > 0: Resolution set OK
*/
uint8_t DS18B20_SetResolution(OneWire_IOTypeDef OneWireEnum,uint8_t* ROM, DS18B20_Resolution_TypeDef resolution);

/**
* @brief  Checks if device with specific ROM number is DS18B20
* @param  *ROM: Pointer to first byte of ROM address for desired DS12B80 device.
*         Entire ROM address is 8-bytes long
* @retval Device status
*            - 0: Device is not DS18B20
*            - > 0: Device is DS18B20
*/
uint8_t DS18B20_Is(uint8_t* ROM);

/**
* @brief  Sets high alarm temperature to specific DS18B20 sensor
* @param  *OneWireStruct: Pointer to @ref TM_OneWire_t working structure (OneWire channel)
* @param  *ROM: Pointer to first byte of ROM address for desired DS12B80 device.
*         Entire ROM address is 8-bytes long
* @param  temp: integer value for temperature between -55 to 125 degrees
* @retval Success status:
*            - 0: Device is not DS18B20
*            - > 0: High alarm set OK
*/
uint8_t DS18B20_SetAlarmHighTemperature(OneWire_IOTypeDef OneWireEnum,uint8_t* ROM, int8_t temp);

/**
* @brief  Sets low alarm temperature to specific DS18B20 sensor
* @param  *OneWireStruct: Pointer to @ref TM_OneWire_t working structure (OneWire channel)
* @param  *ROM: Pointer to first byte of ROM address for desired DS12B80 device.
*         Entire ROM address is 8-bytes long
* @param  temp: integer value for temperature between -55 to 125 degrees
* @retval Success status:
*            - 0: Device is not DS18B20
*            - > 0: Low alarm set OK
*/
uint8_t DS18B20_SetAlarmLowTemperature(OneWire_IOTypeDef OneWireEnum,uint8_t* ROM, int8_t temp);

/**
* @brief  Disables alarm temperature for specific DS18B20 sensor
* @param  *OneWireStruct: Pointer to @ref TM_OneWire_t working structure (OneWire channel)
* @param  *ROM: Pointer to first byte of ROM address for desired DS12B80 device.
*         Entire ROM address is 8-bytes long
* @retval Success status:
*            - 0: Device is not DS18B20
*            - > 0: Alarm disabled OK
*/
uint8_t DS18B20_DisableAlarmTemperature(OneWire_IOTypeDef OneWireEnum,uint8_t* ROM);

/**
* @brief  Searches for devices with alarm flag set
* @param  *OneWireStruct: Pointer to @ref TM_OneWire_t working structure (OneWire channel)
* @retval Alarm search status
*            - 0: No device found with alarm flag set
*            - > 0: Device is found with alarm flag
* @note   To get all devices on one onewire channel with alarm flag set, you can do this:
@verbatim
while (TM_DS18B20_AlarmSearch(&OneWireStruct)) {
    //Read device ID here
    //Print to user device by device
}
@endverbatim
* @retval 1 if any device has flag, otherwise 0
*/
uint8_t DS18B20_AlarmSearch(OneWire_IOTypeDef OneWireEnum);

/**
* @brief  Checks if all DS18B20 sensors are done with temperature conversion
* @param  *OneWireStruct: Pointer to @ref TM_OneWire_t working structure (OneWire channel)
* @retval Conversion status
*            - 0: Not all devices are done
*            - > 0: All devices are done with conversion
*/
uint8_t DS18B20_AllDone(OneWire_IOTypeDef OneWireEnum);

/**
  * @}
  */

#ifdef __cplusplus
}
#endif


#endif /* ___H */
DS18B20.c
Code:
/**
  ******************************************************************************
  * @file    :ds18b20.c
  * @author  :DatLe
  * @version :
  * @date    :
  * @brief   :
  *          This file should be added to the main application to use the provided
  *          functions that manage Leds, push-buttons, COM ports and low level
  *          HW resources initialization of the different modules available on
  *          STM32 evaluation boards from STMicroelectronics.
  ******************************************************************************
  */
 
/* Includes ------------------------------------------------------------------*/
#include "ds18b20.h"

/** @addtogroup Utilities
  * @{
  */
 

/** @defgroup Abstraction_Layer
  * @{
  */
 
/** @defgroup Public_Variables
  * @{
  */

/** @defgroup Private_TypesDefinitions
  * @{
  */

/**
  * @}
  */


/** @defgroup Private_Defines
  * @{
  */
/**
  * @}
  */


/** @defgroup Private_Macros
  * @{
  */
/**
  * @}
  */


/** @defgroup Private_Variables
  * @{
  */

/**
  * @}
  */


/** @defgroup FunctionPrototypes
  * @{
  */
/**
  * @}
  */

/** @defgroup Private_Functions
  * @{
  */
uint8_t DS18B20_Start(OneWire_IOTypeDef OneWireEnum,uint8_t *ROM)
{
    /* Check if device is DS18B20 */
    if (!DS18B20_Is(ROM)) {
        return 0;
    }
   
    /* Reset line */
    OneWire_Reset(OneWireEnum);
    /* Select ROM number */
    OneWire_SelectWithPointer(OneWireEnum,ROM);
    /* Start temperature conversion */
    OneWire_WriteByte(OneWireEnum,DS18B20_CMD_CONVERTTEMP);
   
    return 1;
}

void DS18B20_StartAll(OneWire_IOTypeDef OneWireEnum) {
    static uint8_t Read;
  /* Reset pulse */
    OneWire_Reset(OneWireEnum);
    /* Skip rom */
    OneWire_WriteByte(OneWireEnum,ONEWIRE_CMD_SKIPROM);

    /* Start conversion on all connected devices */
    OneWire_WriteByte(OneWireEnum,DS18B20_CMD_CONVERTTEMP);
 
  OneWire_WriteByte(OneWireEnum,ONEWIRE_CMD_RPWRSUPPLY);
  Read=OneWire_ReadByte(OneWireEnum);
}

uint8_t DS18B20_Read(OneWire_IOTypeDef OneWireEnum,uint8_t *ROM, float *destination) {
    uint16_t temperature;
    uint8_t resolution;
    int8_t digit, minus = 0;
    float decimal;
    uint8_t i = 0;
    uint8_t data[9];
    uint8_t crc;
   
    /* Check if device is DS18B20 */
    if (!DS18B20_Is(ROM)) {
        return 0;
    }
   
    /* Check if line is released, if it is, then conversion is complete */
    if (!OneWire_ReadBit(OneWireEnum)) {
        /* Conversion is not finished yet */
        return 0;
    }

    /* Reset line */
    OneWire_Reset(OneWireEnum);
    /* Select ROM number */
    OneWire_SelectWithPointer(OneWireEnum,ROM);
    /* Read scratchpad command by onewire protocol */
    OneWire_WriteByte(OneWireEnum,ONEWIRE_CMD_RSCRATCHPAD);
   
    /* Get data */
    for (i = 0; i < 9; i++) {
        /* Read byte by byte */
        data[i] = OneWire_ReadByte(OneWireEnum);
    }
   
    /* Calculate CRC */
    crc = OneWire_CRC8(data, 8);
   
    /* Check if CRC is ok */
    if (crc != data[8]) {
        /* CRC invalid */
        return 0;
    }
   
    /* First two bytes of scratchpad are temperature values */
    temperature = data[0] | (data[1] << 8);

    /* Reset line */
    OneWire_Reset(OneWireEnum);
   
    /* Check if temperature is negative */
    if (temperature & 0x8000) {
        /* Two's complement, temperature is negative */
        temperature = ~temperature + 1;
        minus = 1;
    }

   
    /* Get sensor resolution */
    resolution = ((data[4] & 0x60) >> 5) + 9;

   
    /* Store temperature integer digits and decimal digits */
    digit = temperature >> 4;
    digit |= ((temperature >> 8) & 0x7) << 4;
   
    /* Store decimal digits */
    switch (resolution) {
        case 9: {
            decimal = (temperature >> 3) & 0x01;
            decimal *= (float)DS18B20_DECIMAL_STEPS_9BIT;
        } break;
        case 10: {
            decimal = (temperature >> 2) & 0x03;
            decimal *= (float)DS18B20_DECIMAL_STEPS_10BIT;
        } break;
        case 11: {
            decimal = (temperature >> 1) & 0x07;
            decimal *= (float)DS18B20_DECIMAL_STEPS_11BIT;
        } break;
        case 12: {
            decimal = temperature & 0x0F;
            decimal *= (float)DS18B20_DECIMAL_STEPS_12BIT;
        } break;
        default: {
            decimal = 0xFF;
            digit = 0;
        }
    }
   
    /* Check for negative part */
    decimal = digit + decimal;
    if (minus) {
        decimal = 0 - decimal;
    }
   
    /* Set to pointer */
    *destination = decimal;
   
    /* Return 1, temperature valid */
    return 1;
}

uint8_t DS18B20_GetResolution(OneWire_IOTypeDef OneWireEnum,uint8_t *ROM) {
    uint8_t conf;
   
    if (!DS18B20_Is(ROM)) {
        return 0;
    }
   
    /* Reset line */
    OneWire_Reset(OneWireEnum);
    /* Select ROM number */
    OneWire_SelectWithPointer(OneWireEnum,ROM);
    /* Read scratchpad command by onewire protocol */
    OneWire_WriteByte(OneWireEnum,ONEWIRE_CMD_RSCRATCHPAD);
   
    /* Ignore first 4 bytes */
    OneWire_ReadByte(OneWireEnum);
    OneWire_ReadByte(OneWireEnum);
    OneWire_ReadByte(OneWireEnum);
    OneWire_ReadByte(OneWireEnum);
   
    /* 5th byte of scratchpad is configuration register */
    conf = OneWire_ReadByte(OneWireEnum);
   
    /* Return 9 - 12 value according to number of bits */
    return ((conf & 0x60) >> 5) + 9;
}

uint8_t DS18B20_SetResolution(OneWire_IOTypeDef OneWireEnum,uint8_t *ROM, DS18B20_Resolution_TypeDef resolution) {
    uint8_t th, tl, conf;
    if (!DS18B20_Is(ROM)) {
        return 0;
    }
   
    /* Reset line */
    OneWire_Reset(OneWireEnum);
    /* Select ROM number */
    OneWire_SelectWithPointer(OneWireEnum,ROM);
    /* Read scratchpad command by onewire protocol */
    OneWire_WriteByte(OneWireEnum,ONEWIRE_CMD_RSCRATCHPAD);
   
    /* Ignore first 2 bytes */
    OneWire_ReadByte(OneWireEnum);
    OneWire_ReadByte(OneWireEnum);
   
    th = OneWire_ReadByte(OneWireEnum);
    tl = OneWire_ReadByte(OneWireEnum);
    conf = OneWire_ReadByte(OneWireEnum);
   
    if (resolution == DS18B20_RESOLUTION_9BITS) {
        conf &= ~(1 << DS18B20_RESOLUTION_R1);
        conf &= ~(1 << DS18B20_RESOLUTION_R0);
    } else if (resolution == DS18B20_RESOLUTION_10BITS) {
        conf &= ~(1 << DS18B20_RESOLUTION_R1);
        conf |= 1 << DS18B20_RESOLUTION_R0;
    } else if (resolution == DS18B20_RESOLUTION_11BITS) {
        conf |= 1 << DS18B20_RESOLUTION_R1;
        conf &= ~(1 << DS18B20_RESOLUTION_R0);
    } else if (resolution == DS18B20_RESOLUTION_12BITS) {
        conf |= 1 << DS18B20_RESOLUTION_R1;
        conf |= 1 << DS18B20_RESOLUTION_R0;
    }
   
    /* Reset line */
    OneWire_Reset(OneWireEnum);
    /* Select ROM number */
    OneWire_SelectWithPointer(OneWireEnum,ROM);
    /* Write scratchpad command by onewire protocol, only th, tl and conf register can be written */
    OneWire_WriteByte(OneWireEnum,ONEWIRE_CMD_WSCRATCHPAD);
   
    /* Write bytes */
    OneWire_WriteByte(OneWireEnum,th);
    OneWire_WriteByte(OneWireEnum,tl);
    OneWire_WriteByte(OneWireEnum,conf);
   
    /* Reset line */
    OneWire_Reset(OneWireEnum);
    /* Select ROM number */
    OneWire_SelectWithPointer(OneWireEnum,ROM);
    /* Copy scratchpad to EEPROM of DS18B20 */
    OneWire_WriteByte(OneWireEnum,ONEWIRE_CMD_CPYSCRATCHPAD);
   
    return 1;
}

uint8_t DS18B20_Is(uint8_t *ROM) {
    /* Checks if first byte is equal to DS18B20's family code */
    if (*ROM == DS18B20_FAMILY_CODE) {
        return 1;
    }
    return 0;
}

uint8_t DS18B20_SetAlarmLowTemperature(OneWire_IOTypeDef OneWireEnum,uint8_t *ROM, int8_t temp) {
    uint8_t tl, th, conf;
    if (!DS18B20_Is(ROM)) {
        return 0;
    }
    if (temp > 125) {
        temp = 125;
    }
    if (temp < -55) {
        temp = -55;
    }
    /* Reset line */
    OneWire_Reset(OneWireEnum);
    /* Select ROM number */
    OneWire_SelectWithPointer(OneWireEnum,ROM);
    /* Read scratchpad command by onewire protocol */
    OneWire_WriteByte(OneWireEnum,ONEWIRE_CMD_RSCRATCHPAD);
   
    /* Ignore first 2 bytes */
    OneWire_ReadByte(OneWireEnum);
    OneWire_ReadByte(OneWireEnum);
   
    th = OneWire_ReadByte(OneWireEnum);
    tl = OneWire_ReadByte(OneWireEnum);
    conf = OneWire_ReadByte(OneWireEnum);
   
    tl = (uint8_t)temp;

    /* Reset line */
    OneWire_Reset(OneWireEnum);
    /* Select ROM number */
    OneWire_SelectWithPointer(OneWireEnum,ROM);
    /* Write scratchpad command by onewire protocol, only th, tl and conf register can be written */
    OneWire_WriteByte(OneWireEnum,ONEWIRE_CMD_WSCRATCHPAD);
   
    /* Write bytes */
    OneWire_WriteByte(OneWireEnum,th);
    OneWire_WriteByte(OneWireEnum,tl);
    OneWire_WriteByte(OneWireEnum,conf);
   
    /* Reset line */
    OneWire_Reset(OneWireEnum);
    /* Select ROM number */
    OneWire_SelectWithPointer(OneWireEnum,ROM);
    /* Copy scratchpad to EEPROM of DS18B20 */
    OneWire_WriteByte(OneWireEnum,ONEWIRE_CMD_CPYSCRATCHPAD);
   
    return 1;
}

uint8_t DS18B20_SetAlarmHighTemperature(OneWire_IOTypeDef OneWireEnum,uint8_t *ROM, int8_t temp) {
    uint8_t tl, th, conf;
    if (!DS18B20_Is(ROM)) {
        return 0;
    }
    if (temp > 125) {
        temp = 125;
    }
    if (temp < -55) {
        temp = -55;
    }
    /* Reset line */
    OneWire_Reset(OneWireEnum);
    /* Select ROM number */
    OneWire_SelectWithPointer(OneWireEnum,ROM);
    /* Read scratchpad command by onewire protocol */
    OneWire_WriteByte(OneWireEnum,ONEWIRE_CMD_RSCRATCHPAD);
   
    /* Ignore first 2 bytes */
    OneWire_ReadByte(OneWireEnum);
    OneWire_ReadByte(OneWireEnum);
   
    th = OneWire_ReadByte(OneWireEnum);
    tl = OneWire_ReadByte(OneWireEnum);
    conf = OneWire_ReadByte(OneWireEnum);
   
    th = (uint8_t)temp;

    /* Reset line */
    OneWire_Reset(OneWireEnum);
    /* Select ROM number */
    OneWire_SelectWithPointer(OneWireEnum,ROM);
    /* Write scratchpad command by onewire protocol, only th, tl and conf register can be written */
    OneWire_WriteByte(OneWireEnum,ONEWIRE_CMD_WSCRATCHPAD);
   
    /* Write bytes */
    OneWire_WriteByte(OneWireEnum,th);
    OneWire_WriteByte(OneWireEnum,tl);
    OneWire_WriteByte(OneWireEnum,conf);
   
    /* Reset line */
    OneWire_Reset(OneWireEnum);
    /* Select ROM number */
    OneWire_SelectWithPointer(OneWireEnum,ROM);
    /* Copy scratchpad to EEPROM of DS18B20 */
    OneWire_WriteByte(OneWireEnum,ONEWIRE_CMD_CPYSCRATCHPAD);
   
    return 1;
}

uint8_t DS18B20_DisableAlarmTemperature(OneWire_IOTypeDef OneWireEnum,uint8_t *ROM) {
    uint8_t tl, th, conf;
    if (!DS18B20_Is(ROM)) {
        return 0;
    }
    /* Reset line */
    OneWire_Reset(OneWireEnum);
    /* Select ROM number */
    OneWire_SelectWithPointer(OneWireEnum,ROM);
    /* Read scratchpad command by onewire protocol */
    OneWire_WriteByte(OneWireEnum,ONEWIRE_CMD_RSCRATCHPAD);
   
    /* Ignore first 2 bytes */
    OneWire_ReadByte(OneWireEnum);
    OneWire_ReadByte(OneWireEnum);
   
    th = OneWire_ReadByte(OneWireEnum);
    tl = OneWire_ReadByte(OneWireEnum);
    conf = OneWire_ReadByte(OneWireEnum);
   
    th = 125;
    tl = (uint8_t)-55;

    /* Reset line */
    OneWire_Reset(OneWireEnum);
    /* Select ROM number */
    OneWire_SelectWithPointer(OneWireEnum,ROM);
    /* Write scratchpad command by onewire protocol, only th, tl and conf register can be written */
    OneWire_WriteByte(OneWireEnum,ONEWIRE_CMD_WSCRATCHPAD);
   
    /* Write bytes */
    OneWire_WriteByte(OneWireEnum,th);
    OneWire_WriteByte(OneWireEnum,tl);
    OneWire_WriteByte(OneWireEnum,conf);
   
    /* Reset line */
    OneWire_Reset(OneWireEnum);
    /* Select ROM number */
    OneWire_SelectWithPointer(OneWireEnum,ROM);
    /* Copy scratchpad to EEPROM of DS18B20 */
    OneWire_WriteByte(OneWireEnum,ONEWIRE_CMD_CPYSCRATCHPAD);
   
    return 1;
}

uint8_t DS18B20_AlarmSearch(OneWire_IOTypeDef OneWireEnum) {
    /* Start alarm search */
    return OneWire_Search(OneWireEnum,DS18B20_CMD_ALARMSEARCH);
}

uint8_t DS18B20_AllDone(OneWire_IOTypeDef OneWireEnum) {
    /* If read bit is low, then device is not finished yet with calculation temperature */
    return OneWire_ReadBit(OneWireEnum);
}
 

   
/******************* (C) COPYRIGHT 2015 ACIS *****END OF FILE****/

And here is init device code: ( I use 2 devices DS18B20, each device conecto to 1 IO pin)
Code:
#define EXPECTING_SENSORS          2 
static uint8_t ROM[EXPECTING_SENSORS][8];
static uint8_t devices[EXPECTING_SENSORS];//status of detected device 1: Detected OK, 0: no device detected
uint8_t DetectOK[EXPECTING_SENSORS];// temp variable, if device is detected and has ROM code is not equal 0.
static uint8_t count[EXPECTING_SENSORS];// Counter how many device in 1 IO pin ( of course only 1, because using 2 device but each device connect to 1 IO pin)

    for(i=0;i<EXPECTING_SENSORS;i++)
    {
        /* Add first time code here */
        /* clear ROM data */
        memset(ROM[i],0,8);
        count[i]=0;
        OneWire_Init(i);
        /* Checks for any device on 1-wire */
        devices[i] = OneWire_First((OneWire_IOTypeDef)i);
        if (devices[i]) {
          /* Increase counter */
          count[i]++;
         
          /* Get full ROM value, 8 bytes, give location of first byte where to save */
          OneWire_GetFullROM((OneWire_IOTypeDef)i,ROM[i]);
          /* Get next device */
          devices[i] = OneWire_Next((OneWire_IOTypeDef)i);
        }

        /* Go through all connected devices and set resolution to 12bits */
        for (j = 0; j < count[i]; j++)
        {
          /* Set resolution to 12bits */
          DS18B20_SetResolution((OneWire_IOTypeDef)i,ROM[i], DS18B20_RESOLUTION_12BITS);
          /* Set high temperature alarm on device number 0, 25 degrees celcius */
          DS18B20_DisableAlarmTemperature((OneWire_IOTypeDef)i,ROM[i]);
        }
        /* Start temperature conversion on all devices on one bus */
        DS18B20_StartAll((OneWire_IOTypeDef)i);
        /* Wait until all are done on one onewire port */
        if (!DS18B20_AllDone((OneWire_IOTypeDef)i)){;}
        /* Start TO */
        if(Setting.DebugEnable)
        {
          #ifdef __USING_UART_DEBUG
          UART_DBG_Print("Init ds18b20");
          printf("Num of device: %d\r\n",count[i]);
          #endif
        }
      }
      DetectOK[i]=0;     
      for(j=0;j<8;j++)
      {
        if(device[i][j]!=0)
        {
          DetectOK[i]=1;
        }
      }
      if(!DetectOK[i])
      {
        if(Setting.DebugEnable)
        {
          #ifdef __USING_UART_DEBUG
          printf("Not detect any device\r\n");
          #endif
        }
      }
      else
      {
        if(Setting.DebugEnable)
        {
          #ifdef __USING_UART_DEBUG
          printf("Detect OK\r\n");
          printf("ROM code is: 0x%x:0x%x:0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\r\n",
                  ROM[i][0],ROM[i][1],ROM[i][2],ROM[i][3],
                  ROM[i][4],ROM[i][5],ROM[i][6],ROM[i][7]);
          #endif
        }
        /* Start temperature conversion on all devices on one bus */
        DS18B20_StartAll((OneWire_IOTypeDef)i);
      }
    }
Finally, read temperature value:

Code:
  float temps[EXPECTING_SENSORS]; //variable to store temperature data, 2 device (EXPECTING_SENSORS define as upper), each device connect to 1 IO pin
  /* TO to read temp */
  for(i=0;i<EXPECTING_SENSORS;i++)
  {
    /* Wait until all are done on one onewire port */
    if(DS18B20_AllDone((OneWire_IOTypeDef)i))
    {
      /* Read temperature from each device separatelly */
      for (j = 0; j < count[i]; j++)
      {
        /* Read temperature from ROM address and store it to temps variable */
        if (DS18B20_Read((OneWire_IOTypeDef)i,device[i], &temps[i]))
        {
          /* Print temperature */
          temps[i]+=0.5;
        }
        else
        {
          /* Reading error */
        }
      }
    }
  }
 

DatLe

May 31, 2016
15
Joined
May 31, 2016
Messages
15
Step by step,
Firstly, read ROM code. If you get ROM code OK, go to next step.
Did you used debugger before??? Its very helpful to trace exactly where is the bug?
 

Sadlercomfort

Ash
Feb 9, 2013
424
Joined
Feb 9, 2013
Messages
424
Step by step,
Firstly, read ROM code. If you get ROM code OK, go to next step.
Did you used debugger before??? Its very helpful to trace exactly where is the bug?

I was able to get a presence signal back from the DS if thats what you mean, after that nothing seemed to work.

The presence signal is the first step, after that however.. there is a huge amount of code before I receive anything back from the DS. So it's difficult to determine which part of the code is incorrect.

I ran the code through the MPLAB debugger and everything seemed ok. The debugger cannot simulate the DS though.


It's either my code, or the DS is faulty :rolleyes:
 

DatLe

May 31, 2016
15
Joined
May 31, 2016
Messages
15
Hi Sadlercomfort,

I read your source code again and they have some point may be "wrong"
Code:
unsigned char read_bit(void)
{
    DQ = 0;             // pull DQ low to start timeslot
    TRISC0=0;            //Lower the port
    TRISC0=1;            //Release to return high
    DQ = 1;             // then return high
    __delay_us(15);     // delay 15us from start of timeslot
    return(DQ);            // return value of DQ line
}

Follow up waveform of OW:
27115220560_77dc3b9c4b_o_d.gif

Set output--> out 0 -->"have a small delay (A)" -->set input -->"wait a little to make sure DS18b20 return value (E)"-->read bit -->"small deday to wait follow up waveform(F)".

You can follow up waveform I post upper, to fix other one wire function.
I post my onewire lib:
onewire.h:
Code:
/**
  ******************************************************************************
  * @file   :onewire.h
  * @author :DatLe
  * @version:v1_00
  * @date   :   
  * @brief  :Header file for onewire.c module.
  ******************************************************************************
  ****************************************************************************** 
  */
 
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __ONEWIRE_H
#define __ONEWIRE_H

#ifdef __cplusplus
extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
   #include "stm32f4xx.h"
   #include "common.h"
   #include "delay.h"

/**
@code 
@endcode
*/
/* OneWire delay */
#define ONEWIRE_DELAY(x)                                DelayUs(x)

/* Pin define */
#define ONEWIRE1_PIN                             GPIO_PIN_2
#define ONEWIRE1_GPIO_PORT                       GPIOA
#define ONEWIRE1_GPIO_CLK_ENABLE()               __GPIOA_CLK_ENABLE() 
#define ONEWIRE1_GPIO_CLK_DISABLE()              __GPIOA_CLK_DISABLE()

#define ONEWIRE2_PIN                             GPIO_PIN_3
#define ONEWIRE2_GPIO_PORT                       GPIOA
#define ONEWIRE2_GPIO_CLK_ENABLE()               __GPIOA_CLK_ENABLE() 
#define ONEWIR2_GPIO_CLK_DISABLE()              __GPIOA_CLK_DISABLE()

#define ONEWRIREx_GPIO_CLK_ENABLE(__INDEX__)        (((__INDEX__) == ONEWIRE1) ? ONEWIRE1_GPIO_CLK_ENABLE() :ONEWIRE2_GPIO_CLK_ENABLE())
/* Pin settings */
#define ONEWIRE_LOW(x)                                HAL_GPIO_WritePin(GPIO_PORT[x], GPIO_PIN[x], GPIO_PIN_RESET)//TM_GPIO_SetPinLow()
#define ONEWIRE_HIGH(x)                              HAL_GPIO_WritePin(GPIO_PORT[x], GPIO_PIN[x], GPIO_PIN_SET)//TM_GPIO_SetPinHigh()
#define ONEWIRE_READ(x)                         HAL_GPIO_ReadPin(GPIO_PORT[x], GPIO_PIN[x])
#define ONEWIRE_INPUT(x)                            TM_GPIO_SetPinAsInput(x)
#define ONEWIRE_OUTPUT(x)                          TM_GPIO_SetPinAsOutput(x)

/* 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
/**
  * @}
  */
 
/** @defgroup Exported_Types
  * @{
  */
typedef enum
{
  ONEWIRE1=0,
  ONEWIRE2,
 
  ONEWIRE_TOTAL_NUM
}OneWire_IOTypeDef;
/**
* @brief  OneWire working struct
* @note   Except ROM_NO member, everything is fully private and should not be touched by user
*/
typedef struct {
    uint8_t LastDiscrepancy;       /*!< Search private */
    uint8_t LastFamilyDiscrepancy; /*!< Search private */
    uint8_t LastDeviceFlag;        /*!< Search private */
    uint8_t ROM_NO[8];             /*!< 8-bytes address of last search device */
} OneWire_TypeDef;
/**
  * @}
  */
 
/** @defgroup Exported_Constants
  * @{
  */
/**
  * @}
  */

/** @defgroup Exported_Macros
  * @{
  */
/**
  * @}
  */

/** @defgroup Exported_Functions
  * @{
  */
/**
* @brief  Initializes OneWire bus
* @param  *OneWireStruct: Pointer to @ref TM_OneWire_t empty working onewire structure
* @param  *Pointer to GPIO port used for onewire channel
* @param  GPIO_Pin: GPIO Pin on specific GPIOx to be used for onewire channel
* @retval None
*/
void OneWire_Init(OneWire_IOTypeDef OneWireEnum);

/**
* @brief  Resets OneWire bus
*
* @note   Sends reset command for OneWire
* @param  *OneWireStruct: Pointer to @ref TM_OneWire_t working onewire structure
* @retval None
*/
uint8_t OneWire_Reset(OneWire_IOTypeDef OneWireEnum);

/**
* @brief  Reads byte from one wire bus
* @param  *OneWireStruct: Pointer to @ref TM_OneWire_t working onewire structure
* @retval Byte from read operation
*/
uint8_t OneWire_ReadByte(OneWire_IOTypeDef OneWireEnum);

/**
* @brief  Writes byte to bus
* @param  *OneWireStruct: Pointer to @ref TM_OneWire_t working onewire structure
* @param  byte: 8-bit value to write over OneWire protocol
* @retval None
*/
void OneWire_WriteByte( OneWire_IOTypeDef OneWireEnum,uint8_t byte);

/**
* @brief  Writes single bit to onewire bus
* @param  *OneWireStruct: Pointer to @ref TM_OneWire_t working onewire structure
* @param  bit: Bit value to send, 1 or 0
* @retval None
*/
void OneWire_WriteBit(OneWire_IOTypeDef OneWireEnum,uint8_t bit);

/**
* @brief  Reads single bit from one wire bus
* @param  *OneWireStruct: Pointer to @ref TM_OneWire_t working onewire structure
* @retval Bit value:
*            - 0: Bit is low (zero)
*            - > 0: Bit is high (one)
*/
uint8_t OneWire_ReadBit(OneWire_IOTypeDef OneWireEnum);

/**
* @brief  Searches for OneWire devices on specific Onewire port
* @note   Not meant for public use. Use @ref TM_OneWire_First and @ref TM_OneWire_Next for this.
* @param  *OneWireStruct: Pointer to @ref TM_OneWire_t working onewire structure where to search
* @param  Device status:
*            - 0: No devices detected
*            - > 0: Device detected
*/
uint8_t OneWire_Search(OneWire_IOTypeDef OneWireEnum,uint8_t command);

/**
* @brief  Resets search states
* @param  *OneWireStruct: Pointer to @ref TM_OneWire_t working onewire where to reset search values
* @retval None
*/
void OneWire_ResetSearch(OneWire_IOTypeDef OneWireEnum);

/**
* @brief  Starts search, reset states first
* @note   When you want to search for ALL devices on one onewire port, you should first use this function.
@verbatim
/...Initialization before
status = TM_OneWire_First(&OneWireStruct);
while (status) {
    //Save ROM number from device
    TM_OneWire_GetFullROM(ROM_Array_Pointer);
    //Check for new device
    status = TM_OneWire_Next(&OneWireStruct);
}
@endverbatim
* @param  *OneWireStruct: Pointer to @ref TM_OneWire_t working onewire where to reset search values
* @param  Device status:
*            - 0: No devices detected
*            - > 0: Device detected
*/
uint8_t OneWire_First(OneWire_IOTypeDef OneWireEnum);

/**
* @brief  Reads next device
* @note   Use @ref TM_OneWire_First to start searching
* @param  *OneWireStruct: Pointer to @ref TM_OneWire_t working onewire
* @param  Device status:
*            - 0: No devices detected any more
*            - > 0: New device detected
*/
uint8_t OneWire_Next(OneWire_IOTypeDef OneWireEnum);

/**
* @brief  Gets ROM number from device from search
* @param  *OneWireStruct: Pointer to @ref TM_OneWire_t working onewire
* @param  index: Because each device has 8-bytes long ROm address, you have to call this 8 times, to get ROM bytes from 0 to 7
* @reetval ROM byte for index (0 to 7) at current found device
*/
uint8_t OneWire_GetROM(OneWire_IOTypeDef OneWireEnum,uint8_t index);

/**
* @brief  Gets all 8 bytes ROM value from device from search
* @param  *OneWireStruct: Pointer to @ref TM_OneWire_t working onewire
* @param  *firstIndex: Pointer to first location for first byte, other bytes are automatically incremented
* @retval None
*/
void OneWire_GetFullROM(OneWire_IOTypeDef OneWireEnum,uint8_t *firstIndex);

/**
* @brief  Selects specific slave on bus
* @param  *OneWireStruct: Pointer to @ref TM_OneWire_t working onewire
* @param  *addr: Pointer to first location of 8-bytes long ROM address
* @retval None
*/
void OneWire_Select(OneWire_IOTypeDef OneWireEnum,uint8_t* addr);

/**
* @brief  Selects specific slave on bus with pointer address
* @param  *OneWireStruct: Pointer to @ref TM_OneWire_t working onewire
* @param  *ROM: Pointer to first byte of ROM address
* @retval None
*/
void OneWire_SelectWithPointer(OneWire_IOTypeDef OneWire,uint8_t* ROM);

/**
* @brief  Calculates 8-bit CRC for 1-wire devices
* @param  *addr: Pointer to 8-bit array of data to calculate CRC
* @param  len: Number of bytes to check
*
* @retval Calculated CRC from input data
*/
uint8_t OneWire_CRC8(uint8_t* addr, uint8_t len);


/**
  * @}
  */

#ifdef __cplusplus
}
#endif


#endif /* ___H */

/**
  * @}
  */

/**
  * @}
  */

/**
  * @}
  */   

/******************* (C) COPYRIGHT 2015 ACIS *****END OF FILE****/

onewire.c:
Code:
/**
  ******************************************************************************
  * @file    :onewire.c
  * @author  :DatLe
  * @version :
  * @date    :
  * @brief   :
  *          This file should be added to the main application to use the provided
  *          functions that manage Leds, push-buttons, COM ports and low level
  *          HW resources initialization of the different modules available on
  *          STM32 evaluation boards from STMicroelectronics.
  ******************************************************************************
  */
 
/* Includes ------------------------------------------------------------------*/
#include "onewire.h"

/** @addtogroup Utilities
  * @{
  */
 

/** @defgroup Abstraction_Layer
  * @{
  */
 
/** @defgroup Public_Variables
  * @{
  */

/** @defgroup Private_TypesDefinitions
  * @{
  */

/**
  * @}
  */


/** @defgroup Private_Defines
  * @{
  */
/**
  * @}
  */


/** @defgroup Private_Macros
  * @{
  */
/**
  * @}
  */


/** @defgroup Private_Variables
  * @{
  */
static GPIO_TypeDef* GPIO_PORT[] ={ONEWIRE1_GPIO_PORT,
                                   ONEWIRE2_GPIO_PORT};

static const uint16_t GPIO_PIN[] =     {ONEWIRE1_PIN,
                                       ONEWIRE2_PIN};
static OneWire_TypeDef OneWire[ONEWIRE_TOTAL_NUM];
/**
  * @}
  */


/** @defgroup FunctionPrototypes
  * @{
  */
/**
  * @}
  */
static void TM_GPIO_SetPinAsInput(OneWire_IOTypeDef OneWire);
static void TM_GPIO_SetPinAsOutput(OneWire_IOTypeDef OneWire);

/** @defgroup Private_Functions
  * @{
  */
 
static void TM_GPIO_SetPinAsInput(OneWire_IOTypeDef OneWireEnum)
{
  /* Enable the GPIO_LED Clock */
  GPIO_InitTypeDef GPIO_InitStruct;

  /* Configure the GPIO_ONEWIRE pin */
  GPIO_InitStruct.Pin = GPIO_PIN[OneWireEnum];
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_MEDIUM;
 
  HAL_GPIO_Init(GPIO_PORT[OneWireEnum], &GPIO_InitStruct);
}
static void TM_GPIO_SetPinAsOutput(OneWire_IOTypeDef OneWire)
{
  /* Enable the GPIO_LED Clock */
  GPIO_InitTypeDef GPIO_InitStruct;

  /* Configure the GPIO_ONEWIRE pin */
  GPIO_InitStruct.Pin = GPIO_PIN[OneWire];
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_MEDIUM;
 
  HAL_GPIO_Init(GPIO_PORT[OneWire], &GPIO_InitStruct);
}
void OneWire_Init(OneWire_IOTypeDef OneWireEnum) {
    /* Init GPIO pin */
  /* Enable the GPIO_LED Clock */
  GPIO_InitTypeDef GPIO_InitStruct;
  /* Enable the GPIO_BUZZER Clock */
    ONEWRIREx_GPIO_CLK_ENABLE(OneWireEnum);

    /* Configure the GPIO_ONEWIRE pin */
    GPIO_InitStruct.Pin = GPIO_PIN[OneWireEnum];
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_MEDIUM;
   
    HAL_GPIO_Init(GPIO_PORT[OneWireEnum], &GPIO_InitStruct);
}

uint8_t OneWire_Reset(OneWire_IOTypeDef OneWireEnum)
{
    uint8_t i;
   
    /* Line low, and wait 480us */
    ONEWIRE_LOW(OneWireEnum);
    ONEWIRE_OUTPUT(OneWireEnum);
    ONEWIRE_DELAY(480);
   
    /* Release line and wait for 70us */
    ONEWIRE_INPUT(OneWireEnum);
    ONEWIRE_DELAY(70);
   
    /* Check bit value */
    i = ONEWIRE_READ(OneWireEnum);
   
    /* Delay for 410 us */
    ONEWIRE_DELAY(410);
   
    /* Return value of presence pulse, 0 = OK, 1 = ERROR */
    return i;
}

void OneWire_WriteBit(OneWire_IOTypeDef OneWireEnum,uint8_t bit) {
    if (bit) {
        /* Set line low */
        ONEWIRE_LOW(OneWireEnum);
        ONEWIRE_OUTPUT(OneWireEnum);
        ONEWIRE_DELAY(10);
       
        /* Bit high */
        ONEWIRE_INPUT(OneWireEnum);
       
        /* Wait for 55 us and release the line */
        ONEWIRE_DELAY(55);
        ONEWIRE_INPUT(OneWireEnum);
    } else {
        /* Set line low */
        ONEWIRE_LOW(OneWireEnum);
        ONEWIRE_OUTPUT(OneWireEnum);
        ONEWIRE_DELAY(65);
       
        /* Bit high */
        ONEWIRE_INPUT(OneWireEnum);
       
        /* Wait for 5 us and release the line */
        ONEWIRE_DELAY(5);
        ONEWIRE_INPUT(OneWireEnum);
    }

}

uint8_t OneWire_ReadBit(OneWire_IOTypeDef OneWireEnum)
{
    uint8_t bit = 0;
   
    /* Line low */
    ONEWIRE_LOW(OneWireEnum);
    ONEWIRE_OUTPUT(OneWireEnum);
    ONEWIRE_DELAY(3);
   
    /* Release line */
    ONEWIRE_INPUT(OneWireEnum);
    ONEWIRE_DELAY(10);
   
    /* Read line value */
    if (ONEWIRE_READ(OneWireEnum)) {
        /* Bit is HIGH */
        bit = 1;
    }
   
    /* Wait 50us to complete 60us period */
    ONEWIRE_DELAY(50);
   
    /* Return bit value */
    return bit;
}

void OneWire_WriteByte(OneWire_IOTypeDef OneWireEnum,uint8_t byte)
{
    uint8_t i = 8;
    /* Write 8 bits */
    while (i--) {
        /* LSB bit is first */
        OneWire_WriteBit(OneWireEnum,byte & 0x01);
        byte >>= 1;
    }
}

uint8_t OneWire_ReadByte(OneWire_IOTypeDef OneWireEnum) {
    uint8_t i = 8, byte = 0;
    while (i--) {
        byte >>= 1;
        byte |= (OneWire_ReadBit(OneWireEnum) << 7);
    }
   
    return byte;
}

uint8_t OneWire_First(OneWire_IOTypeDef OneWireEnum)
{
    /* Reset search values */
    OneWire_ResetSearch(OneWireEnum);

    /* Start with searching */
    return OneWire_Search(OneWireEnum,ONEWIRE_CMD_SEARCHROM);
}

uint8_t OneWire_Next(OneWire_IOTypeDef OneWireEnum) {
   /* Leave the search state alone */
   return OneWire_Search(OneWireEnum,ONEWIRE_CMD_SEARCHROM);
}

void OneWire_ResetSearch(OneWire_IOTypeDef OneWireEnum) {
    /* Reset the search state */
    OneWire[OneWireEnum].LastDiscrepancy = 0;
    OneWire[OneWireEnum].LastDeviceFlag = 0;
    OneWire[OneWireEnum].LastFamilyDiscrepancy = 0;
}

uint8_t OneWire_Search(OneWire_IOTypeDef OneWireEnum,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 (!OneWire[OneWireEnum].LastDeviceFlag) {
        // 1-Wire reset
        if (OneWire_Reset(OneWireEnum)) {
            /* Reset the search */
            OneWire[OneWireEnum].LastDiscrepancy = 0;
            OneWire[OneWireEnum].LastDeviceFlag = 0;
            OneWire[OneWireEnum].LastFamilyDiscrepancy = 0;
            return 0;
        }

        // issue the search command
        OneWire_WriteByte(OneWireEnum,command); 

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

            // 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 < OneWire[OneWireEnum].LastDiscrepancy) {
                        search_direction = ((OneWire[OneWireEnum].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 == OneWire[OneWireEnum].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) {
                            OneWire[OneWireEnum].LastFamilyDiscrepancy = last_zero;
                        }
                    }
                }

                // set or clear the bit in the ROM byte rom_byte_number
                // with mask rom_byte_mask
                if (search_direction == 1) {
                    OneWire[OneWireEnum].ROM_NO[rom_byte_number] |= rom_byte_mask;
                } else {
                    OneWire[OneWireEnum].ROM_NO[rom_byte_number] &= ~rom_byte_mask;
                }
               
                // serial number search direction write bit
                OneWire_WriteBit(OneWireEnum,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
            OneWire[OneWireEnum].LastDiscrepancy = last_zero;

            // check for last device
            if (OneWire[OneWireEnum].LastDiscrepancy == 0) {
                OneWire[OneWireEnum].LastDeviceFlag = 1;
            }

            search_result = 1;
        }
    }

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

    return search_result;
}

int OneWire_Verify(OneWire_IOTypeDef OneWireEnum) {
    unsigned char rom_backup[8];
    int i,rslt,ld_backup,ldf_backup,lfd_backup;

    // keep a backup copy of the current state
    for (i = 0; i < 8; i++)
    rom_backup[i] = OneWire[OneWireEnum].ROM_NO[i];
    ld_backup = OneWire[OneWireEnum].LastDiscrepancy;
    ldf_backup = OneWire[OneWireEnum].LastDeviceFlag;
    lfd_backup = OneWire[OneWireEnum].LastFamilyDiscrepancy;

    // set search to find the same device
    OneWire[OneWireEnum].LastDiscrepancy = 64;
    OneWire[OneWireEnum].LastDeviceFlag = 0;

    if (OneWire_Search(OneWireEnum,ONEWIRE_CMD_SEARCHROM)) {
        // check if same device found
        rslt = 1;
        for (i = 0; i < 8; i++) {
            if (rom_backup[i] != OneWire[OneWireEnum].ROM_NO[i]) {
                rslt = 1;
                break;
            }
        }
    } else {
        rslt = 0;
    }

    // restore the search state
    for (i = 0; i < 8; i++) {
        OneWire[OneWireEnum].ROM_NO[i] = rom_backup[i];
    }
    OneWire[OneWireEnum].LastDiscrepancy = ld_backup;
    OneWire[OneWireEnum].LastDeviceFlag = ldf_backup;
    OneWire[OneWireEnum].LastFamilyDiscrepancy = lfd_backup;

    // return the result of the verify
    return rslt;
}

void OneWire_TargetSetup(OneWire_IOTypeDef OneWireEnum,uint8_t family_code) {
   uint8_t i;

    // set the search state to find SearchFamily type devices
    OneWire[OneWireEnum].ROM_NO[0] = family_code;
    for (i = 1; i < 8; i++) {
        OneWire[OneWireEnum].ROM_NO[i] = 0;
    }
   
    OneWire[OneWireEnum].LastDiscrepancy = 64;
    OneWire[OneWireEnum].LastFamilyDiscrepancy = 0;
    OneWire[OneWireEnum].LastDeviceFlag = 0;
}

void OneWire_FamilySkipSetup(OneWire_IOTypeDef OneWireEnum) {
    // set the Last discrepancy to last family discrepancy
    OneWire[OneWireEnum].LastDiscrepancy = OneWire[OneWireEnum].LastFamilyDiscrepancy;
    OneWire[OneWireEnum].LastFamilyDiscrepancy = 0;

    // check for end of list
    if (OneWire[OneWireEnum].LastDiscrepancy == 0) {
        OneWire[OneWireEnum].LastDeviceFlag = 1;
    }
}

uint8_t OneWire_GetROM(OneWire_IOTypeDef OneWireEnum,uint8_t index) {
    return OneWire[OneWireEnum].ROM_NO[index];
}

void OneWire_Select(OneWire_IOTypeDef OneWireEnum,uint8_t* addr) {
    uint8_t i;
    OneWire_WriteByte(OneWireEnum,ONEWIRE_CMD_MATCHROM);
   
    for (i = 0; i < 8; i++) {
        OneWire_WriteByte(OneWireEnum,*(addr + i));
    }
}

void OneWire_SelectWithPointer(OneWire_IOTypeDef OneWireEnum,uint8_t *ROM) {
    uint8_t i;
    OneWire_WriteByte(OneWireEnum,ONEWIRE_CMD_MATCHROM);
   
    for (i = 0; i < 8; i++) {
        OneWire_WriteByte(OneWireEnum,*(ROM + i));
    }   
}

void OneWire_GetFullROM(OneWire_IOTypeDef OneWireEnum,uint8_t *firstIndex) {
    uint8_t i;
    for (i = 0; i < 8; i++) {
        *(firstIndex + i) = OneWire[OneWireEnum].ROM_NO[i];
    }
}

uint8_t 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;
}
   
/******************* (C) COPYRIGHT 2015 ACIS *****END OF FILE****/
 

Sadlercomfort

Ash
Feb 9, 2013
424
Joined
Feb 9, 2013
Messages
424
I'm not using one-wire, I'm using my own supply for the DS, and my Vdd is not tied to DQ.

Can I still use this one wire code?


Also, the timing diagram you've shown me is different to the one in the datasheet and it doesn't include the time.

I'm not very good at reading timing diagrams o_O
 

Attachments

  • DS18B20.pdf
    361.8 KB · Views: 99
Last edited:

DatLe

May 31, 2016
15
Joined
May 31, 2016
Messages
15
Hi Sadlercomfort,

1. You must have pull up resistor from DQ to Vdd, Vdd from 3.3V-->5V is OK. Because DQ pin is open drain. Pull up resistors must be have. Currently, Im using 1k-->3k3. See datasheet to check the maximum Idq and choose pull up res.
2. Of course, DS18B20 communication is one wire, the figure 2 in your datasheet, it the one wire wave form. May be has a little diff but its still one wire.
3. "I'm not very good at reading timing diagrams". Hehe, you have to read if you want to code . If have any issue, contact me via skype:datle2805
 

Sadlercomfort

Ash
Feb 9, 2013
424
Joined
Feb 9, 2013
Messages
424
Hi Sadlercomfort,

1. You must have pull up resistor from DQ to Vdd, Vdd from 3.3V-->5V is OK. Because DQ pin is open drain. Pull up resistors must be have. Currently, Im using 1k-->3k3. See datasheet to check the maximum Idq and choose pull up res.

Everything is connected up fine as shown in Figure 7. With a 4.7KΩ pullup resistor and Vdd/Vpu are regulated 5v DC.

Hi Sadlercomfort,

2. Of course, DS18B20 communication is one wire, the figure 2 in your datasheet, it the one wire wave form. May be has a little diff but its still one wire.

Maybe I should rephrase that to 'I'm not using parasite power'. So are you suggesting that only difference with parasite power is the commands..not the individual reading/writing of bits?

3. "I'm not very good at reading timing diagrams". Hehe, you have to read if you want to code . If have any issue, contact me via skype:datle2805

I know the importance of reading a timing diagram, that's why I mentioned it.:rolleyes:

Figure 16 is much easier to follow than Figure 2, I'll keep mulling it over until it sinks in.
 

Sadlercomfort

Ash
Feb 9, 2013
424
Joined
Feb 9, 2013
Messages
424
It's going to take me a while to understand your code.. its like hieroglyphics to me. Again this will take time. o_O

What are these header files:
#include "stm32f4xx.h"
#include "common.h"
#include "onewire.h"
 
Last edited:

DatLe

May 31, 2016
15
Joined
May 31, 2016
Messages
15
27411723295_4a0d4062ca_b_d.jpg

OK, lets start analyze code and wave form.
Note: bold line in wave form mean that master IO pin is set as output, normal line: master IO pin set as input.
1. Master write bit 1: (figure on the right top)
/* Set line low */
// for first 15us second master always write 0 to start a transfer bit
ONEWIRE_LOW();//set output is 0
ONEWIRE_OUTPUT();// set pin as output
ONEWIRE_DELAY(15); // delay 15 us sec, depend on one wire slave device, in this case, follow wave form upper here, figure on the right top
/* Bit high */
ONEWIRE_INPUT(OneWireEnum);// set master IO pin is input -->look at figure again and you will see normal line

/* Wait for 45us and release the line */
ONEWIRE_DELAY(45);// delay 15us + 30 us -->see wave form.
ONEWIRE_INPUT(OneWireEnum);// dont care, I like to release IO as input for next bit transfer. If no need to send, Master IO pin is always set as input and connection is off

2. Master write bit 0: (figure on the left top)
/* Set line low */
ONEWIRE_LOW();
ONEWIRE_OUTPUT();// Set master IO pin as output and set IO is 0 (low)
ONEWIRE_DELAY(60);// delay 15us + 15us + 30us

/* Bit high */
ONEWIRE_INPUT();// look at the last, you see on the waveform have a small "normal line" at high (logic 1).

/* Wait for 5 us and release the line */
ONEWIRE_DELAY(5);// small "normal line" is 5us delay
ONEWIRE_INPUT();// dont care, I like to release IO as input for next bit transfer. If no need to send, Master IO pin is always set as input and connection is off.
3. Master read :
/* Line low */
ONEWIRE_LOW();
ONEWIRE_OUTPUT(); // set output and output 0
ONEWIRE_DELAY(3);// small delay > 1 us-->see wave form upper here

/* Release line */
ONEWIRE_INPUT(); // set master IO pin as input. (normal line in wave form)
ONEWIRE_DELAY(10);// wait a little to make sure DS18B20 ready to send data

/* Read line value */
if (ONEWIRE_READ()) {// get data from device
/* Bit is HIGH */
bit = 1;
}
/* Wait 50us to complete 60us period */
ONEWIRE_DELAY(50);// wait to finish 60 us one bit read phrase total time

/* Return bit value */
return bit;

Some timing may be little difference. Because using your wave form. But using my current timing in my source code its still work well. Dont worry. hehe
 

Sadlercomfort

Ash
Feb 9, 2013
424
Joined
Feb 9, 2013
Messages
424
Thanks I'm beginning to understand it more now you've broken it down. :)

Note: bold line in wave form mean that master IO pin is set as output, normal line: master IO pin set as input.
I never knew this! At the beginning of the program should I set ONEWIRE Pin as input or output? And low or high?

1. Master write bit 1: (figure on the right top)
/* Set line low */
// for first 15us second master always write 0 to start a transfer bit
ONEWIRE_LOW();//set output is 0
ONEWIRE_OUTPUT();// set pin as output
ONEWIRE_DELAY(15); // delay 15 us sec, depend on one wire slave device, in this case, follow wave form upper here, figure on the right top
/* Bit high */
ONEWIRE_INPUT(OneWireEnum);// set master IO pin is input -->look at figure again and you will see normal line

/* Wait for 45us and release the line */
ONEWIRE_DELAY(45);// delay 15us + 30 us -->see wave form.
ONEWIRE_INPUT(OneWireEnum);// dont care, I like to release IO as input for next bit transfer. If no need to send, Master IO pin is always set as input and connection is off

Also, when I set ONEWIRE_LOW(); then ONEWIRE_OUTPUT(); does this mean the voltage on the ONEWIRE pin should read ~0v. Because I've measured this with a multi-meter and I'm not getting 0v.

Why is my ONEWIRE pin not pulling low? o_O
 
Last edited:

DatLe

May 31, 2016
15
Joined
May 31, 2016
Messages
15
I never knew this! At the beginning of the program should I set ONEWIRE Pin as input or output? And low or high?
You should set master IO pin as input. because of pull up resistor, logic will be high
Also, when I set ONEWIRE_LOW(); then ONEWIRE_OUTPUT(); does this mean the voltage on the ONEWIRE pin should read ~0v. Because I've measured this with a multi-meter and I'm not getting 0v.
Depend on MCU you use, may be set IO pin as output before output its. Currently, Im using STM32F, it work. But in PIC, may be change order, set as output firstly, then output it later.
Please test you can set output and can toggle IO pin.
ONEWIRE_LOW()--> ~0V. If not, please check IO pin is correct. May be you are connecting to another pin. ^^
 

Sadlercomfort

Ash
Feb 9, 2013
424
Joined
Feb 9, 2013
Messages
424
I've created a simple program like so:
Code:
void main()
{
    while(1){
    RC0 = 0;
    TRISC0 = 0;
     __delay_ms(3000);
    RC0 = 1;
   }

I've measured the voltage on the DQ pin, and it stays HIGH.
 

DatLe

May 31, 2016
15
Joined
May 31, 2016
Messages
15
Code:
void main()
{
    while(1){
    TRISC0 = 0;
    RC0 = 0;
     __delay_ms(1000);
    RC0 = 1;
    __delay_ms(1000);
   }
1. Try toggle again. If not, then change another IO pin and test again.
2. Try remove DQ pin and DS18B20. May be something wrong?
 

Sadlercomfort

Ash
Feb 9, 2013
424
Joined
Feb 9, 2013
Messages
424
I tried the above code but instead used RC3 pin, and works ok.

So I removed the DS18B20 and DQ pin and tested the code again.. but still getting HIGH on RC0. Something is wrong here.

I'm going to move the DS18B20 to a working pin.
 

Harald Kapp

Moderator
Moderator
Nov 17, 2011
13,700
Joined
Nov 17, 2011
Messages
13,700
Code:
void main()
{
    while(1){
    RC0 = 0;
    TRISC0 = 0;
     __delay_ms(3000);
    RC0 = 1;
   }
The problem with this code is that you have only one delay. After setting RC0=0 you wait 3 seconds, teh set RC0=1 and immediately back to RC0=0. This will give you a very short pulse on RC0 which you will not be able to detect with a multimeter.
However, your meter should show a permanent low, not high, as it does. There is nothing else connected to RC0?

By the way: TRISC0 = 0; should be outside of the loop.
 

Sadlercomfort

Ash
Feb 9, 2013
424
Joined
Feb 9, 2013
Messages
424
Sorry, I keep making mistakes today. I'm just losing abit of patience. :(

There was a small short on RC0 which held it high. I fixed it now, but i already moved DQ of the DS18B20 to RC1.

Code:
void main()  
{
    TRISC1 = 0;
    while(1){
    RC1 = 0;
    __delay_ms(2000);
    RC1 = 1;
    __delay_ms(2000);
    }

I've tested the above code, and the RC1 / DQ pin goes 5V for 2 seconds, then 4.3V for 2 seconds.

Is this correct? I assume if there was a presence pulse pulling it low, it would be too quick for the multimeter to see right?
 

Harald Kapp

Moderator
Moderator
Nov 17, 2011
13,700
Joined
Nov 17, 2011
Messages
13,700
I've tested the above code, and the RC1 / DQ pin goes 5V for 2 seconds, then 4.3V for 2 seconds.

Is this correct?
2 seconds is correct.
5V is o.k. for the High part of the loop.
4.3 V for the Low part of the loop is not correct. Logic low is less than 1V (@ 5 V supply). Make sure nothing else is connected to RC1 but the meter. It is possible that the short on RC0 has afflicted damage to the DS18B20's data pin when the chip tried to pull the output low. This may (or may not) cause the observed 4.3V: a conflict between the PIC trying to drive low and the DS trying to keep a high. A small chance, but fix the output part on the PIC side first before you add components.
 
Top