Hi all,
The DS18B20 routines are taken from:
http://teslabs.com/openplayer/docs/docs … 0_pre1.pdf
My program is as below:
#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 20000000
#include <util/delay.h>
//prototypes
void DS18b20_read_temperature();
uint8_t reset_1wire_bus();
void DS18b20_write_bit(uint8_t bit);
uint8_t DS18b20_read_bit(void);
uint8_t DS18b20_read_byte(void);
void DS18b20_write_byte(uint8_t byte);
void display_temperature();
//defines
#define DS18b20_cmd_converttemp 0x44
#define DS18b20_cmd_rscratchpad 0xbe
#define DS18b20_cmd_wscratchpad 0x4e
#define DS18b20_cmd_cpyscratchpad 0x48
#define DS18b20_cmd_receeprom 0xb8
#define DS18b20_cmd_rpwrsupply 0xb4
#define DS18b20_cmd_searchrom 0xf0
#define DS18b20_cmd_readrom 0x33
#define DS18b20_cmd_matchrom 0x55
#define DS18b20_cmd_skiprom 0xcc
#define DS18b20_cmd_alarmsearch 0xec
#define DS18b20_decimal_steps_12bit 625
#define SEG_a 0x01
#define SEG_b 0x02
#define SEG_c 0x04
#define SEG_d 0x08
#define SEG_e 0x10
#define SEG_f 0x20
#define SEG_g 0x40
#define SEG_dot 0x80
unsigned char seg={
(SEG_a|SEG_b|SEG_c|SEG_d|SEG_e|SEG_f), // 0
(SEG_b|SEG_c), // 1
(SEG_a|SEG_b|SEG_d|SEG_e|SEG_g), // 2
(SEG_a|SEG_b|SEG_c|SEG_d|SEG_g), // 3
(SEG_b|SEG_c|SEG_c|SEG_f|SEG_g), // 4
(SEG_a|SEG_c|SEG_d|SEG_f|SEG_g), // 5
(SEG_a|SEG_c|SEG_d|SEG_e|SEG_f|SEG_g), // 6
(SEG_a|SEG_b|SEG_c), // 7
(SEG_a|SEG_b|SEG_c|SEG_d|SEG_e|SEG_f|SEG_g), // 8
(SEG_a|SEG_b|SEG_c|SEG_d|SEG_f|SEG_g), // 9
(SEG_a|SEG_d|SEG_e|SEG_f), // 10
};
//global variables
uint8_t digit, decimal, digit_addressed=0;
uint8_t d[7];
void DS18b20_read_temperature()
{
uint8_t temperature[2];
reset_1wire_bus();
DS18b20_write_byte(DS18b20_cmd_skiprom); //0xcc
DS18b20_write_byte(DS18b20_cmd_converttemp); //0x44
while(!DS18b20_read_bit()); DS18B20 will pull bus low until conversion is over
reset_1wire_bus();
DS18b20_write_byte(DS18b20_cmd_skiprom);
DS18b20_write_byte(DS18b20_cmd_rscratchpad);
temperature[0]=DS18b20_read_byte();
temperature[1]=DS18b20_read_byte();
reset_1wire_bus();
digit=temperature[0]>>4;
digit|=(temperature[1]&0x07)<<4;
decimal=temperature[0]&0xf;
decimal*=DS18b20_decimal_steps_12bit;
}
uint8_t reset_1wire_bus()
{ uint8_t i;
PORTD&=~_BV(6); //pull bus to zero
DDRD|=_BV(6); //make sure the PD6 is an output
_delay_us(520); //I’ve choosen to add 10% above the minimum of 480us
DDRD&=~_BV(6); //change bus to read 18b20’s response
_delay_us(80); //bus should be stabilised by 60us
i=(PIND & 0b01000000); //PD6 is read
_delay_us(520-80);
return i; //when i=0, a 18B20 is responding.
}
void DS18b20_write_bit(uint8_t bit)
{
PORTD&=~_BV(6); //bus low required
DDRD|=_BV(6); //change PD6 to work as output
_delay_us(1);
if(bit) DDRD&=~_BV(6); //if we are req’d to write a “one”, just change PD6 to input, the pullup will create the “one” automatically.
_delay_us(69); // tweaking in progress
DDRD&=~_BV(6); //complete the routine by changing PD6 to read.
//my total time = 1+69=70us, minimum is 60us.
}
uint8_t DS18b20_read_bit(void)
{
uint8_t bit=0;
PORTD&=~_BV(6); //will be pulling bus low
DDRD|=_BV(6); //change PD6 to work as output
_delay_us(1); //delay 1us
cli(); //my tweaking
DDRD&=~_BV(6); //get ready to read the coming info
//do not read after 15us
// _delay_us(15);
_delay_us(9); //tweaking — no improvement
if(PIND & 0b01000000) bit=1; //read the bit
_delay_us(70-9-1); //minimum time slot = 60us
sei();
return bit;
}
uint8_t DS18b20_read_byte(void)
{
uint8_t i=8, n=0;
while(i–)
{
n>>=1;
n|=(DS18b20_read_bit()<<7);
}
return n;
}
void DS18b20_write_byte(uint8_t byte)
{
uint8_t i=8;
while(i–)
{
DS18b20_write_bit(byte&1);
byte>>=1;
}
}
ISR(TIMER0_OVF_vect)
{
PORTB = ~(d[digit_addressed]);
switch (digit_addressed)
{
case 0: PORTD=0b11111011;
break;
case 1: PORTD=0b11110111;
break;
case 2: PORTD=0b11101111;
break;
default:PORTD=0b11011111;
}
digit_addressed++;
if(digit_addressed>=4) digit_addressed=0;
}
int main()
{
TCNT0 = 0x00 ;
TCCR0B = 0x04; //prescaler of 256
TIMSK = 0x02; //overflow irq req’d
sei();
PORTD|=_BV(2)|_BV(3)|_BV(4)|_BV(5);
DDRD |=_BV(2)|_BV(3)|_BV(4)|_BV(5);
PORTB=0xff;
DDRB =0xff;
while(1)
{
uint8_t i;
i = reset_1wire_bus();
if(i==0) DS18b20_read_temperature();
else digit=255;
d[4]=digit/100; //digit is updated in the DS18B20_read_temperature();
d[5]=(digit-d[4]*100)/10;
d[6]=digit-d[4]*100-d[5]*10;
d[0]= seg[d[4]];
d[1]= seg[d[5]];
d[2]= seg[d[6]];
d[3]= seg[10];
_delay_ms(30);
}
}