A cut-down version of https://os.mbed.com/users/Sissors/code/DS1820/ tweaked for use with the STM32F103. It is all generic Mbed operations though, so should be usable anywhere. Non-essential functions have been removed, as this is intended for use within a tutorial.
Dependents: STM32F103C8T6_DS18B20 stm32f103c8t6-ds18b20
Fork of DS1820 by
Diff: DS1820.cpp
- Revision:
- 16:d490e11c466d
- Parent:
- 14:c591209285e9
- Child:
- 17:045f96704cc6
--- a/DS1820.cpp Sun Jan 08 17:26:21 2017 +0000 +++ b/DS1820.cpp Thu Jan 11 04:37:42 2018 +0000 @@ -1,88 +1,35 @@ #include "DS1820.h" -#ifdef TARGET_STM -//STM targets use opendrain mode since their GPIO code is too bad to be used like the others - #define ONEWIRE_INPUT(pin) pin->write(1) - #define ONEWIRE_OUTPUT(pin) - #define ONEWIRE_INIT(pin) pin->output(); pin->mode(OpenDrain) - - // TEMP, remove once STM fixed their stuff -// Enable GPIO clock and return GPIO base address -static uint32_t Set_GPIO_Clock(uint32_t port_idx) { - uint32_t gpio_add = 0; - switch (port_idx) { - case PortA: - gpio_add = GPIOA_BASE; - __GPIOA_CLK_ENABLE(); - break; - case PortB: - gpio_add = GPIOB_BASE; - __GPIOB_CLK_ENABLE(); - break; -#if defined(GPIOC_BASE) - case PortC: - gpio_add = GPIOC_BASE; - __GPIOC_CLK_ENABLE(); - break; -#endif -#if defined(GPIOD_BASE) - case PortD: - gpio_add = GPIOD_BASE; - __GPIOD_CLK_ENABLE(); - break; -#endif -#if defined(GPIOF_BASE) - case PortF: - gpio_add = GPIOF_BASE; - __GPIOF_CLK_ENABLE(); - break; -#endif - default: - error("Pinmap error: wrong port number."); - break; - } - return gpio_add; -} +DigitalOut tracer(PA_6); +static inline void onewire_input(DigitalInOut &pin) { + pin.input(); + pin.mode(PullUp); +} -#else - #define ONEWIRE_INPUT(pin) pin->input() - #define ONEWIRE_OUTPUT(pin) pin->output() - #define ONEWIRE_INIT(pin) -#endif +static inline void onewire_output(DigitalInOut &pin) { + pin.output(); + pin.write(0); +} LinkedList<node> DS1820::probes; -DS1820::DS1820 (PinName data_pin, PinName power_pin, bool power_polarity) : _datapin(data_pin), _parasitepin(power_pin) { +DS1820::DS1820 (PinName data_pin) : _datapin(data_pin) { int byte_counter; - _power_polarity = power_polarity; + + tracer = 1; - _power_mosfet = power_pin != NC; - for(byte_counter=0;byte_counter<9;byte_counter++) RAM[byte_counter] = 0x00; - ONEWIRE_INIT((&_datapin)); - // Temp code since the above doesn't actually do anything in mbed revisions up to 133 - #ifdef TARGET_STM - - uint32_t port_index = STM_PORT(data_pin); - uint32_t pin_index = STM_PIN(data_pin); + onewire_input(_datapin); - // Enable GPIO clock - uint32_t gpio_add = Set_GPIO_Clock(port_index); - GPIO_TypeDef *gpio = (GPIO_TypeDef *)gpio_add; - - gpio->OTYPER |= (uint32_t)(1 << pin_index); - #endif - - if (!unassignedProbe(&_datapin, _ROM)) - error("No unassigned DS1820 found!\n"); + if (!unassignedProbe(_ROM)) + error("No unassigned DS1820 found!\r\n"); else { - _datapin.input(); + onewire_input(_datapin); probes.append(this); - _parasite_power = !read_power_supply(); } } @@ -97,51 +44,48 @@ } -bool DS1820::onewire_reset(DigitalInOut *pin) { +bool DS1820::onewire_reset() { // This will return false if no devices are present on the data bus bool presence=false; - ONEWIRE_OUTPUT(pin); - pin->write(0); // bring low for 500 us + onewire_output(_datapin); // bring low for 500 us wait_us(500); - ONEWIRE_INPUT(pin); // let the data line float high + onewire_input(_datapin); // let the data line float high wait_us(90); // wait 90us - if (pin->read()==0) // see if any devices are pulling the data line low + if (_datapin.read()==0) // see if any devices are pulling the data line low presence=true; wait_us(410); return presence; } -void DS1820::onewire_bit_out (DigitalInOut *pin, bool bit_data) { - ONEWIRE_OUTPUT(pin); - pin->write(0); - wait_us(3); // DXP modified from 5 +void DS1820::onewire_bit_out (bool bit_data) { + onewire_output(_datapin); + wait_us(1); // DXP modified from 5 if (bit_data) { - pin->write(1); // bring data line high - wait_us(55); + onewire_input(_datapin); // bring data line high } else { - wait_us(55); // keep data line low - pin->write(1); - wait_us(10); // DXP added to allow bus to float high before next bit_out + wait_us(57); // keep data line low + onewire_input(_datapin); } + wait_us(55); } void DS1820::onewire_byte_out(char data) { // output data character (least sig bit first). int n; for (n=0; n<8; n++) { - onewire_bit_out(&this->_datapin, data & 0x01); + onewire_bit_out(data & 0x01); data = data >> 1; // now the next bit is in the least sig bit position. } + wait_us(100); } -bool DS1820::onewire_bit_in(DigitalInOut *pin) { +bool DS1820::onewire_bit_in() { bool answer; - ONEWIRE_OUTPUT(pin); - pin->write(0); - wait_us(3); // DXP modofied from 5 - ONEWIRE_INPUT(pin); + onewire_output(_datapin); + wait_us(1); // DXP modified from 5 + onewire_input(_datapin); wait_us(10); // DXP modified from 5 - answer = pin->read(); - wait_us(45); // DXP modified from 50 + answer = _datapin.read(); + wait_us(49); // DXP modified from 50 return answer; } @@ -150,36 +94,18 @@ int i; for (i=0; i<8; i++) { answer = answer >> 1; // shift over to make room for the next bit - if (onewire_bit_in(&this->_datapin)) + if (onewire_bit_in()) answer = answer | 0x80; // if the data port is high, make this bit a 1 } return answer; } -bool DS1820::unassignedProbe(PinName pin) { - DigitalInOut _pin(pin); - ONEWIRE_INIT((&_pin)); - // Temp code since the above doesn't actually do anything in mbed revisions up to 133 - #ifdef TARGET_STM - - uint32_t port_index = STM_PORT(pin); - uint32_t pin_index = STM_PIN(pin); - - // Enable GPIO clock - uint32_t gpio_add = Set_GPIO_Clock(port_index); - GPIO_TypeDef *gpio = (GPIO_TypeDef *)gpio_add; - - gpio->OTYPER |= (uint32_t)(1 << pin_index); - #endif - char ROM_address[8]; - return search_ROM_routine(&_pin, 0xF0, ROM_address); + +bool DS1820::unassignedProbe(char *ROM_address) { + return search_ROM_routine(0xF0, ROM_address); } -bool DS1820::unassignedProbe(DigitalInOut *pin, char *ROM_address) { - return search_ROM_routine(pin, 0xF0, ROM_address); -} - -bool DS1820::search_ROM_routine(DigitalInOut *pin, char command, char *ROM_address) { +bool DS1820::search_ROM_routine(char command, char *ROM_address) { bool DS1820_done_flag = false; int DS1820_last_descrepancy = 0; char DS1820_search_ROM[8] = {0, 0, 0, 0, 0, 0, 0, 0}; @@ -190,21 +116,23 @@ return_value=false; while (!DS1820_done_flag) { - if (!onewire_reset(pin)) { + if (!onewire_reset()) { return false; } else { ROM_bit_index=1; descrepancy_marker=0; char command_shift = command; for (int n=0; n<8; n++) { // Search ROM command or Search Alarm command - onewire_bit_out(pin, command_shift & 0x01); + onewire_bit_out(command_shift & 0x01); command_shift = command_shift >> 1; // now the next bit is in the least sig bit position. } + wait_us(100); + byte_counter = 0; bit_mask = 0x01; while (ROM_bit_index<=64) { - Bit_A = onewire_bit_in(pin); - Bit_B = onewire_bit_in(pin); + Bit_A = onewire_bit_in(); + Bit_B = onewire_bit_in(); if (Bit_A & Bit_B) { descrepancy_marker = 0; // data read error, this should never happen ROM_bit_index = 0xFF; @@ -230,7 +158,7 @@ } } } - onewire_bit_out (pin, DS1820_search_ROM[byte_counter] & bit_mask); + onewire_bit_out (DS1820_search_ROM[byte_counter] & bit_mask); ROM_bit_index++; if (bit_mask & 0x80) { byte_counter++; @@ -239,6 +167,8 @@ bit_mask = bit_mask << 1; } } + + wait_us(100); } DS1820_last_descrepancy = descrepancy_marker; if (ROM_bit_index != 0xFF) { @@ -252,6 +182,9 @@ } for(byte_counter=0;byte_counter<8;byte_counter++) ROM_address[byte_counter] = DS1820_search_ROM[byte_counter]; + + printf("Found DS18B20: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\r\n", + ROM_address[0], ROM_address[1], ROM_address[2], ROM_address[3], ROM_address[4], ROM_address[5], ROM_address[6], ROM_address[7]); return true; } else { //Otherwise, check if ROM is already known bool equal = true; @@ -279,15 +212,15 @@ void DS1820::match_ROM() { // Used to select a specific device int i; - onewire_reset(&this->_datapin); - onewire_byte_out( 0x55); //Match ROM command + onewire_reset(); + onewire_byte_out(0x55); //Match ROM command for (i=0;i<8;i++) { onewire_byte_out(_ROM[i]); } } void DS1820::skip_ROM() { - onewire_reset(&this->_datapin); + onewire_reset(); onewire_byte_out(0xCC); // Skip ROM command } @@ -360,24 +293,13 @@ } } + tracer = 0; onewire_byte_out( 0x44); // perform temperature conversion - if (_parasite_power) { - if (_power_mosfet) { - _parasitepin = _power_polarity; // Parasite power strong pullup - wait_ms(delay_time); - _parasitepin = !_power_polarity; - delay_time = 0; - } else { - _datapin.output(); - _datapin.write(1); - wait_ms(delay_time); - _datapin.input(); - } - } else { - if (wait) { - wait_ms(delay_time); - delay_time = 0; - } + tracer = 1; + + if (wait) { + wait_ms(delay_time); + delay_time = 0; } return delay_time; } @@ -453,16 +375,5 @@ } return answer; } - -bool DS1820::read_power_supply(devices device) { -// This will return true if the device (or all devices) are Vcc powered -// This will return false if the device (or ANY device) is parasite powered - if (device==all_devices) - skip_ROM(); // Skip ROM command, will poll for any device using parasite power - else - match_ROM(); - onewire_byte_out(0xB4); // Read power supply command - return onewire_bit_in(&this->_datapin); -}