Skip to content

Instantly share code, notes, and snippets.

@gresan-gits
Created February 2, 2020 14:18
Show Gist options
  • Save gresan-gits/8626b4da8ea6322c1459ac2beb9d27ff to your computer and use it in GitHub Desktop.
Save gresan-gits/8626b4da8ea6322c1459ac2beb9d27ff to your computer and use it in GitHub Desktop.
CCS C DS18B20
/*** FILEHEADER ****************************************************************
*
* FILENAME: ds1820.h
* DATE: 25.02.2005
* AUTHOR: Christian Stadler
*
* DESCRIPTION: Driver for DS1820 1-Wire Temperature sensor (Dallas)
*
******************************************************************************/
/*** HISTORY OF CHANGE *********************************************************
*
* $Log: /pic/_drv/ds1820.h $
*
* 9 13.11.10 20:02 Stadler
* - changed interrupt lock and delay functions to #defines to remove
* function call overhead
*
* 8 6.11.10 10:24 Stadler
* - adjusted 1-wire timing
*
* 7 5.11.10 22:55 Stadler
* - changed driver API
*
* 6 5.11.10 21:59 Stadler
* - added DS18B20 support
* - fixed problem with ROM search algorithm
*
* 5 2.11.10 20:25 Stadler
* - changed function DS1820_FindFirstDev to DS1820_FindFirstDevice
* - changed function DS1820_FindNextDev to DS1820_FindNextDevice
* - updated code style
*
* 4 31.10.10 17:12 Stadler
* - introduced DS1820_DelayUs
*
* 3 25.10.10 13:09 Stadler
* - added interrupt lock
*
* 2 12.03.05 11:24 Stadler
* - added EEPROM write function
* - added "Search ROM Algorithm" to control multiple devices
*
* 1 26.02.05 18:18 Stadler
* Driver for DS1820 1-Wire Temperature sensor (Dallas)
*
******************************************************************************/
#ifndef _DS1820_H
#define _DS1820_H
/* check configuration of driver */
#ifndef DS1820_DATAPIN
#error DS1820 data pin not defined!
#endif
#define TEMP_RES 0x100 /* temperature resolution => 1/256°C = 0.0039°C */
/* -------------------------------------------------------------------------- */
/* DS1820 Timing Parameters */
/* -------------------------------------------------------------------------- */
#define DS1820_RST_PULSE 480 /* master reset pulse time in [us] */
#define DS1820_MSTR_BITSTART 2 /* delay time for bit start by master */
#define DS1820_PRESENCE_WAIT 40 /* delay after master reset pulse in [us] */
#define DS1820_PRESENCE_FIN 480 /* dealy after reading of presence pulse [us] */
#define DS1820_BITREAD_DLY 5 /* bit read delay */
#define DS1820_BITWRITE_DLY 100 /* bit write delay */
/* -------------------------------------------------------------------------- */
/* DS1820 Registers */
/* -------------------------------------------------------------------------- */
#define DS1820_REG_TEMPLSB 0
#define DS1820_REG_TEMPMSB 1
#define DS1820_REG_CNTREMAIN 6
#define DS1820_REG_CNTPERSEC 7
#define DS1820_SCRPADMEM_LEN 9 /* length of scratchpad memory */
#define DS1820_ADDR_LEN 8
/* -------------------------------------------------------------------------- */
/* DS1820 Commands */
/* -------------------------------------------------------------------------- */
#define DS1820_CMD_SEARCHROM 0xF0
#define DS1820_CMD_READROM 0x33
#define DS1820_CMD_MATCHROM 0x55
#define DS1820_CMD_SKIPROM 0xCC
#define DS1820_CMD_ALARMSEARCH 0xEC
#define DS1820_CMD_CONVERTTEMP 0x44
#define DS1820_CMD_WRITESCRPAD 0x4E
#define DS1820_CMD_READSCRPAD 0xBE
#define DS1820_CMD_COPYSCRPAD 0x48
#define DS1820_CMD_RECALLEE 0xB8
#define DS1820_FAMILY_CODE_DS18B20 0x28
#define DS1820_FAMILY_CODE_DS18S20 0x10
/* -------------------------------------------------------------------------- */
/* static variables */
/* -------------------------------------------------------------------------- */
static bool bDoneFlag;
static uint8 nLastDiscrepancy_u8;
static uint8 nRomAddr_au8[DS1820_ADDR_LEN];
/* -------------------------------------------------------------------------- */
/* Low-Level Functions */
/* -------------------------------------------------------------------------- */
/*******************************************************************************
* FUNCTION: DS1820_DelayUs
* PURPOSE: Delay for the given number of micro seconds.
*
* INPUT: dly_us number of micro seconds to delay
* OUTPUT: -
* RETURN: -
******************************************************************************/
#define DS1820_DelayUs(dly_us) delay_us(dly_us)
/*******************************************************************************
* FUNCTION: DS1820_DelayMs
* PURPOSE: Delay for the given number of milliseconds.
*
* INPUT: dly_ms number of milliseconds to delay
* OUTPUT: -
* RETURN: -
******************************************************************************/
#define DS1820_DelayMs(dly_ms) delay_ms(dly_ms)
/*******************************************************************************
* FUNCTION: DS1820_DisableInterrupts
* PURPOSE: Disable interrupts
*
* INPUT: -
* OUTPUT: -
* RETURN: -
******************************************************************************/
#ifdef DS1820_INTERRUPT_LOCK
#define DS1820_DisableInterrupts() disable_interrupts(GLOBAL)
#else
#define DS1820_DisableInterrupts()
#endif
/*******************************************************************************
* FUNCTION: DS1820_EnableInterrupts
* PURPOSE: Enable interrupts
*
* INPUT: -
* OUTPUT: -
* RETURN: -
******************************************************************************/
#ifdef DS1820_INTERRUPT_LOCK
#define DS1820_EnableInterrupts() enable_interrupts(GLOBAL)
#else
#define DS1820_EnableInterrupts()
#endif
/*******************************************************************************
* FUNCTION: DS1820_Reset
* PURPOSE: Initializes the DS1820 device.
*
* INPUT: -
* OUTPUT: -
* RETURN: FALSE if at least one device is on the 1-wire bus, TRUE otherwise
******************************************************************************/
bool DS1820_Reset(void)
{
bool bPresPulse;
DS1820_DisableInterrupts();
/* reset pulse */
output_low(DS1820_DATAPIN);
DS1820_DelayUs(DS1820_RST_PULSE);
output_high(DS1820_DATAPIN);
/* wait until pullup pull 1-wire bus to high */
DS1820_DelayUs(DS1820_PRESENCE_WAIT);
/* get presence pulse */
bPresPulse = input(DS1820_DATAPIN);
DS1820_DelayUs(424);
DS1820_EnableInterrupts();
return bPresPulse;
}
/*******************************************************************************
* FUNCTION: DS1820_ReadBit
* PURPOSE: Reads a single bit from the DS1820 device.
*
* INPUT: -
* OUTPUT: -
* RETURN: bool value of the bit which as been read form the DS1820
******************************************************************************/
bool DS1820_ReadBit(void)
{
bool bBit;
DS1820_DisableInterrupts();
output_low(DS1820_DATAPIN);
DS1820_DelayUs(DS1820_MSTR_BITSTART);
input(DS1820_DATAPIN);
DS1820_DelayUs(DS1820_BITREAD_DLY);
bBit = input(DS1820_DATAPIN);
DS1820_EnableInterrupts();
return (bBit);
}
/*******************************************************************************
* FUNCTION: DS1820_WriteBit
* PURPOSE: Writes a single bit to the DS1820 device.
*
* INPUT: bBit value of bit to be written
* OUTPUT: -
* RETURN: -
******************************************************************************/
void DS1820_WriteBit(bool bBit)
{
DS1820_DisableInterrupts();
output_low(DS1820_DATAPIN);
DS1820_DelayUs(DS1820_MSTR_BITSTART);
if (bBit != FALSE)
{
output_high(DS1820_DATAPIN);
}
DS1820_DelayUs(DS1820_BITWRITE_DLY);
output_high(DS1820_DATAPIN);
DS1820_EnableInterrupts();
}
/*******************************************************************************
* FUNCTION: DS1820_ReadByte
* PURPOSE: Reads a single byte from the DS1820 device.
*
* INPUT: -
* OUTPUT: -
* RETURN: uint8 byte which has been read from the DS1820
******************************************************************************/
uint8 DS1820_ReadByte(void)
{
uint8 i;
uint8 value = 0;
for (i=0 ; i < 8; i++)
{
if ( DS1820_ReadBit() )
{
value |= (1 << i);
}
DS1820_DelayUs(120);
}
return(value);
}
/*******************************************************************************
* FUNCTION: DS1820_WriteByte
* PURPOSE: Writes a single byte to the DS1820 device.
*
* INPUT: val_u8 byte to be written
* OUTPUT: -
* RETURN: -
******************************************************************************/
void DS1820_WriteByte(uint8 val_u8)
{
uint8 i;
uint8 temp;
for (i=0; i < 8; i++) /* writes byte, one bit at a time */
{
temp = val_u8 >> i; /* shifts val right 'i' spaces */
temp &= 0x01; /* copy that bit to temp */
DS1820_WriteBit(temp); /* write bit in temp into */
}
DS1820_DelayUs(105);
}
/* -------------------------------------------------------------------------- */
/* API Interface */
/* -------------------------------------------------------------------------- */
/*******************************************************************************
* FUNCTION: DS1820_AddrDevice
* PURPOSE: Addresses a single or all devices on the 1-wire bus.
*
* INPUT: nAddrMethod use DS1820_CMD_MATCHROM to select a single
* device or DS1820_CMD_SKIPROM to select all
* OUTPUT: -
* RETURN: -
******************************************************************************/
void DS1820_AddrDevice(uint8 nAddrMethod)
{
uint8 i;
if (nAddrMethod == DS1820_CMD_MATCHROM)
{
DS1820_WriteByte(DS1820_CMD_MATCHROM); /* address single devices on bus */
for (i = 0; i < DS1820_ADDR_LEN; i ++)
{
DS1820_WriteByte(nRomAddr_au8[i]);
}
}
else
{
DS1820_WriteByte(DS1820_CMD_SKIPROM); /* address all devices on bus */
}
}
/*******************************************************************************
* FUNCTION: DS1820_FindNextDevice
* PURPOSE: Finds next device connected to the 1-wire bus.
*
* INPUT: -
* OUTPUT: nRomAddr_au8[] ROM code of the next device
* RETURN: bool TRUE if there are more devices on the 1-wire
* bus, FALSE otherwise
******************************************************************************/
bool DS1820_FindNextDevice(void)
{
uint8 state_u8;
uint8 byteidx_u8;
uint8 mask_u8 = 1;
uint8 bitpos_u8 = 1;
uint8 nDiscrepancyMarker_u8 = 0;
bool bit_b;
bool bStatus;
bool next_b = FALSE;
/* init ROM address */
for (byteidx_u8=0; byteidx_u8 < 8; byteidx_u8 ++)
{
nRomAddr_au8[byteidx_u8] = 0x00;
}
bStatus = DS1820_Reset(); /* reset the 1-wire */
if (bStatus || bDoneFlag) /* no device found */
{
nLastDiscrepancy_u8 = 0; /* reset the search */
return FALSE;
}
/* send search rom command */
DS1820_WriteByte(DS1820_CMD_SEARCHROM);
byteidx_u8 = 0;
do
{
state_u8 = 0;
/* read bit */
if ( DS1820_ReadBit() != 0 )
{
state_u8 = 2;
}
DS1820_DelayUs(120);
/* read bit complement */
if ( DS1820_ReadBit() != 0 )
{
state_u8 |= 1;
}
DS1820_DelayUs(120);
/* description for values of state_u8: */
/* 00 There are devices connected to the bus which have conflicting */
/* bits in the current ROM code bit position. */
/* 01 All devices connected to the bus have a 0 in this bit position. */
/* 10 All devices connected to the bus have a 1 in this bit position. */
/* 11 There are no devices connected to the 1-wire bus. */
/* if there are no devices on the bus */
if (state_u8 == 3)
{
break;
}
else
{
/* devices have the same logical value at this position */
if (state_u8 > 0)
{
/* get bit value */
bit_b = (bool)(state_u8 >> 1);
}
/* devices have confilcting bits in the current ROM code */
else
{
/* if there was a conflict on the last iteration */
if (bitpos_u8 < nLastDiscrepancy_u8)
{
/* take same bit as in last iteration */
bit_b = ( (nRomAddr_au8[byteidx_u8] & mask_u8) > 0 );
}
else
{
bit_b = (bitpos_u8 == nLastDiscrepancy_u8);
}
if (bit_b == 0)
{
nDiscrepancyMarker_u8 = bitpos_u8;
}
}
/* store bit in ROM address */
if (bit_b != 0)
{
nRomAddr_au8[byteidx_u8] |= mask_u8;
}
else
{
nRomAddr_au8[byteidx_u8] &= ~mask_u8;
}
DS1820_WriteBit(bit_b);
/* increment bit position */
bitpos_u8 ++;
/* calculate next mask value */
mask_u8 = mask_u8 << 1;
/* check if this byte has finished */
if (mask_u8 == 0)
{
byteidx_u8 ++; /* advance to next byte of ROM mask */
mask_u8 = 1; /* update mask */
}
}
} while (byteidx_u8 < DS1820_ADDR_LEN);
/* if search was unsuccessful then */
if (bitpos_u8 < 65)
{
/* reset the last discrepancy to 0 */
nLastDiscrepancy_u8 = 0;
}
else
{
/* search was successful */
nLastDiscrepancy_u8 = nDiscrepancyMarker_u8;
bDoneFlag = (nLastDiscrepancy_u8 == 0);
/* indicates search is not complete yet, more parts remain */
next_b = TRUE;
}
return next_b;
}
/*******************************************************************************
* FUNCTION: DS1820_FindFirstDevice
* PURPOSE: Starts the device search on the 1-wire bus.
*
* INPUT: -
* OUTPUT: nRomAddr_au8[] ROM code of the first device
* RETURN: bool TRUE if there are more devices on the 1-wire
* bus, FALSE otherwise
******************************************************************************/
bool DS1820_FindFirstDevice(void)
{
nLastDiscrepancy_u8 = 0;
bDoneFlag = FALSE;
return ( DS1820_FindNextDevice() );
}
/*******************************************************************************
* FUNCTION: DS1820_WriteEEPROM
* PURPOSE: Writes to the DS1820 EEPROM memory (2 bytes available).
*
* INPUT: nTHigh high byte of EEPROM
* nTLow low byte of EEPROM
* OUTPUT: -
* RETURN: -
******************************************************************************/
void DS1820_WriteEEPROM(uint8 nTHigh, uint8 nTLow)
{
/* --- write to scratchpad ----------------------------------------------- */
DS1820_Reset();
DS1820_AddrDevice(DS1820_CMD_MATCHROM);
DS1820_WriteByte(DS1820_CMD_WRITESCRPAD); /* start conversion */
DS1820_WriteByte(nTHigh);
DS1820_WriteByte(nTLow);
DS1820_DelayUs(10);
DS1820_Reset();
DS1820_AddrDevice(DS1820_CMD_MATCHROM);
DS1820_WriteByte(DS1820_CMD_COPYSCRPAD); /* start conversion */
delay_ms(10);
}
/*******************************************************************************
* FUNCTION: DS1820_GetTempRaw
* PURPOSE: Get temperature raw value from single DS1820 device.
*
* Scratchpad Memory Layout
* Byte Register
* 0 Temperature_LSB
* 1 Temperature_MSB
* 2 Temp Alarm High / User Byte 1
* 3 Temp Alarm Low / User Byte 2
* 4 Reserved
* 5 Reserved
* 6 Count_Remain
* 7 Count_per_C
* 8 CRC
*
* Temperature calculation for DS18S20 (Family Code 0x10):
* =======================================================
* (Count_per_C - Count_Remain)
* Temperature = temp_raw - 0.25 + ----------------------------
* Count_per_C
*
* Where temp_raw is the value from the temp_MSB and temp_LSB with
* the least significant bit removed (the 0.5C bit).
*
*
* Temperature calculation for DS18B20 (Family Code 0x28):
* =======================================================
* bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
* LSB 2^3 2^2 2^1 2^0 2^-1 2^-2 2^-3 2^-4
* bit15 bit14 bit13 bit12 bit3 bit2 bit1 bit0
* MSB S S S S S 2^6 2^5 2^4
*
* The temperature data is stored as a 16-bit sign-extended two’s
* complement number in the temperature register. The sign bits (S)
* indicate if the temperature is positive or negative: for
* positive numbers S = 0 and for negative numbers S = 1.
*
* RETURN: sint16 raw temperature value with a resolution
* of 1/256°C
******************************************************************************/
sint16 DS1820_GetTempRaw(void)
{
uint8 i;
uint16 temp_u16;
uint16 highres_u16;
uint8 scrpad[DS1820_SCRPADMEM_LEN];
/* --- start temperature conversion -------------------------------------- */
DS1820_Reset();
DS1820_AddrDevice(DS1820_CMD_MATCHROM); /* address the device */
output_high(DS1820_DATAPIN);
DS1820_WriteByte(DS1820_CMD_CONVERTTEMP); /* start conversion */
//DS1820_DelayMs(DS1820_TEMPCONVERT_DLY); /* wait for temperature conversion */
DS1820_DelayMs(750);
/* --- read sratchpad ---------------------------------------------------- */
DS1820_Reset();
DS1820_AddrDevice(DS1820_CMD_MATCHROM); /* address the device */
DS1820_WriteByte(DS1820_CMD_READSCRPAD); /* read scratch pad */
/* read scratch pad data */
for (i=0; i < DS1820_SCRPADMEM_LEN; i++)
{
scrpad[i] = DS1820_ReadByte();
}
/* --- calculate temperature --------------------------------------------- */
/* Formular for temperature calculation: */
/* Temp = Temp_read - 0.25 + ((Count_per_C - Count_Remain)/Count_per_C) */
/* get raw value of temperature (0.5°C resolution) */
temp_u16 = 0;
temp_u16 = (uint16)((uint16)scrpad[DS1820_REG_TEMPMSB] << 8);
temp_u16 |= (uint16)(scrpad[DS1820_REG_TEMPLSB]);
if (nRomAddr_au8[0] == DS1820_FAMILY_CODE_DS18S20)
{
/* get temperature value in 1°C resolution */
temp_u16 >>= 1;
/* temperature resolution is TEMP_RES (0x100), so 1°C equals 0x100 */
/* => convert to temperature to 1/256°C resolution */
temp_u16 = ((uint16)temp_u16 << 8);
/* now substract 0.25°C */
temp_u16 -= ((uint16)TEMP_RES >> 2);
/* now calculate high resolution */
highres_u16 = scrpad[DS1820_REG_CNTPERSEC] - scrpad[DS1820_REG_CNTREMAIN];
highres_u16 = ((uint16)highres_u16 << 8);
if (scrpad[DS1820_REG_CNTPERSEC])
{
highres_u16 = highres_u16 / (uint16)scrpad[DS1820_REG_CNTPERSEC];
}
/* now calculate result */
highres_u16 = highres_u16 + temp_u16;
}
else
{
/* 12 bit temperature value has 0.0625°C resolution */
/* shift left by 4 to get 1/256°C resolution */
highres_u16 = temp_u16;
highres_u16 <<= 4;
}
return (highres_u16);
}
/*******************************************************************************
* FUNCTION: DS1820_GetTempFloat
* PURPOSE: Converts internal temperature value to string (physical value).
*
* INPUT: none
* OUTPUT: none
* RETURN: float temperature value with as float value
******************************************************************************/
float DS1820_GetTempFloat(void)
{
return ((float)DS1820_GetTempRaw() / (float)TEMP_RES);
}
/*******************************************************************************
* FUNCTION: DS1820_GetTempString
* PURPOSE: Converts internal temperature value to string (physical value).
*
* INPUT: tRaw_s16 internal temperature value
* OUTPUT: strTemp_pc user string buffer to write temperature value
* RETURN: sint16 temperature value with an internal resolution
* of TEMP_RES
******************************************************************************/
void DS1820_GetTempString(sint16 tRaw_s16, char *strTemp_pc)
{
sint16 tPhyLow_s16;
sint8 tPhy_s8;
/* convert from raw value (1/256°C resolution) to physical value */
tPhy_s8 = (sint8)(tRaw_s16/TEMP_RES);
/* convert digits from raw value (1/256°C resolution) to physical value */
/*tPhyLow_u16 = tInt_s16 % TEMP_RES;*/
tPhyLow_s16 = tRaw_s16 & 0xFF; /* this operation is the same as */
/* but saves flash memory tInt_s16 % TEMP_RES */
tPhyLow_s16 = tPhyLow_s16 * 100;
tPhyLow_s16 = (uint16)tPhyLow_s16 / TEMP_RES;
/* write physical temperature value to string */
sprintf(strTemp_pc, "%d.%02d", tPhy_s8, (sint8)tPhyLow_s16);
}
#endif /* _DS1820_H */
#include <main.h>
#define LCD_ENABLE_PIN PIN_B0
#define LCD_RS_PIN PIN_B1
#define LCD_RW_PIN PIN_B2
#define LCD_DATA4 PIN_B4
#define LCD_DATA5 PIN_B5
#define LCD_DATA6 PIN_B6
#define LCD_DATA7 PIN_B7
#include <lcd.c>
//
#include "_inc\types.h"
#define DS1820_DATAPIN PIN_D0
#include "_lib\ds1820.h"
void main()
{
lcd_init ();
lcd_putc ("\fmcu.pinpeo.com\r\n DS1820 Demo ! ");
int16 temperature_raw; /*Du lieu nhiet do (resolution 1 / 256°C) */
float temperature_float; /* Gia tri nhiet do do duoc */
char temperature[8]; /* Mang luu gia tri nhiet do*/
unsigned int8 sensor_count;
delay_ms(1000);
fprintf(UART, "\n\r*** DS1820 Loading...! ***\n\r");
delay_ms(500);
sensor_count = 0;
while (TRUE)
{
if ( DS1820_FindFirstDevice() )
{
do
{
temperature_raw = DS1820_GetTempRaw();
DS1820_GetTempString(temperature_raw, temperature);
temperature_float = DS1820_GetTempFloat();
fprintf(UART, "Sensor %d: %f°C \n\r",
sensor_count,
temperature_float);
sensor_count ++;
}
while ( DS1820_FindNextDevice() );
sensor_count = 0;
}
delay_ms(1000);
}
}
#include <18F4520.h>
#device adc=16
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#use delay(clock=20000000)
#use rs232(UART1, baud=9600, errors,stream=UART)
#include <string.h>
/*** FILEHEADER ****************************************************************
*
* FILENAME: types.h
* DATE: 21.11.2004
* AUTHOR: Christian Stadler
*
* DESCRIPTION: Definition of common types.
*
******************************************************************************/
/*** HISTORY OF CHANGE *********************************************************
*
* $Log: /pic/_inc/types.h $
*
* 3 1.11.10 11:42 Stadler
* - type definitons dependend on compiler
*
* 2 26.02.05 18:44 Stadler
* added bool type
*
******************************************************************************/
#ifndef _TYPES_H
#define _TYPES_H
/*---------------------------------------------------------------------------*/
/* Type definitions for Microchip C18 Compiler */
/*---------------------------------------------------------------------------*/
#if defined(__18CXX)
typedef unsigned char bool;
typedef signed char sint8;
typedef signed int sint16;
typedef signed long sint32;
typedef unsigned char uint8;
typedef unsigned int uint16;
typedef unsigned long uint32;
#endif /* #if defined(__18CXX) */
/*---------------------------------------------------------------------------*/
/* Type definitions for CCS C Compiler */
/*---------------------------------------------------------------------------*/
#if (defined(__PCB__) || defined(__PCH__) || defined(__PCM__))
typedef int1 bool;
typedef signed int8 sint8;
typedef signed int16 sint16;
typedef signed int32 sint32;
typedef unsigned int8 uint8;
typedef unsigned int16 uint16;
typedef unsigned int32 uint32;
#endif /* (defined(__PCB__) || defined(__PCH__) || defined(__PCM__)) */
#endif /*_TYPES_H */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment