Hi,
I am using nrf51822 to get DS18B20's temperature data, but I am fail to do it.
Would you please give me an sample C source code which can get temperature data from DS18B20?
Thank you,
Chianglin
Hi,
I am using nrf51822 to get DS18B20's temperature data, but I am fail to do it.
Would you please give me an sample C source code which can get temperature data from DS18B20?
Thank you,
Chianglin
Hi Ives,
Please check out this thread.
Hi Martin,
Thank you for your answer.
I had modify the demo code, and the debug output is:
Power supply: external
Serial got -1:
Got 40959 dCel, 74046 d[Fahr]
Got 40959 dCel, 74046 d[Fahr]
Got 40959 dCel, 74046 d[Fahr]
Got 40959 dCel, 74046 d[Fahr]
About my source code, please find following code:
#include "nrf_gpio.h"
#include "nrf_delay.h"
#include <stdio.h>
/** Structure holding a 1-wire serial number. */
typedef struct sBSPACMonewireSerialNumber
{
/** The serial number in order MSB to LSB */
uint8_t id[6];
} sBSPACMonewireSerialNumber;
enum
{
BSPACM_ONEWIRE_CMD_READ_ROM = 0x33, /** Read 64-bit ROM code without using search procedure */
BSPACM_ONEWIRE_CMD_SKIP_ROM = 0xcc, /** Skip ROM sends the following command to all bus devices */
BSPACM_ONEWIRE_CMD_READ_POWER_SUPPLY = 0xb4, // Determine whether device is parasite-powered or external-powered */
BSPACM_ONEWIRE_CMD_RECALL_EE = 0xb8, /** Store data from EEPROM into RAM */
BSPACM_ONEWIRE_CMD_READ_SCRATCHPAD = 0xbe, /** Read the RAM area. */
BSPACM_ONEWIRE_CMD_CONVERT_T = 0x44, // Initiate a temperature conversion.
/* * Be aware that temperature conversion can take up to 750ms at the
* default 12-bit resolution.
*
* For an externally (non-parasite) powered sensor, the caller may
* use #iBSPACMonewireReadBit_ni to determine whether the conversion
* has completed. Completion is indicated when the device responds
* with a 1. */
};
/** Define protocol state times in microseconds.
*
* @note Since all these times are far less than any sane watchdog
* interval, and the timing can be important, BSPACM_CORE_DELAY_CYCLES
* is not used in this module. */
enum
{
OWT_RSTL_us = 480, /** Minimum time to hold bus low to ensure reset */
OWT_RSTH_us = 480, /** Time to wait for presence detection after reset to quiesce */
OWT_PDHIGH_us = 60, /** Delay before presence pulse is known to be valid (15us..60us) */
OWT_LOW0_us = 60, /** Minimum time to hold bus low when writing a zero */
OWT_LOW1_us = 1, /** Minimum time to hold bus low when writing a one */
OWT_REC_us = 1, /** Recovery delay between write/read transaction cycles */
OWT_INT_us = 1, /** Time to hold bus low when initiating a read slot */
OWT_RDV_us = 15 - OWT_INT_us, /** Point at which read value should be sampled */
OWT_SLOT_us = 60, /** Minimum duration of a read or write slot */
};
#ifndef ONEWIRE_PIN
#define ONEWIRE_PIN 26
#endif /* ONEWIRE_PIN */
#define ONEWIRE_BIT (1ULL << ONEWIRE_PIN)
void dirset (void)
{
NRF_GPIO->DIRSET = ONEWIRE_BIT;
}
void dirclr (void)
{
NRF_GPIO->PIN_CNF[ONEWIRE_PIN] = 0
| (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
| (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos)
| (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos)
| (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos)
| (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos);
}
int iBSPACMonewireReset_ni (void)
{
int present;
#if 1
/* Non-standard: Hold bus high for OWT_RESET_us. This provides
* enough parasitic power for the device to signal presence.
* Without this, effective RSTL duration may exceed the maximum
* 960us before device reset. */
dirset();
NRF_GPIO->OUTSET = ONEWIRE_BIT;
nrf_delay_us(OWT_RSTH_us);
/* Hold bus low for OWT_RESET_us */
NRF_GPIO->OUTCLR = ONEWIRE_BIT;
nrf_delay_us(OWT_RSTL_us);
/* Release bus and switch to input until presence pulse should be
* visible. */
dirclr();
nrf_delay_us(OWT_PDHIGH_us);
/* Record presence if bus is low (DS182x is holding it there) */
present = !(NRF_GPIO->IN & ONEWIRE_BIT);
/* Wait for reset cycle to complete */
nrf_delay_us(OWT_RSTH_us - OWT_PDHIGH_us);
#else
/* Non-standard: Hold bus high for OWT_RESET_us. This provides
* enough parasitic power for the device to signal presence.
* Without this, effective RSTL duration may exceed the maximum
* 960us before device reset. */
nrf_gpio_cfg_output(ONEWIRE_PIN);
nrf_gpio_pin_set(ONEWIRE_PIN);
nrf_delay_us(OWT_RSTH_us);
/* Hold bus low for OWT_RESET_us */
nrf_gpio_pin_clear(ONEWIRE_PIN);
nrf_delay_us(OWT_RSTL_us);
nrf_gpio_cfg_input(ONEWIRE_PIN, NRF_GPIO_PIN_NOPULL); // Release bus and switch to input until presence pulse should be visible.
nrf_delay_us(OWT_PDHIGH_us);
/* Record presence if bus is low (DS182x is holding it there) */
present = !(nrf_gpio_pin_read(ONEWIRE_PIN));
#endif
/* Wait for reset cycle to complete */
nrf_delay_us(OWT_RSTH_us - OWT_PDHIGH_us);
return present;
}
void vBSPACMonewireShutdown_ni (void)
{
NRF_GPIO->OUTCLR = ONEWIRE_BIT;
dirclr();
}
void vBSPACMonewireWriteByte_ni (int byte)
{
int bp;
for (bp = 0; bp < 8; ++bp)
{
NRF_GPIO->OUTCLR = ONEWIRE_BIT;
dirset();
if (byte & 0x01) {
nrf_delay_us(OWT_LOW1_us);
dirclr();
nrf_delay_us(OWT_SLOT_us - OWT_LOW1_us + OWT_REC_us);
} else {
nrf_delay_us(OWT_LOW0_us);
dirclr();
nrf_delay_us(OWT_SLOT_us - OWT_LOW0_us + OWT_REC_us);
}
byte >>= 1;
}
}
int iBSPACMonewireReadBit_ni (void)
{
int rv;
NRF_GPIO->OUTCLR = ONEWIRE_BIT;
dirset();
nrf_delay_us(OWT_INT_us);
dirclr();
nrf_delay_us(OWT_RDV_us);
//abc vBSPACMledSet(0, 1);
rv = !!(NRF_GPIO->IN & ONEWIRE_BIT);
//abc vBSPACMledSet(0, 0);
nrf_delay_us(OWT_SLOT_us - OWT_RDV_us - OWT_INT_us + OWT_REC_us);
return rv;
}
int iBSPACMonewireReadByte_ni (void)
{
int byte = 0;
int bit = 1;
do {
if (iBSPACMonewireReadBit_ni()) {
byte |= bit;
}
bit <<= 1;
} while (0x100 != bit);
return byte;
}
int iBSPACMonewireComputeCRC(const unsigned char * romp, int len)
{
static const unsigned char OW_CRC_POLY = 0x8c;
unsigned char crc = 0;
while (0 < len--) {
int bi;
crc ^= *romp++;
for (bi = 0; bi < 8; ++bi) {
if (crc & 1) {
crc = (crc >> 1) ^ OW_CRC_POLY;
} else {
crc >>= 1;
}
}
}
return crc;
}
int iBSPACMonewireReadSerialNumber (sBSPACMonewireSerialNumber * snp)
{
uint8_t rom[8];
int i;
int rv = -1;
do {
if (! iBSPACMonewireReset_ni()) {
break;
}
vBSPACMonewireWriteByte_ni(BSPACM_ONEWIRE_CMD_READ_ROM);
for (i = 0; i < sizeof(rom); ++i) {
rom[i] = iBSPACMonewireReadByte_ni();
}
rv = 0;
} while (0);
if (0 == rv) {
if (0 != iBSPACMonewireComputeCRC(rom, sizeof(rom))) {
rv = -1;
} else {
for (i = 0; i < sizeof(snp->id); ++i) {
snp->id[i] = rom[sizeof(rom) - 2 - i];
}
}
}
return rv;
}
int iBSPACMonewireRequestTemperature_ni (void)
{
if (! iBSPACMonewireReset_ni()) {
return -1;
}
vBSPACMonewireWriteByte_ni(BSPACM_ONEWIRE_CMD_SKIP_ROM);
vBSPACMonewireWriteByte_ni(BSPACM_ONEWIRE_CMD_CONVERT_T);
return 0;
}
int iBSPACMonewireReadPowerSupply (void)
{
int rv = -1;
if (iBSPACMonewireReset_ni())
{
vBSPACMonewireWriteByte_ni(BSPACM_ONEWIRE_CMD_SKIP_ROM);
vBSPACMonewireWriteByte_ni(BSPACM_ONEWIRE_CMD_READ_POWER_SUPPLY);
rv = iBSPACMonewireReadBit_ni();
}
return rv;
}
int iBSPACMonewireReadTemperature_ni (int * temp_xCel)
{
int t;
if (! iBSPACMonewireReset_ni()) {
return -1;
}
vBSPACMonewireWriteByte_ni(BSPACM_ONEWIRE_CMD_SKIP_ROM);
vBSPACMonewireWriteByte_ni(BSPACM_ONEWIRE_CMD_READ_SCRATCHPAD);
t = iBSPACMonewireReadByte_ni();
t |= (iBSPACMonewireReadByte_ni() << 8);
*temp_xCel = t;
return 0;
}
void DS18B20_Run(void)
{
do
{
if (! iBSPACMonewireReset_ni()) {
printf("ERR: No DS18B20 present on P0.%u\n", ONEWIRE_PIN);
break;
}
static const char * const supply_type[] = { "parasitic", "external" };
int external_power = iBSPACMonewireReadPowerSupply();
printf("Power supply: %s\r\n", supply_type[external_power]);
if (0 > external_power) {
printf("ERROR: Device not present?\r\n");
break;
}
sBSPACMonewireSerialNumber serial;
int rc = iBSPACMonewireReadSerialNumber(&serial);
printf("Serial got %d: \r\n", rc);
//abc vBSPACMconsoleDisplayOctets(serial.id, sizeof(serial.id));
//abc putchar('\n');
#if 1
while (0 == iBSPACMonewireRequestTemperature_ni())
{
int t_raw;
nrf_delay_ms(600UL);
while (! iBSPACMonewireReadBit_ni()) {
}
rc = iBSPACMonewireReadTemperature_ni(&t_raw);
int t_dCel = (10 * t_raw) / 16;
int t_dFahr = 320 + (9 * t_dCel) / 5;
printf("Got %d dCel, %d d[Fahr]\r\n", t_dCel, t_dFahr);
}
#endif
} while (0);
dirset();
NRF_GPIO->OUTCLR = ONEWIRE_BIT;
}
Would you please tell me how can I modify my code?
Thank you
Hi Martin,
Thank you for your answer.
I had modify the demo code, and the debug output is:
Power supply: external
Serial got -1:
Got 40959 dCel, 74046 d[Fahr]
Got 40959 dCel, 74046 d[Fahr]
Got 40959 dCel, 74046 d[Fahr]
Got 40959 dCel, 74046 d[Fahr]
About my source code, please find following code:
#include "nrf_gpio.h"
#include "nrf_delay.h"
#include <stdio.h>
/** Structure holding a 1-wire serial number. */
typedef struct sBSPACMonewireSerialNumber
{
/** The serial number in order MSB to LSB */
uint8_t id[6];
} sBSPACMonewireSerialNumber;
enum
{
BSPACM_ONEWIRE_CMD_READ_ROM = 0x33, /** Read 64-bit ROM code without using search procedure */
BSPACM_ONEWIRE_CMD_SKIP_ROM = 0xcc, /** Skip ROM sends the following command to all bus devices */
BSPACM_ONEWIRE_CMD_READ_POWER_SUPPLY = 0xb4, // Determine whether device is parasite-powered or external-powered */
BSPACM_ONEWIRE_CMD_RECALL_EE = 0xb8, /** Store data from EEPROM into RAM */
BSPACM_ONEWIRE_CMD_READ_SCRATCHPAD = 0xbe, /** Read the RAM area. */
BSPACM_ONEWIRE_CMD_CONVERT_T = 0x44, // Initiate a temperature conversion.
/* * Be aware that temperature conversion can take up to 750ms at the
* default 12-bit resolution.
*
* For an externally (non-parasite) powered sensor, the caller may
* use #iBSPACMonewireReadBit_ni to determine whether the conversion
* has completed. Completion is indicated when the device responds
* with a 1. */
};
/** Define protocol state times in microseconds.
*
* @note Since all these times are far less than any sane watchdog
* interval, and the timing can be important, BSPACM_CORE_DELAY_CYCLES
* is not used in this module. */
enum
{
OWT_RSTL_us = 480, /** Minimum time to hold bus low to ensure reset */
OWT_RSTH_us = 480, /** Time to wait for presence detection after reset to quiesce */
OWT_PDHIGH_us = 60, /** Delay before presence pulse is known to be valid (15us..60us) */
OWT_LOW0_us = 60, /** Minimum time to hold bus low when writing a zero */
OWT_LOW1_us = 1, /** Minimum time to hold bus low when writing a one */
OWT_REC_us = 1, /** Recovery delay between write/read transaction cycles */
OWT_INT_us = 1, /** Time to hold bus low when initiating a read slot */
OWT_RDV_us = 15 - OWT_INT_us, /** Point at which read value should be sampled */
OWT_SLOT_us = 60, /** Minimum duration of a read or write slot */
};
#ifndef ONEWIRE_PIN
#define ONEWIRE_PIN 26
#endif /* ONEWIRE_PIN */
#define ONEWIRE_BIT (1ULL << ONEWIRE_PIN)
void dirset (void)
{
NRF_GPIO->DIRSET = ONEWIRE_BIT;
}
void dirclr (void)
{
NRF_GPIO->PIN_CNF[ONEWIRE_PIN] = 0
| (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
| (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos)
| (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos)
| (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos)
| (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos);
}
int iBSPACMonewireReset_ni (void)
{
int present;
#if 1
/* Non-standard: Hold bus high for OWT_RESET_us. This provides
* enough parasitic power for the device to signal presence.
* Without this, effective RSTL duration may exceed the maximum
* 960us before device reset. */
dirset();
NRF_GPIO->OUTSET = ONEWIRE_BIT;
nrf_delay_us(OWT_RSTH_us);
/* Hold bus low for OWT_RESET_us */
NRF_GPIO->OUTCLR = ONEWIRE_BIT;
nrf_delay_us(OWT_RSTL_us);
/* Release bus and switch to input until presence pulse should be
* visible. */
dirclr();
nrf_delay_us(OWT_PDHIGH_us);
/* Record presence if bus is low (DS182x is holding it there) */
present = !(NRF_GPIO->IN & ONEWIRE_BIT);
/* Wait for reset cycle to complete */
nrf_delay_us(OWT_RSTH_us - OWT_PDHIGH_us);
#else
/* Non-standard: Hold bus high for OWT_RESET_us. This provides
* enough parasitic power for the device to signal presence.
* Without this, effective RSTL duration may exceed the maximum
* 960us before device reset. */
nrf_gpio_cfg_output(ONEWIRE_PIN);
nrf_gpio_pin_set(ONEWIRE_PIN);
nrf_delay_us(OWT_RSTH_us);
/* Hold bus low for OWT_RESET_us */
nrf_gpio_pin_clear(ONEWIRE_PIN);
nrf_delay_us(OWT_RSTL_us);
nrf_gpio_cfg_input(ONEWIRE_PIN, NRF_GPIO_PIN_NOPULL); // Release bus and switch to input until presence pulse should be visible.
nrf_delay_us(OWT_PDHIGH_us);
/* Record presence if bus is low (DS182x is holding it there) */
present = !(nrf_gpio_pin_read(ONEWIRE_PIN));
#endif
/* Wait for reset cycle to complete */
nrf_delay_us(OWT_RSTH_us - OWT_PDHIGH_us);
return present;
}
void vBSPACMonewireShutdown_ni (void)
{
NRF_GPIO->OUTCLR = ONEWIRE_BIT;
dirclr();
}
void vBSPACMonewireWriteByte_ni (int byte)
{
int bp;
for (bp = 0; bp < 8; ++bp)
{
NRF_GPIO->OUTCLR = ONEWIRE_BIT;
dirset();
if (byte & 0x01) {
nrf_delay_us(OWT_LOW1_us);
dirclr();
nrf_delay_us(OWT_SLOT_us - OWT_LOW1_us + OWT_REC_us);
} else {
nrf_delay_us(OWT_LOW0_us);
dirclr();
nrf_delay_us(OWT_SLOT_us - OWT_LOW0_us + OWT_REC_us);
}
byte >>= 1;
}
}
int iBSPACMonewireReadBit_ni (void)
{
int rv;
NRF_GPIO->OUTCLR = ONEWIRE_BIT;
dirset();
nrf_delay_us(OWT_INT_us);
dirclr();
nrf_delay_us(OWT_RDV_us);
//abc vBSPACMledSet(0, 1);
rv = !!(NRF_GPIO->IN & ONEWIRE_BIT);
//abc vBSPACMledSet(0, 0);
nrf_delay_us(OWT_SLOT_us - OWT_RDV_us - OWT_INT_us + OWT_REC_us);
return rv;
}
int iBSPACMonewireReadByte_ni (void)
{
int byte = 0;
int bit = 1;
do {
if (iBSPACMonewireReadBit_ni()) {
byte |= bit;
}
bit <<= 1;
} while (0x100 != bit);
return byte;
}
int iBSPACMonewireComputeCRC(const unsigned char * romp, int len)
{
static const unsigned char OW_CRC_POLY = 0x8c;
unsigned char crc = 0;
while (0 < len--) {
int bi;
crc ^= *romp++;
for (bi = 0; bi < 8; ++bi) {
if (crc & 1) {
crc = (crc >> 1) ^ OW_CRC_POLY;
} else {
crc >>= 1;
}
}
}
return crc;
}
int iBSPACMonewireReadSerialNumber (sBSPACMonewireSerialNumber * snp)
{
uint8_t rom[8];
int i;
int rv = -1;
do {
if (! iBSPACMonewireReset_ni()) {
break;
}
vBSPACMonewireWriteByte_ni(BSPACM_ONEWIRE_CMD_READ_ROM);
for (i = 0; i < sizeof(rom); ++i) {
rom[i] = iBSPACMonewireReadByte_ni();
}
rv = 0;
} while (0);
if (0 == rv) {
if (0 != iBSPACMonewireComputeCRC(rom, sizeof(rom))) {
rv = -1;
} else {
for (i = 0; i < sizeof(snp->id); ++i) {
snp->id[i] = rom[sizeof(rom) - 2 - i];
}
}
}
return rv;
}
int iBSPACMonewireRequestTemperature_ni (void)
{
if (! iBSPACMonewireReset_ni()) {
return -1;
}
vBSPACMonewireWriteByte_ni(BSPACM_ONEWIRE_CMD_SKIP_ROM);
vBSPACMonewireWriteByte_ni(BSPACM_ONEWIRE_CMD_CONVERT_T);
return 0;
}
int iBSPACMonewireReadPowerSupply (void)
{
int rv = -1;
if (iBSPACMonewireReset_ni())
{
vBSPACMonewireWriteByte_ni(BSPACM_ONEWIRE_CMD_SKIP_ROM);
vBSPACMonewireWriteByte_ni(BSPACM_ONEWIRE_CMD_READ_POWER_SUPPLY);
rv = iBSPACMonewireReadBit_ni();
}
return rv;
}
int iBSPACMonewireReadTemperature_ni (int * temp_xCel)
{
int t;
if (! iBSPACMonewireReset_ni()) {
return -1;
}
vBSPACMonewireWriteByte_ni(BSPACM_ONEWIRE_CMD_SKIP_ROM);
vBSPACMonewireWriteByte_ni(BSPACM_ONEWIRE_CMD_READ_SCRATCHPAD);
t = iBSPACMonewireReadByte_ni();
t |= (iBSPACMonewireReadByte_ni() << 8);
*temp_xCel = t;
return 0;
}
void DS18B20_Run(void)
{
do
{
if (! iBSPACMonewireReset_ni()) {
printf("ERR: No DS18B20 present on P0.%u\n", ONEWIRE_PIN);
break;
}
static const char * const supply_type[] = { "parasitic", "external" };
int external_power = iBSPACMonewireReadPowerSupply();
printf("Power supply: %s\r\n", supply_type[external_power]);
if (0 > external_power) {
printf("ERROR: Device not present?\r\n");
break;
}
sBSPACMonewireSerialNumber serial;
int rc = iBSPACMonewireReadSerialNumber(&serial);
printf("Serial got %d: \r\n", rc);
//abc vBSPACMconsoleDisplayOctets(serial.id, sizeof(serial.id));
//abc putchar('\n');
#if 1
while (0 == iBSPACMonewireRequestTemperature_ni())
{
int t_raw;
nrf_delay_ms(600UL);
while (! iBSPACMonewireReadBit_ni()) {
}
rc = iBSPACMonewireReadTemperature_ni(&t_raw);
int t_dCel = (10 * t_raw) / 16;
int t_dFahr = 320 + (9 * t_dCel) / 5;
printf("Got %d dCel, %d d[Fahr]\r\n", t_dCel, t_dFahr);
}
#endif
} while (0);
dirset();
NRF_GPIO->OUTCLR = ONEWIRE_BIT;
}
Would you please tell me how can I modify my code?
Thank you
Hi Ives,
What SDK version are you running on?
could you send over the whole project so I could recreate it on my desk?
Hi Martin,
My SDK is nRF5_SDK_12.3.0_d7731ad and I am use nrf51822 MCU.
`Please find the attach file for my full project. Please un-compress the 7z file into ./example/peripheral directory.
Thank you,
Chianglin
Here we are not checking the CRC check calculated from the scratchpad and the one calculated from rom.
Do we require to do so if yes then how