I am implementing my own SW for getting data from DS18B20, but I've been stuck on decoding address for a while - "receiving" only zeros as a result. Here is my code:
#include <avr/io.h>
#include "DS18B20_driver.h"
#include <util/delay.h>
#include "debug_uart.h" //delete
#include <stdio.h> //delete
//High_level_funcitons
void dallas_get_address(uint8_t* address){
reset_pulse();
_delay_ms(2);
write_byte(0x33); //READ ROM command;
read_rom(address);
uart_send_string("Dallas address is: \n");
for(int j = 0; j < 8; j++){
char buffer[3];
sprintf(buffer, "%02X", address[j]);
uart_send_string(buffer);
}
uart_send_string(" \n");
}
//Mid_high_level_functions
void read_rom(uint8_t* address){
for(int j = 0; j < 8; j++){
address[j] = read_byte();
}
}
//Mid_low_level_functions
void write_byte(uint8_t byte_value){
for(int j = 0; j < 8; j++){
_delay_us(1); //1 us between write cycles
if(byte_value & 0x01){ //if bit is high in first position
write_bit_high();
}
else{
write_bit_low();
}
byte_value >>= 1; //shifting byte by one position
}
}
uint8_t read_byte(){
uint8_t received_byte = 0; //Clearing variables
uint8_t received_bit = 0;
for(int j = 0; j < 8; j++){
received_bit = read_bit();
received_byte |= (received_bit << j);
}
return received_byte;
}
//Low_level_functions
void write_bit_high(){
DDRX |= (1 << PXX);
PORTX &= ~(1 << PXX);
_delay_us(10);
PORTX |= (1 << PXX);
_delay_us(55); // 45us + 3us recovery, then it stays in 5V state
DDRX &= ~(1 << PXX);
}
void write_bit_low(){
DDRX |= (1 << PXX);
PORTX &= ~(1 << PXX);
_delay_us(65);
PORTX |= (1 << PXX);
_delay_us(5); //3us recovery, then it stays in 5V state
DDRX &= ~(1 << PXX);
}
uint8_t read_bit(){
DDRX |= (1 << PXX);
PORTX &= ~(1 << PXX);
_delay_us(3);
DDRX &= ~(1 << PXX);
//PORTX &= ~(1 << PXX);
//PORTX |= (1 << PXX);
_delay_us(10); //15us recovery
if(PINX & (1 << PXX)){
_delay_us(53); //rest of transmission interval
return 1; //returns 0b00000001
}
else{
_delay_us(53);
return 0; //returns 0b00000000
}
}
int reset_pulse(){
DDRX |= (1 << PXX);
PORTX &= ~(1 << PXX); //Master transmitts reset pulse, by pulling low
_delay_us(480); //480-720us
PORTX |= (1 << PXX);
DDRX &= ~(1 << PXX);
_delay_us(70);
if(!(PINX & (1 << PXX))){
uart_send_string("Response was successfull!\n");
return 1;
}
else{
_delay_us(100);
if(!(PINX & (1 << PXX))){
uart_send_string("Response was successfull!\n");
return 1;
}
else{
uart_send_string("Sensor/s is/are not responding!\n");
return 0;
}
}
}
What've done:
different pulses timing different Dallas sensors disconnecting/connecting sensor - reset pulse/presence pulse works fine.
Output I get:
Response was successfull!
Dallas address is:
0000000000000000
when Dallas is connected
Sensor/s is/are not responding!
Dallas address is:
0000000000000000
when Dallas is disconnected
Mybe I'm doing some dumb mistake I can't see because I am fairly new selftougth embedded developer.
Thank you in advance for your replies and advices.
dallas_get_address()is called, a minimal reproducible example.uart_send_string()blocking or non-blocking? Even if it is non-blocking, copying data to buffer introduces delays. If your firmware uses interrupts, they also may introduce delays.dallas_get_addresswould from a design point of view be better performed by the caller ofdallas_get_address, which should return a status. Similarly forreset_pulse, use the return status to test, and exit fromdallas_get_addresswith a failure status. Wit respect to your problem, are you certain this code is producing accurate timing? Without knowing what processor this is running on, and at what speed, and how the delay functions are implemented, it is not possible to tell from the code. I would not attempt my own 1-Wire code without a scope to verify it.c uint8_t address_1[8]; dallas_get_address(address_1); _delay_ms(1000);