feat: add rom search method for ds18b20
This commit is contained in:
parent
aa65f9556f
commit
43424ca5be
@ -1,168 +0,0 @@
|
||||
// Copyright 2021 IOsetting <iosetting(at)outlook.com>
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "ds18b20.h"
|
||||
|
||||
void DS18B20_Init(void)
|
||||
{
|
||||
DS18B20_DQ_PULLUP();
|
||||
DS18B20_DQ_OUTPUT();
|
||||
DS18B20_DQ = SET;
|
||||
SYS_DelayUs(1000);
|
||||
DS18B20_DQ = RESET;
|
||||
SYS_DelayUs(1000);
|
||||
DS18B20_DQ = SET;
|
||||
SYS_DelayUs(2000);
|
||||
}
|
||||
|
||||
__BIT DS18B20_Reset(void)
|
||||
{
|
||||
__BIT b;
|
||||
|
||||
/* Line low, and wait 480us */
|
||||
DS18B20_DQ = RESET;
|
||||
DS18B20_DQ_OUTPUT();
|
||||
SYS_DelayUs(500);
|
||||
/* Release line and wait for 70us */
|
||||
DS18B20_DQ_INPUT();
|
||||
SYS_DelayUs(70);
|
||||
/* Check bit value, success if low */
|
||||
b = DS18B20_DQ;
|
||||
/* Delay for 410 us */
|
||||
SYS_DelayUs(410);
|
||||
/* Return value of presence pulse, 0 = OK, 1 = ERROR */
|
||||
return b;
|
||||
}
|
||||
|
||||
__BIT DS18B20_ReadBit(void)
|
||||
{
|
||||
__BIT b = RESET;
|
||||
|
||||
/* Line low */
|
||||
DS18B20_DQ = RESET;
|
||||
DS18B20_DQ_OUTPUT();
|
||||
SYS_DelayUs(2);
|
||||
|
||||
/* Release line */
|
||||
DS18B20_DQ_INPUT();
|
||||
SYS_DelayUs(10);
|
||||
|
||||
/* Read line value */
|
||||
if (DS18B20_DQ) {
|
||||
/* Bit is HIGH */
|
||||
b = SET;
|
||||
}
|
||||
|
||||
/* Wait 50us to complete 60us period */
|
||||
SYS_DelayUs(50);
|
||||
|
||||
/* Return bit value */
|
||||
return b;
|
||||
}
|
||||
|
||||
uint8_t DS18B20_ReadByte(void)
|
||||
{
|
||||
uint8_t i = 8, byte = 0;
|
||||
while (i--)
|
||||
{
|
||||
byte >>= 1;
|
||||
byte |= (DS18B20_ReadBit() << 7);
|
||||
}
|
||||
return byte;
|
||||
}
|
||||
|
||||
void DS18B20_WriteBit(__BIT b)
|
||||
{
|
||||
if (b)
|
||||
{
|
||||
/* Set line low */
|
||||
DS18B20_DQ = RESET;
|
||||
DS18B20_DQ_OUTPUT();
|
||||
SYS_DelayUs(10);
|
||||
|
||||
/* Bit high */
|
||||
DS18B20_DQ_INPUT();
|
||||
|
||||
/* Wait for 55 us and release the line */
|
||||
SYS_DelayUs(55);
|
||||
DS18B20_DQ_INPUT();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set line low */
|
||||
DS18B20_DQ = RESET;
|
||||
DS18B20_DQ_OUTPUT();
|
||||
SYS_DelayUs(65);
|
||||
|
||||
/* Bit high */
|
||||
DS18B20_DQ_INPUT();
|
||||
|
||||
/* Wait for 5 us and release the line */
|
||||
SYS_DelayUs(5);
|
||||
DS18B20_DQ_INPUT();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void DS18B20_WriteByte(uint8_t byte)
|
||||
{
|
||||
uint8_t i = 8;
|
||||
/* Write 8 bits */
|
||||
while (i--)
|
||||
{
|
||||
/* LSB bit is first */
|
||||
DS18B20_WriteBit(byte & 0x01);
|
||||
byte >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
void DS18B20_StartAll(void)
|
||||
{
|
||||
/* Reset pulse */
|
||||
DS18B20_Reset();
|
||||
/* Skip rom */
|
||||
DS18B20_WriteByte(ONEWIRE_CMD_SKIPROM);
|
||||
/* Start conversion on all connected devices */
|
||||
DS18B20_WriteByte(DS18B20_CMD_CONVERTTEMP);
|
||||
}
|
||||
|
||||
__BIT DS18B20_AllDone(void)
|
||||
{
|
||||
/* If read bit is low, then device is not finished yet with calculation temperature */
|
||||
return DS18B20_ReadBit();
|
||||
}
|
||||
|
||||
uint16_t DS18B20_ReadTemperature(void)
|
||||
{
|
||||
uint16_t temperature;
|
||||
uint8_t i = 0;
|
||||
uint8_t data[9];
|
||||
|
||||
/* Reset line */
|
||||
DS18B20_Reset();
|
||||
/* Skip ROM */
|
||||
DS18B20_WriteByte(ONEWIRE_CMD_SKIPROM);
|
||||
/* Read scratchpad command by onewire protocol */
|
||||
DS18B20_WriteByte(ONEWIRE_CMD_RSCRATCHPAD);
|
||||
|
||||
/* Get data */
|
||||
for (i = 0; i < 9; i++)
|
||||
{
|
||||
/* Read byte by byte */
|
||||
data[i] = DS18B20_ReadByte();
|
||||
}
|
||||
temperature = data[1];
|
||||
temperature = temperature << 8 | data[0];
|
||||
return temperature;
|
||||
}
|
301
demo/gpio/ds18b20/multiple-ds18b20/ds18b20.c
Normal file
301
demo/gpio/ds18b20/multiple-ds18b20/ds18b20.c
Normal file
@ -0,0 +1,301 @@
|
||||
// Copyright 2021 IOsetting <iosetting(at)outlook.com>
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "ds18b20.h"
|
||||
|
||||
void DS18B20_Init(void)
|
||||
{
|
||||
DS18B20_DQ_PULLUP();
|
||||
DS18B20_DQ_OUTPUT();
|
||||
DS18B20_DQ = SET;
|
||||
SYS_DelayUs(1000);
|
||||
DS18B20_DQ = RESET;
|
||||
SYS_DelayUs(1000);
|
||||
DS18B20_DQ = SET;
|
||||
SYS_DelayUs(2000);
|
||||
}
|
||||
|
||||
__BIT DS18B20_Reset(void)
|
||||
{
|
||||
__BIT b;
|
||||
|
||||
/* Line low, and wait 480us */
|
||||
DS18B20_DQ = RESET;
|
||||
DS18B20_DQ_OUTPUT();
|
||||
SYS_DelayUs(500);
|
||||
/* Release line and wait for 70us */
|
||||
DS18B20_DQ_INPUT();
|
||||
SYS_DelayUs(70);
|
||||
/* Check bit value, success if low */
|
||||
b = DS18B20_DQ;
|
||||
/* Delay for 410 us */
|
||||
SYS_DelayUs(410);
|
||||
/* Return value of presence pulse, 0 = OK, 1 = ERROR */
|
||||
return b;
|
||||
}
|
||||
|
||||
__BIT DS18B20_ReadBit(void)
|
||||
{
|
||||
__BIT b = RESET;
|
||||
|
||||
/* Line low */
|
||||
DS18B20_DQ = RESET;
|
||||
DS18B20_DQ_OUTPUT();
|
||||
SYS_DelayUs(2);
|
||||
|
||||
/* Release line */
|
||||
DS18B20_DQ_INPUT();
|
||||
SYS_DelayUs(10);
|
||||
|
||||
/* Read line value */
|
||||
if (DS18B20_DQ) {
|
||||
/* Bit is HIGH */
|
||||
b = SET;
|
||||
}
|
||||
|
||||
/* Wait 50us to complete 60us period */
|
||||
SYS_DelayUs(50);
|
||||
|
||||
/* Return bit value */
|
||||
return b;
|
||||
}
|
||||
|
||||
uint8_t DS18B20_ReadByte(void)
|
||||
{
|
||||
uint8_t i = 8, byte = 0;
|
||||
while (i--)
|
||||
{
|
||||
byte >>= 1;
|
||||
byte |= (DS18B20_ReadBit() << 7);
|
||||
}
|
||||
return byte;
|
||||
}
|
||||
|
||||
void DS18B20_WriteBit(__BIT b)
|
||||
{
|
||||
if (b)
|
||||
{
|
||||
/* Set line low */
|
||||
DS18B20_DQ = RESET;
|
||||
DS18B20_DQ_OUTPUT();
|
||||
SYS_DelayUs(10);
|
||||
|
||||
/* Bit high */
|
||||
DS18B20_DQ_INPUT();
|
||||
|
||||
/* Wait for 55 us and release the line */
|
||||
SYS_DelayUs(55);
|
||||
DS18B20_DQ_INPUT();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set line low */
|
||||
DS18B20_DQ = RESET;
|
||||
DS18B20_DQ_OUTPUT();
|
||||
SYS_DelayUs(65);
|
||||
|
||||
/* Bit high */
|
||||
DS18B20_DQ_INPUT();
|
||||
|
||||
/* Wait for 5 us and release the line */
|
||||
SYS_DelayUs(5);
|
||||
DS18B20_DQ_INPUT();
|
||||
}
|
||||
}
|
||||
|
||||
void DS18B20_WriteByte(uint8_t byte)
|
||||
{
|
||||
uint8_t i = 8;
|
||||
/* Write 8 bits */
|
||||
while (i--)
|
||||
{
|
||||
/* LSB bit is first */
|
||||
DS18B20_WriteBit(byte & 0x01);
|
||||
byte >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
void DS18B20_ReadScratchpad(uint8_t *buf)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
/* Reset line */
|
||||
DS18B20_Reset();
|
||||
/* Skip ROM */
|
||||
DS18B20_WriteByte(ONEWIRE_CMD_SKIPROM);
|
||||
/* Read scratchpad command by onewire protocol */
|
||||
DS18B20_WriteByte(ONEWIRE_CMD_RSCRATCHPAD);
|
||||
|
||||
/* Get data */
|
||||
for (i = 0; i < 9; i++)
|
||||
{
|
||||
/* Read byte by byte */
|
||||
*buf++ = DS18B20_ReadByte();
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t DS18B20_Crc(uint8_t *addr, uint8_t len)
|
||||
{
|
||||
uint8_t crc = 0, inbyte, i, mix;
|
||||
|
||||
while (len--)
|
||||
{
|
||||
inbyte = *addr++;
|
||||
for (i = 8; i; i--)
|
||||
{
|
||||
mix = (crc ^ inbyte) & 0x01;
|
||||
crc >>= 1;
|
||||
if (mix)
|
||||
{
|
||||
crc ^= 0x8C;
|
||||
}
|
||||
inbyte >>= 1;
|
||||
}
|
||||
}
|
||||
/* Return calculated CRC */
|
||||
return crc;
|
||||
}
|
||||
|
||||
void DS18B20_StartAll(void)
|
||||
{
|
||||
/* Reset pulse */
|
||||
DS18B20_Reset();
|
||||
/* Skip rom */
|
||||
DS18B20_WriteByte(ONEWIRE_CMD_SKIPROM);
|
||||
/* Start conversion on all connected devices */
|
||||
DS18B20_WriteByte(DS18B20_CMD_CONVERTTEMP);
|
||||
}
|
||||
|
||||
__BIT DS18B20_AllDone(void)
|
||||
{
|
||||
/* If read bit is low, then device is not finished yet with calculation temperature */
|
||||
return DS18B20_ReadBit();
|
||||
}
|
||||
|
||||
void DS18B20_ReadRom(uint8_t *buf)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
/* Reset pulse */
|
||||
DS18B20_Reset();
|
||||
/* Read rom */
|
||||
DS18B20_WriteByte(ONEWIRE_CMD_READROM);
|
||||
/* Get data */
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
/* Read byte by byte */
|
||||
*buf++ = DS18B20_ReadByte();
|
||||
}
|
||||
}
|
||||
|
||||
void DS18B20_Select(const uint8_t* addr)
|
||||
{
|
||||
uint8_t len = 8;
|
||||
DS18B20_WriteByte(ONEWIRE_CMD_MATCHROM);
|
||||
while (len--)
|
||||
{
|
||||
DS18B20_WriteByte(*addr++);
|
||||
}
|
||||
}
|
||||
|
||||
void DS18B20_Start(const uint8_t *addr)
|
||||
{
|
||||
/* Reset pulse */
|
||||
DS18B20_Reset();
|
||||
/* Select ROM number */
|
||||
DS18B20_Select(addr);
|
||||
/* Start conversion on selected device */
|
||||
DS18B20_WriteByte(DS18B20_CMD_CONVERTTEMP);
|
||||
}
|
||||
|
||||
void DS18B20_ReadScratchpadFromAddr(const uint8_t *addr, uint8_t *buf)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
/* Reset line */
|
||||
DS18B20_Reset();
|
||||
/* Select ROM number */
|
||||
DS18B20_Select(addr);
|
||||
/* Read scratchpad command by onewire protocol */
|
||||
DS18B20_WriteByte(ONEWIRE_CMD_RSCRATCHPAD);
|
||||
|
||||
/* Get data */
|
||||
for (i = 0; i < 9; i++)
|
||||
{
|
||||
/* Read byte by byte */
|
||||
*buf++ = DS18B20_ReadByte();
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t DS18B20_Detect(uint8_t *buff, uint8_t *stack, uint8_t split_point)
|
||||
{
|
||||
uint8_t len = 64, pos = 0;
|
||||
/* Start from deepest point */
|
||||
split_point = (split_point == 0x00)? 0xFF : split_point;
|
||||
/* Reset line */
|
||||
DS18B20_Reset();
|
||||
/* Start searching */
|
||||
DS18B20_WriteByte(ONEWIRE_CMD_SEARCHROM);
|
||||
|
||||
while (len--)
|
||||
{
|
||||
// Read the value and its complement value of this bit
|
||||
__BIT pb = DS18B20_ReadBit();
|
||||
__BIT cb = DS18B20_ReadBit();
|
||||
if (pb && cb) // no device
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (pb) // bit = 1
|
||||
{
|
||||
*(buff + pos / 8) |= 0x01 << (pos % 8);
|
||||
DS18B20_WriteBit(SET);
|
||||
// confirm: set this bit to 1
|
||||
*(stack + pos / 8) |= 0x01 << (pos % 8);
|
||||
}
|
||||
else if (cb) // bit = 0
|
||||
{
|
||||
*(buff + pos / 8) &= ~(0x01 << (pos % 8));
|
||||
DS18B20_WriteBit(RESET);
|
||||
// confirm: set this bit to 1
|
||||
*(stack + pos / 8) |= 0x01 << (pos % 8);
|
||||
}
|
||||
else // bit can be 0 or 1, possible split point
|
||||
{
|
||||
if (split_point == 0xFF || pos > split_point)
|
||||
{
|
||||
// new split point, try 0
|
||||
*(buff + pos / 8) &= ~(0x01 << (pos % 8));
|
||||
DS18B20_WriteBit(RESET);
|
||||
// unconfirm: set this bit to 0
|
||||
*(stack + pos / 8) &= ~(0x01 << (pos % 8));
|
||||
// record this new split point
|
||||
split_point = pos;
|
||||
}
|
||||
else if (pos == split_point)
|
||||
{
|
||||
// reach split point, try 1
|
||||
*(buff + pos / 8) |= 0x01 << (pos % 8);
|
||||
DS18B20_WriteBit(SET);
|
||||
// confirm: set this bit to 1
|
||||
*(stack + pos / 8) |= 0x01 << (pos % 8);
|
||||
}
|
||||
else // middle point, use existing bit
|
||||
{
|
||||
DS18B20_WriteBit(*(buff + pos / 8) >> (pos % 8) & 0x01);
|
||||
}
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
// Relocate split point, move it to the last *unconfirmed* bit of stack
|
||||
while (split_point > 0 && *(stack + split_point / 8) >> (split_point % 8) & 0x01 == 0x01) split_point--;
|
||||
return split_point;
|
||||
}
|
@ -100,7 +100,22 @@ void DS18B20_WriteBit(__BIT b);
|
||||
void DS18B20_WriteByte(uint8_t byte);
|
||||
|
||||
/**
|
||||
* @brief Start all DS18B20
|
||||
* @brief 8-bit CRC calculation
|
||||
*
|
||||
* @param addr
|
||||
* @param len
|
||||
* @return crc result
|
||||
*/
|
||||
uint8_t DS18B20_Crc(uint8_t *addr, uint8_t len);
|
||||
|
||||
/**
|
||||
* @brief Read SRAM scratchpad
|
||||
* @param buf a 9-byte buffer, Byte 8 contains the CRC code for bytes 0 through 7
|
||||
*/
|
||||
void DS18B20_ReadScratchpad(uint8_t *buf);
|
||||
|
||||
/**
|
||||
* @brief Start conversion on all slaves
|
||||
*/
|
||||
void DS18B20_StartAll(void);
|
||||
|
||||
@ -111,10 +126,43 @@ void DS18B20_StartAll(void);
|
||||
__BIT DS18B20_AllDone(void);
|
||||
|
||||
/**
|
||||
* @brief Read 16 bits temperature
|
||||
* @return temperature value
|
||||
* @brief Read 64-bit ROM: 8-bit family code "0x28", unique 48-bit serial number, 8-bit CRC
|
||||
* @note This command can only be used if there is a single DS18B20 on the bus.
|
||||
* If multiple slaves are present, a data collision will occur(a wired AND result).
|
||||
* @param buf a 8-byte buffer
|
||||
*/
|
||||
uint16_t DS18B20_ReadTemperature(void);
|
||||
void DS18B20_ReadRom(uint8_t *buf);
|
||||
|
||||
/**
|
||||
* @brief Select a slave on the bus
|
||||
* @note Only the slave that exactly matches the 64-bit ROM code sequence will respond to
|
||||
* the function command issued by the master; all other slaves on the bus will wait
|
||||
* for a reset pulse.
|
||||
* @param addr 64-bit ROM code
|
||||
*/
|
||||
void DS18B20_Select(const uint8_t* addr);
|
||||
|
||||
/**
|
||||
* @brief Start conversion on selected slave
|
||||
* @param addr 64-bit ROM code
|
||||
*/
|
||||
void DS18B20_Start(const uint8_t *addr);
|
||||
|
||||
/**
|
||||
* @brief Read SRAM scratchpad from selected slave
|
||||
*
|
||||
* @param addr 64-bit ROM code
|
||||
* @param buf a 9-byte buffer, Byte 8 contains the CRC code for bytes 0 through 7
|
||||
*/
|
||||
void DS18B20_ReadScratchpadFromAddr(const uint8_t *addr, uint8_t *buf);
|
||||
|
||||
/**
|
||||
* @brief Perform one ROM search
|
||||
* @param buff 8-byte array for ROM bytes
|
||||
* @param stack 8-byte array for search stack
|
||||
* @param split_point deepest split point of last search
|
||||
* @return new split point
|
||||
*/
|
||||
uint8_t DS18B20_Detect(uint8_t *buff, uint8_t *stack, uint8_t split_point);
|
||||
|
||||
#endif // __DS18B20_H_
|
79
demo/gpio/ds18b20/multiple-ds18b20/main.c
Normal file
79
demo/gpio/ds18b20/multiple-ds18b20/main.c
Normal file
@ -0,0 +1,79 @@
|
||||
// Copyright 2021 IOsetting <iosetting(at)outlook.com>
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/***
|
||||
* Example code of communication on 1-Wire bus with multiple DS18B20
|
||||
*
|
||||
* Board: STC8H3K32
|
||||
*
|
||||
* P35 -> DQ
|
||||
* GND -> GND
|
||||
* 3.3V -> VCC
|
||||
*/
|
||||
|
||||
#include "fw_hal.h"
|
||||
#include "ds18b20.h"
|
||||
|
||||
uint8_t DS18B20_Buff[9], addr[8], Search_Stack[8];
|
||||
|
||||
void PrintArray(uint8_t *arr, uint8_t start, uint8_t end)
|
||||
{
|
||||
uint8_t i;
|
||||
for (i = start; i < end; i++)
|
||||
{
|
||||
UART1_TxHex(*(arr + i));
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
uint8_t i, sp;
|
||||
|
||||
SYS_SetClock();
|
||||
// UART1, baud 115200, baud source Timer1, 1T mode, no interrupt
|
||||
UART1_Config8bitUart(UART1_BaudSource_Timer1, HAL_State_ON, 115200);
|
||||
DS18B20_Init();
|
||||
|
||||
while(1)
|
||||
{
|
||||
// Reset split point and search for all DS18B20
|
||||
sp = 0;
|
||||
do
|
||||
{
|
||||
// ROM search and store ROM bytes to addr
|
||||
sp = DS18B20_Detect(addr, Search_Stack, sp);
|
||||
// Print the new split point and address
|
||||
UART1_TxHex(sp);
|
||||
UART1_TxChar(' ');
|
||||
PrintArray(addr, 0, 8);
|
||||
// Convert and read from this address
|
||||
DS18B20_Start(addr);
|
||||
while (!DS18B20_AllDone())
|
||||
{
|
||||
UART1_TxChar('.');
|
||||
SYS_Delay(50);
|
||||
}
|
||||
DS18B20_ReadScratchpadFromAddr(addr, DS18B20_Buff);
|
||||
PrintArray(DS18B20_Buff, 0, 9);
|
||||
UART1_TxChar(' ');
|
||||
i = DS18B20_Crc(DS18B20_Buff, 8);
|
||||
UART1_TxString("CRC:");
|
||||
UART1_TxHex(i);
|
||||
UART1_TxChar(' ');
|
||||
UART1_TxString("\r\n");
|
||||
} while (sp);
|
||||
|
||||
SYS_Delay(1000);
|
||||
}
|
||||
}
|
301
demo/gpio/ds18b20/single-ds18b20/ds18b20.c
Normal file
301
demo/gpio/ds18b20/single-ds18b20/ds18b20.c
Normal file
@ -0,0 +1,301 @@
|
||||
// Copyright 2021 IOsetting <iosetting(at)outlook.com>
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "ds18b20.h"
|
||||
|
||||
void DS18B20_Init(void)
|
||||
{
|
||||
DS18B20_DQ_PULLUP();
|
||||
DS18B20_DQ_OUTPUT();
|
||||
DS18B20_DQ = SET;
|
||||
SYS_DelayUs(1000);
|
||||
DS18B20_DQ = RESET;
|
||||
SYS_DelayUs(1000);
|
||||
DS18B20_DQ = SET;
|
||||
SYS_DelayUs(2000);
|
||||
}
|
||||
|
||||
__BIT DS18B20_Reset(void)
|
||||
{
|
||||
__BIT b;
|
||||
|
||||
/* Line low, and wait 480us */
|
||||
DS18B20_DQ = RESET;
|
||||
DS18B20_DQ_OUTPUT();
|
||||
SYS_DelayUs(500);
|
||||
/* Release line and wait for 70us */
|
||||
DS18B20_DQ_INPUT();
|
||||
SYS_DelayUs(70);
|
||||
/* Check bit value, success if low */
|
||||
b = DS18B20_DQ;
|
||||
/* Delay for 410 us */
|
||||
SYS_DelayUs(410);
|
||||
/* Return value of presence pulse, 0 = OK, 1 = ERROR */
|
||||
return b;
|
||||
}
|
||||
|
||||
__BIT DS18B20_ReadBit(void)
|
||||
{
|
||||
__BIT b = RESET;
|
||||
|
||||
/* Line low */
|
||||
DS18B20_DQ = RESET;
|
||||
DS18B20_DQ_OUTPUT();
|
||||
SYS_DelayUs(2);
|
||||
|
||||
/* Release line */
|
||||
DS18B20_DQ_INPUT();
|
||||
SYS_DelayUs(10);
|
||||
|
||||
/* Read line value */
|
||||
if (DS18B20_DQ) {
|
||||
/* Bit is HIGH */
|
||||
b = SET;
|
||||
}
|
||||
|
||||
/* Wait 50us to complete 60us period */
|
||||
SYS_DelayUs(50);
|
||||
|
||||
/* Return bit value */
|
||||
return b;
|
||||
}
|
||||
|
||||
uint8_t DS18B20_ReadByte(void)
|
||||
{
|
||||
uint8_t i = 8, byte = 0;
|
||||
while (i--)
|
||||
{
|
||||
byte >>= 1;
|
||||
byte |= (DS18B20_ReadBit() << 7);
|
||||
}
|
||||
return byte;
|
||||
}
|
||||
|
||||
void DS18B20_WriteBit(__BIT b)
|
||||
{
|
||||
if (b)
|
||||
{
|
||||
/* Set line low */
|
||||
DS18B20_DQ = RESET;
|
||||
DS18B20_DQ_OUTPUT();
|
||||
SYS_DelayUs(10);
|
||||
|
||||
/* Bit high */
|
||||
DS18B20_DQ_INPUT();
|
||||
|
||||
/* Wait for 55 us and release the line */
|
||||
SYS_DelayUs(55);
|
||||
DS18B20_DQ_INPUT();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set line low */
|
||||
DS18B20_DQ = RESET;
|
||||
DS18B20_DQ_OUTPUT();
|
||||
SYS_DelayUs(65);
|
||||
|
||||
/* Bit high */
|
||||
DS18B20_DQ_INPUT();
|
||||
|
||||
/* Wait for 5 us and release the line */
|
||||
SYS_DelayUs(5);
|
||||
DS18B20_DQ_INPUT();
|
||||
}
|
||||
}
|
||||
|
||||
void DS18B20_WriteByte(uint8_t byte)
|
||||
{
|
||||
uint8_t i = 8;
|
||||
/* Write 8 bits */
|
||||
while (i--)
|
||||
{
|
||||
/* LSB bit is first */
|
||||
DS18B20_WriteBit(byte & 0x01);
|
||||
byte >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
void DS18B20_ReadScratchpad(uint8_t *buf)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
/* Reset line */
|
||||
DS18B20_Reset();
|
||||
/* Skip ROM */
|
||||
DS18B20_WriteByte(ONEWIRE_CMD_SKIPROM);
|
||||
/* Read scratchpad command by onewire protocol */
|
||||
DS18B20_WriteByte(ONEWIRE_CMD_RSCRATCHPAD);
|
||||
|
||||
/* Get data */
|
||||
for (i = 0; i < 9; i++)
|
||||
{
|
||||
/* Read byte by byte */
|
||||
*buf++ = DS18B20_ReadByte();
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t DS18B20_Crc(uint8_t *addr, uint8_t len)
|
||||
{
|
||||
uint8_t crc = 0, inbyte, i, mix;
|
||||
|
||||
while (len--)
|
||||
{
|
||||
inbyte = *addr++;
|
||||
for (i = 8; i; i--)
|
||||
{
|
||||
mix = (crc ^ inbyte) & 0x01;
|
||||
crc >>= 1;
|
||||
if (mix)
|
||||
{
|
||||
crc ^= 0x8C;
|
||||
}
|
||||
inbyte >>= 1;
|
||||
}
|
||||
}
|
||||
/* Return calculated CRC */
|
||||
return crc;
|
||||
}
|
||||
|
||||
void DS18B20_StartAll(void)
|
||||
{
|
||||
/* Reset pulse */
|
||||
DS18B20_Reset();
|
||||
/* Skip rom */
|
||||
DS18B20_WriteByte(ONEWIRE_CMD_SKIPROM);
|
||||
/* Start conversion on all connected devices */
|
||||
DS18B20_WriteByte(DS18B20_CMD_CONVERTTEMP);
|
||||
}
|
||||
|
||||
__BIT DS18B20_AllDone(void)
|
||||
{
|
||||
/* If read bit is low, then device is not finished yet with calculation temperature */
|
||||
return DS18B20_ReadBit();
|
||||
}
|
||||
|
||||
void DS18B20_ReadRom(uint8_t *buf)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
/* Reset pulse */
|
||||
DS18B20_Reset();
|
||||
/* Read rom */
|
||||
DS18B20_WriteByte(ONEWIRE_CMD_READROM);
|
||||
/* Get data */
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
/* Read byte by byte */
|
||||
*buf++ = DS18B20_ReadByte();
|
||||
}
|
||||
}
|
||||
|
||||
void DS18B20_Select(const uint8_t* addr)
|
||||
{
|
||||
uint8_t len = 8;
|
||||
DS18B20_WriteByte(ONEWIRE_CMD_MATCHROM);
|
||||
while (len--)
|
||||
{
|
||||
DS18B20_WriteByte(*addr++);
|
||||
}
|
||||
}
|
||||
|
||||
void DS18B20_Start(const uint8_t *addr)
|
||||
{
|
||||
/* Reset pulse */
|
||||
DS18B20_Reset();
|
||||
/* Select ROM number */
|
||||
DS18B20_Select(addr);
|
||||
/* Start conversion on selected device */
|
||||
DS18B20_WriteByte(DS18B20_CMD_CONVERTTEMP);
|
||||
}
|
||||
|
||||
void DS18B20_ReadScratchpadFromAddr(const uint8_t *addr, uint8_t *buf)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
/* Reset line */
|
||||
DS18B20_Reset();
|
||||
/* Select ROM number */
|
||||
DS18B20_Select(addr);
|
||||
/* Read scratchpad command by onewire protocol */
|
||||
DS18B20_WriteByte(ONEWIRE_CMD_RSCRATCHPAD);
|
||||
|
||||
/* Get data */
|
||||
for (i = 0; i < 9; i++)
|
||||
{
|
||||
/* Read byte by byte */
|
||||
*buf++ = DS18B20_ReadByte();
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t DS18B20_Detect(uint8_t *buff, uint8_t *stack, uint8_t split_point)
|
||||
{
|
||||
uint8_t len = 64, pos = 0;
|
||||
/* Start from deepest point */
|
||||
split_point = (split_point == 0x00)? 0xFF : split_point;
|
||||
/* Reset line */
|
||||
DS18B20_Reset();
|
||||
/* Start searching */
|
||||
DS18B20_WriteByte(ONEWIRE_CMD_SEARCHROM);
|
||||
|
||||
while (len--)
|
||||
{
|
||||
// Read the value and its complement value of this bit
|
||||
__BIT pb = DS18B20_ReadBit();
|
||||
__BIT cb = DS18B20_ReadBit();
|
||||
if (pb && cb) // no device
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (pb) // bit = 1
|
||||
{
|
||||
*(buff + pos / 8) |= 0x01 << (pos % 8);
|
||||
DS18B20_WriteBit(SET);
|
||||
// confirm: set this bit to 1
|
||||
*(stack + pos / 8) |= 0x01 << (pos % 8);
|
||||
}
|
||||
else if (cb) // bit = 0
|
||||
{
|
||||
*(buff + pos / 8) &= ~(0x01 << (pos % 8));
|
||||
DS18B20_WriteBit(RESET);
|
||||
// confirm: set this bit to 1
|
||||
*(stack + pos / 8) |= 0x01 << (pos % 8);
|
||||
}
|
||||
else // bit can be 0 or 1, possible split point
|
||||
{
|
||||
if (split_point == 0xFF || pos > split_point)
|
||||
{
|
||||
// new split point, try 0
|
||||
*(buff + pos / 8) &= ~(0x01 << (pos % 8));
|
||||
DS18B20_WriteBit(RESET);
|
||||
// unconfirm: set this bit to 0
|
||||
*(stack + pos / 8) &= ~(0x01 << (pos % 8));
|
||||
// record this new split point
|
||||
split_point = pos;
|
||||
}
|
||||
else if (pos == split_point)
|
||||
{
|
||||
// reach split point, try 1
|
||||
*(buff + pos / 8) |= 0x01 << (pos % 8);
|
||||
DS18B20_WriteBit(SET);
|
||||
// confirm: set this bit to 1
|
||||
*(stack + pos / 8) |= 0x01 << (pos % 8);
|
||||
}
|
||||
else // middle point, use existing bit
|
||||
{
|
||||
DS18B20_WriteBit(*(buff + pos / 8) >> (pos % 8) & 0x01);
|
||||
}
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
// Relocate split point, move it to the last *unconfirmed* bit of stack
|
||||
while (split_point > 0 && *(stack + split_point / 8) >> (split_point % 8) & 0x01 == 0x01) split_point--;
|
||||
return split_point;
|
||||
}
|
168
demo/gpio/ds18b20/single-ds18b20/ds18b20.h
Normal file
168
demo/gpio/ds18b20/single-ds18b20/ds18b20.h
Normal file
@ -0,0 +1,168 @@
|
||||
// Copyright 2021 IOsetting <iosetting(at)outlook.com>
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef __FW_DS18B20__
|
||||
#define __FW_DS18B20__
|
||||
|
||||
#include "fw_hal.h"
|
||||
|
||||
/**
|
||||
* DS18B20 - Programmable Resolution 1-Wire Digital Thermometer
|
||||
*
|
||||
* To-92 Pins:
|
||||
* With the flat side facing you and with the leads pointing down, they are GND, DQ and Vdd
|
||||
*
|
||||
*/
|
||||
|
||||
#define DS18B20_DQ P35
|
||||
#define DS18B20_DQ_PULLUP() GPIO_SetPullUp(GPIO_Port_3, GPIO_Pin_5, HAL_State_ON)
|
||||
#define DS18B20_DQ_INPUT() GPIO_P3_SetMode(GPIO_Pin_5, GPIO_Mode_Input_HIP)
|
||||
#define DS18B20_DQ_OUTPUT() GPIO_P3_SetMode(GPIO_Pin_5, GPIO_Mode_InOut_OD)
|
||||
#define DS18B20_DQ_LOW() DS18B20_DQ=RESET
|
||||
#define DS18B20_DQ_HIGH() DS18B20_DQ=SET
|
||||
|
||||
/* OneWire commands */
|
||||
#define ONEWIRE_CMD_RSCRATCHPAD 0xBE
|
||||
#define ONEWIRE_CMD_WSCRATCHPAD 0x4E
|
||||
#define ONEWIRE_CMD_CPYSCRATCHPAD 0x48
|
||||
#define ONEWIRE_CMD_RECEEPROM 0xB8
|
||||
#define ONEWIRE_CMD_RPWRSUPPLY 0xB4
|
||||
#define ONEWIRE_CMD_SEARCHROM 0xF0
|
||||
#define ONEWIRE_CMD_READROM 0x33
|
||||
#define ONEWIRE_CMD_MATCHROM 0x55
|
||||
#define ONEWIRE_CMD_SKIPROM 0xCC
|
||||
|
||||
#define DS18B20_FAMILY_CODE 0x28
|
||||
#define DS18B20_CMD_ALARMSEARCH 0xEC
|
||||
|
||||
/* DS18B20 read temperature command */
|
||||
#define DS18B20_CMD_CONVERTTEMP 0x44 /* Convert temperature */
|
||||
#define DS18B20_DECIMAL_STEPS_12BIT 0.0625
|
||||
#define DS18B20_DECIMAL_STEPS_11BIT 0.125
|
||||
#define DS18B20_DECIMAL_STEPS_10BIT 0.25
|
||||
#define DS18B20_DECIMAL_STEPS_9BIT 0.5
|
||||
|
||||
/* Bits locations for resolution */
|
||||
#define DS18B20_RESOLUTION_R1 6
|
||||
#define DS18B20_RESOLUTION_R0 5
|
||||
|
||||
typedef enum {
|
||||
DS18B20_Resolution_9bits = 9, /*!< DS18B20 9 bits resolution */
|
||||
DS18B20_Resolution_10bits = 10, /*!< DS18B20 10 bits resolution */
|
||||
DS18B20_Resolution_11bits = 11, /*!< DS18B20 11 bits resolution */
|
||||
DS18B20_Resolution_12bits = 12 /*!< DS18B20 12 bits resolution */
|
||||
} DS18B20_Resolution_t;
|
||||
|
||||
/**
|
||||
* @brief Initialize DS18B20
|
||||
*/
|
||||
void DS18B20_Init(void);
|
||||
|
||||
/**
|
||||
* @brief Reset DS18B20
|
||||
* @return bit value
|
||||
*/
|
||||
__BIT DS18B20_Reset(void);
|
||||
|
||||
/**
|
||||
* @brief Read one bit from DS18B20
|
||||
* @return bit value
|
||||
*/
|
||||
__BIT DS18B20_ReadBit(void);
|
||||
|
||||
/**
|
||||
* @brief Read one byte from DS18B20
|
||||
* @return byte value
|
||||
*/
|
||||
uint8_t DS18B20_ReadByte(void);
|
||||
|
||||
/**
|
||||
* @brief Write one bit to DS18B20
|
||||
* @param b bit value
|
||||
*/
|
||||
void DS18B20_WriteBit(__BIT b);
|
||||
|
||||
/**
|
||||
* @brief Write one byte to DS18B20
|
||||
* @param byte byte value
|
||||
*/
|
||||
void DS18B20_WriteByte(uint8_t byte);
|
||||
|
||||
/**
|
||||
* @brief 8-bit CRC calculation
|
||||
*
|
||||
* @param addr
|
||||
* @param len
|
||||
* @return crc result
|
||||
*/
|
||||
uint8_t DS18B20_Crc(uint8_t *addr, uint8_t len);
|
||||
|
||||
/**
|
||||
* @brief Read SRAM scratchpad
|
||||
* @param buf a 9-byte buffer, Byte 8 contains the CRC code for bytes 0 through 7
|
||||
*/
|
||||
void DS18B20_ReadScratchpad(uint8_t *buf);
|
||||
|
||||
/**
|
||||
* @brief Start conversion on all slaves
|
||||
*/
|
||||
void DS18B20_StartAll(void);
|
||||
|
||||
/**
|
||||
* @brief If read bit is low, then device is not finished yet with calculation temperature
|
||||
* @return bit value
|
||||
*/
|
||||
__BIT DS18B20_AllDone(void);
|
||||
|
||||
/**
|
||||
* @brief Read 64-bit ROM: 8-bit family code "0x28", unique 48-bit serial number, 8-bit CRC
|
||||
* @note This command can only be used if there is a single DS18B20 on the bus.
|
||||
* If multiple slaves are present, a data collision will occur(a wired AND result).
|
||||
* @param buf a 8-byte buffer
|
||||
*/
|
||||
void DS18B20_ReadRom(uint8_t *buf);
|
||||
|
||||
/**
|
||||
* @brief Select a slave on the bus
|
||||
* @note Only the slave that exactly matches the 64-bit ROM code sequence will respond to
|
||||
* the function command issued by the master; all other slaves on the bus will wait
|
||||
* for a reset pulse.
|
||||
* @param addr 64-bit ROM code
|
||||
*/
|
||||
void DS18B20_Select(const uint8_t* addr);
|
||||
|
||||
/**
|
||||
* @brief Start conversion on selected slave
|
||||
* @param addr 64-bit ROM code
|
||||
*/
|
||||
void DS18B20_Start(const uint8_t *addr);
|
||||
|
||||
/**
|
||||
* @brief Read SRAM scratchpad from selected slave
|
||||
*
|
||||
* @param addr 64-bit ROM code
|
||||
* @param buf a 9-byte buffer, Byte 8 contains the CRC code for bytes 0 through 7
|
||||
*/
|
||||
void DS18B20_ReadScratchpadFromAddr(const uint8_t *addr, uint8_t *buf);
|
||||
|
||||
/**
|
||||
* @brief Perform one ROM search
|
||||
* @param buff 8-byte array for ROM bytes
|
||||
* @param stack 8-byte array for search stack
|
||||
* @param split_point deepest split point of last search
|
||||
* @return new split point
|
||||
*/
|
||||
uint8_t DS18B20_Detect(uint8_t *buff, uint8_t *stack, uint8_t split_point);
|
||||
|
||||
#endif // __DS18B20_H_
|
@ -13,7 +13,8 @@
|
||||
// limitations under the License.
|
||||
|
||||
/***
|
||||
* Demo: DS18B20
|
||||
* Example code of communication with single DS18B20
|
||||
*
|
||||
* Board: STC8H3K32
|
||||
*
|
||||
* P35 -> DQ
|
||||
@ -24,11 +25,18 @@
|
||||
#include "fw_hal.h"
|
||||
#include "ds18b20.h"
|
||||
|
||||
uint16_t temp;
|
||||
void PrintArray(uint8_t *arr, uint8_t start, uint8_t end)
|
||||
{
|
||||
uint8_t i;
|
||||
for (i = start; i < end; i++)
|
||||
{
|
||||
UART1_TxHex(*(arr + i));
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
uint16_t temperature;
|
||||
uint8_t buff[9], i;
|
||||
|
||||
SYS_SetClock();
|
||||
// UART1, baud 115200, baud source Timer1, 1T mode, no interrupt
|
||||
@ -41,11 +49,15 @@ int main(void)
|
||||
while (!DS18B20_AllDone())
|
||||
{
|
||||
UART1_TxChar('.');
|
||||
SYS_Delay(1);
|
||||
SYS_Delay(50);
|
||||
}
|
||||
temperature = DS18B20_ReadTemperature();
|
||||
UART1_TxHex(temperature >> 8);
|
||||
UART1_TxHex(temperature & 0xFF);
|
||||
DS18B20_ReadScratchpad(buff);
|
||||
PrintArray(buff, 0, 9);
|
||||
UART1_TxChar(' ');
|
||||
i = DS18B20_Crc(buff, 8);
|
||||
UART1_TxString("CRC:");
|
||||
UART1_TxHex(i);
|
||||
UART1_TxChar(' ');
|
||||
UART1_TxString("\r\n");
|
||||
SYS_Delay(1000);
|
||||
}
|
Loading…
Reference in New Issue
Block a user