I got my hands on a few of these DS18B20 1-wire digital temperature sensors. They’re really awesome. They’re small, easy to work with, and they run on the 1-wire bus which means they can run on a minimum of two wires. However, I found it easier to just run these devices with 3 lines: +5V, GND, Bus – saves a lot of design complexity.
I found a few good 1-wire drivers for CCS C (especially for these devices):
DS18S20 & DS18B20 Codes
One DS18B20 in powered mode
dallas onewire primitives library and ds1822 driver code
I then took ideas from them and made my own little driver. Some of the code is copied, some of it isn’t. Here it is:
main.c
#include "main.h"
#include "1wire.c"
#include "ds1820.c"
float value = 0.0;
void main() {
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF);
setup_spi(SPI_SS_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_oscillator(OSC_8MHZ);
setup_uart(9600);
delay_ms(1000);
printf("Starting...\t\n");
while(TRUE) {
value = ds1820_read();
printf("%f\t\n", value);
}
}
main.h
#ifndef MAIN_H
#define MAIN_H
#include <16F690.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES INTRC_IO //Internal RC Osc, no CLKOUT
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOMCLR //Master Clear pin used for I/O
#FUSES NOCPD //No EE protection
#FUSES PUT //Power Up Timer
#FUSES IESO //Internal External Switch Over mode enabled
#FUSES FCMEN //Fail-safe clock monitor enabled
#use delay(clock=8000000)
#use rs232(baud=9600, parity=N, UART1, bits=8, stop=1)
#endif /*MAIN_H*/
1wire.c
#ifndef ONE_WIRE_C
#define ONE_WIRE_C
/*
* One wire (1-wire) driver for CCS C compiler. Suitable for use with devices
* such as the DS18B20 1-wire digital temperature sensor.
*/
#define ONE_WIRE_PIN PIN_C5
/*
* onewire_reset()
* Description: Initiates the one wire bus.
*/
// OK if just using a single permanently connected device
void onewire_reset() {
output_low(ONE_WIRE_PIN); // pull the bus low for reset
delay_us(500);
output_float(ONE_WIRE_PIN); // float the bus high
delay_us(500); // wait-out remaining initialisation window
output_float(ONE_WIRE_PIN);
}
/*
* onewire_write(int8 data)
* Arguments: a byte of data.
* Description: writes a byte of data to the device.
*/
void onewire_write(int8 data) {
int8 count;
for(count = 0; count < 8; ++count) {
output_low(ONE_WIRE_PIN);
delay_us(2); // pull 1-wire low to initiate write time-slot.
output_bit(ONE_WIRE_PIN, shift_right(&data, 1, 0)); // set output bit on 1-wire
delay_us(60); // wait until end of write slot.
output_float(ONE_WIRE_PIN); // set 1-wire high again,
delay_us(2); // for more than 1us minimum.
}
}
/*
* onewire_read()
* Description: reads and returns a byte of data from the device.
*/
int onewire_read() {
int count, data;
for(count = 0; count < 8; ++count) {
output_low(ONE_WIRE_PIN);
delay_us(2); // pull 1-wire low to initiate read time-slot.
output_float(ONE_WIRE_PIN); // now let 1-wire float high,
delay_us(8); // let device state stabilise,
shift_right(&data, 1, input(ONE_WIRE_PIN)); // and load result.
delay_us(120); // wait until end of read slot.
}
return data;
}
#endif /*ONE_WIRE_C*/
ds1820.c
#ifndef DS1820_C
#define DS1820_C
#include "1wire.c"
float ds1820_read();
void ds1820_configure(int8 TH, int8 TL, int8 config);
/*
* ds1820_read()
* Description: reads the ds18x20 device on the 1-wire bus and returns
* the temperature
*/
float ds1820_read() {
int8 busy=0, temp1, temp2;
signed int16 temp3;
float result;
//ds1820_configure(0x00, 0x00, 0x00); //9 bit resolution
onewire_reset();
onewire_write(0xCC); //Skip ROM, address all devices
onewire_write(0x44); //Start temperature conversion
while(busy == 0) //Wait while busy (bus is low)
busy = onewire_read();
onewire_reset();
onewire_write(0xCC); //Skip ROM, address all devices
onewire_write(0xBE); //Read scratchpad
temp1 = onewire_read();
temp2 = onewire_read();
temp3 = make16(temp2, temp1);
//result = (float) temp3 / 2.0; //Calculation for DS18S20 with 0.5 deg C resolution
result = (float) temp3 / 16.0; //Calculation for DS18B20
delay_ms(200);
return(result);
}
/*
* ds1820_configure(int8 TH, int8 LH, int8 config)
* Description: writes configuration data to the DS18x20 device
* Arguments: alarm trigger high, alarm trigger low, configuration
*/
void ds1820_configure(int8 TH, int8 TL, int8 config) {
onewire_reset();
onewire_write(0xCC); //Skip ROM, address all devices
onewire_write(0x4E); //Write to scratchpad
onewire_write(TH);
onewire_write(TL);
onewire_write(config);
}
#endif /*DS1820_C*/
All you have to do is set the define to the appropriate pin you’re using for the 1-wire bus. Remember to attach a 4.7k pullup resistor on the bus to VDD. The value of the pullup resistor is not critical. If I remember correctly, I tested resistors anywhere from 1k to 10k and they worked fine. If not, just stick with the 4.7k pullup as recommended in the DS18B20 datasheet.