Maxim DS18B20 to STM32 (I2C)

Greetings,

I've been playing with STM32F103RE and DS18B20 1-Wire Digital Thermometer. Judging from what I have seen (examples regarding I2C and *duino projects regarding I2C), it requires somewhat different approach due to the "reset" part in its initialization.

Can someone provide code for connecting that device to STM32 uC's (I'm using STM C libs and uVision 4), as I am perplexed with the part where I should set I2C pin to different modes of operation (input, output, float?) in the reset procedure.

Does that require GPIO configuration to be executed every time reset is needed? Code would be much appreciated.

TIA!

--
"If you lie to the compiler, ¤|¤     http://2.7182818284
it will get its revenge."    ¤|¤     5904523536028747135
Henry Spencer                ¤|¤     2662497757247093699
                             ¤|¤     959574966967627.com
Reply to
Bubba
Loading thread data ...

.
)

I understand what you are confused about. The DS18B20 is not I2C. It uses a Dallas/Maxim one-wire interface. The I2C interface uses two pins, both open collector, one as clock and the other as data. The one-wire interface uses one open collector pin as both clock and data. You need to go to the Maxim web site and read up on the one- wire protocol. It has a reset pulse which is a very long zero, to put all of the slaves in a known state. The master starts all comms by pulling the bus low for a short time for a one and a longer time for a zero. The master starts by enumerating all devices on the bus (or just the one if you know what is out there). The bus is polled to get each device to respond with its serial number which is always unique. Once the objects on the bus have been enumerated, commands can be sent to just one device at a time.

To output the reset, one or zero state, your output must be an open collector output. Typically this is done by setting the output bit to a zero and instead of writing to the output bit, writing to the output enable bit to turn the drive on or off (pull down or open).

If you really want it, I have some old code that ran on a DSP chip. I think it knew specifically how to talk to a DS1822 which should be very similar to the DS18B20, IIRC. The enumeration code will work with any one-wire device and let you know serial numbers. The serial number contains a family and device code which tells you exactly what part it is.

Not complex, but it takes more than five minutes to write this. BTW, I am pretty sure Dallas has code on their web site to do all of this too. You only need to write the interface to control your I/O pins. That will have to be tailored for any code you get unless it knows exactly which pins your DS28B20 is wired to.

Rick

Reply to
rickman

No. It requires completely different handling because its interface is _not_ I2C in the first place. It's Dallas Semiconductor's own serial interface, using no clock line at all.

No. It requires GPIO for the entire job. You'll be bit-banging that protocol.

Reply to
Hans-Bernhard Bröker

=?ISO-8859-15?Q?Hans-Bernhard_Br=F6ker?='s log on stardate 09 sij 2011

Huh.

Yeah, thanks for being mild on my. I'll check 1-Wire interface more thoroughly now. :)

Got that. Thanks for help!

Best regards.

--
"If you lie to the compiler, ¤|¤     http://2.7182818284
it will get its revenge."    ¤|¤     5904523536028747135
Henry Spencer                ¤|¤     2662497757247093699
                             ¤|¤     959574966967627.com
Reply to
Bubba

rickman's log on stardate 08 sij 2011

/snip

Wow, this is really shamefully. :(

My bad, I don't know why I mixed those two, probably because I bought it over Ebay and it was poorly described, and I didn't had enough brains to thing I was actually reading about two different technologies.

And since that made no sense with I2C and its specs... That where my questions comes from...

The code would be really great and appreciated. In addition to all, it will be archived by Google groups, so someone might use it afterwards.

It does ->

formatting link
(Example

  1. 1-Wire Basic Functions). I'll try to do it myself now when I know that I am not bind to non existing I2C.

Thanks for reply.

Best regards!

--
"If you lie to the compiler, ¤|¤     http://2.7182818284
it will get its revenge."    ¤|¤     5904523536028747135
Henry Spencer                ¤|¤     2662497757247093699
                             ¤|¤     959574966967627.com
Reply to
Bubba

It's not a mistake that hasn't been made before I'm sure. One-wire is a bit odd and not widely known. It is proprietary, so if you don't go to the Dallas/Maxim site, you wouldn't have learned about it.

BTW, one-wire uses the tristate outputs to implement an open collector driver. I2C also uses open collector drivers so you would need to do the same sort of port manipulations if you were bit banging I2C rather than using an I2C peripheral.

I am posting the code here. It is C and was written over ten years ago, so there may be some new features in one-wire that aren't supported like the higher speed option. The main utility is the code that does the enumeration. I think it also builds a table of devices allowing for a string of multiple devices to be out there. The one- wire bus connected to multiple daughtercards so that they could be identified and the interfaces initialized accordingly. We never fully implemented the scheme because of the limitations on I/O count on the one-wire parts. If we had followed through on the idea we were going to use 8 bit MCUs instead because they gave a lot more functionality for the buck.

BTW, I paid someone to write this and it cost me quite a few bucks. But that's water over the dam now. If it turns out this file is not complete, let me know and I'll dig up the rest.

BTW, if I had it to do over again, I would do it myself and write it all in Forth. Forth is just so perfect for debugging hardware.

Regards,

Rick

/ ****************************************************************************** PC104C31 Boot Monitor (C) 2000 Arius, Inc.

File : onewire.c Description : High-level 1-wire interface routines (place holder)

*****************************************************************************/ #include "bm_types.h" #include "globs.h" #include "macros.h"

int ow_rom_search(short ow_bus_num, unsigned char *rom_ptr, short init_search);

/ ***************************************************************************** USER INTERFACE FUNCTION. cmd_onewire()

One-wire bus mainenance mode-

Allows user to - display connected one-wire devices - read/write ROM, PROM, and EEPROM data in onewire (write access for EEPROM only) - read temperature sensor

*****************************************************************************/ extern char cmd_line[256]; cmd_onewire() { short done=0;

fprintf(dfp,"\nEntering one-wire maintenance mode, enter 'q' to exit. \n");

while(!done) { fprintf(dfp,"\nonewire> "); fscanf(bm.dbgin_fp,"%s",cmd_line); switch(tolower(cmd_line[0])) { case 'r': break; case '?': case 'h': cmd_onewire_menu(); break; } } }

cmd_onewire_menu() { fprintf(dfp,"\nAvailable One-wire Maintenance Commmands\n"); fprintf(dfp,"----------------------------------------\n"); fprintf(dfp,"r : Read data from all one-wire devices available\n"); #if 0 fprintf(dfp,"w : Write hex_value to Telephony control register\n"); fprintf(dfp,"s : Read 2-Wire & Telephony Status Registers\n"); fprintf(dfp,"r : Read memory at addr\n"); fprintf(dfp,"w : Write hex_value to addr\n"); fprintf(dfp,"m : Direct Connect Debug port to Socket Modem\n"); #endif fprintf(dfp,"? or h : Display this menu\n"); fprintf(dfp,"\n");

}

/* init1wire() - Initializes all 1-wire devices on 1-wire bus */ int init1wire(short ow_bus_num) { short device_num; short first_time; unsigned char *romptr; short ow_valid; short i;

/* Initialize ROM, App reg(PROM), and EEPROM local storage = 0 */ for (device_num=0; device_numaio,ACTRL_AIO1OW); if (data) out_byte |= 0x80; } break; case OW_BUS_AIO2: /* AIO #2 One Wire Bus */ for (i=0; i>=1; data = aio_ow_read(&fpga_ctrl->aio,ACTRL_AIO2OW); if (data) out_byte |= 0x80; } break; } return(out_byte); }

void write_ow_bit(short ow_bus_num,short value) { short data;

switch (ow_bus_num) { case OW_BUS_MAIN: /* Main board one wire device interface */ main_ow_write(value); break; case OW_BUS_AIO1: /* AIO #1 One Wire Bus */ aio_ow_write(&fpga_ctrl->aio,ACTRL_AIO1OW,value); break; case OW_BUS_AIO2: /* AIO #2 One Wire Bus */ aio_ow_write(&fpga_ctrl->aio,ACTRL_AIO2OW,value); break; } }

short read_ow_bit(short ow_bus_num) { short data;

switch (ow_bus_num) { case OW_BUS_MAIN: /* Main board one wire device interface */ data = main_ow_read(); break; case OW_BUS_AIO1: /* AIO #1 One Wire Bus */ data = aio_ow_read(&fpga_ctrl->aio,ACTRL_AIO1OW); break; case OW_BUS_AIO2: /* AIO #2 One Wire Bus */ data = aio_ow_read(&fpga_ctrl->aio,ACTRL_AIO2OW); break; } return(data); }

void write_ow_byte(short ow_bus_num,short out_byte) { short i;

switch (ow_bus_num) { case OW_BUS_MAIN: /* Main board one wire device interface */ for (i=0; i>= 1; } break; case OW_BUS_AIO1: /* AIO #1 One Wire Bus */ for (i=0; iaio,ACTRL_AIO1OW,out_byte&1); out_byte >>= 1; } break; case OW_BUS_AIO2: /* AIO #2 One Wire Bus */ for (i=0; iaio,ACTRL_AIO2OW,out_byte&1); out_byte >>= 1; } break; } }

int reset_ow(short ow_bus_num) { short presense_pulse=0;

switch (ow_bus_num) { case OW_BUS_MAIN: /* Main board one wire device interface */ presense_pulse = main_ow_reset(); break; case OW_BUS_AIO1: /* AIO #1 One Wire Bus */ fpga_ctrl->aio |= ACTRL_AIO1OW; fpga_ctrl->aio &= ~ACTRL_AIO1OW; /* wait for 500us */ WAIT_US(500); /* Pull high */ fpga_ctrl->aio |= ACTRL_AIO1OW; /* Wait for presense pulse */ WAIT_US(70); /* Read presense */ if((fpga_ctrl->aio&ACTRL_AIO1OW)==0) presense_pulse=1; break; case OW_BUS_AIO2: /* AIO #2 One Wire Bus */ fpga_ctrl->aio |= ACTRL_AIO2OW; fpga_ctrl->aio &= ~ACTRL_AIO2OW; /* wait for 500us */ WAIT_US(500); /* Pull high */ fpga_ctrl->aio |= ACTRL_AIO2OW; /* Wait for presense pulse */ WAIT_US(70); /* Read presense */ if((fpga_ctrl->aio&ACTRL_AIO2OW)==0) presense_pulse=1; break; } WAIT_US(500); return(presense_pulse); }

void match_ow_device(short bus_num, short device_num) { short i;

reset_ow(bus_num); write_ow_byte(bus_num,OW_CMD_MATCH_ROM); write_ow_array(bus_num,bm.cfg.ow_device[bus_num][device_num].rom,8); }

/* ow_read_scrach(OW_BUS_MAIN,device_num) */ read_ow_scratch(short bus_num,short device_num,unsigned char *data) { short j; /* select one-wire device */ match_ow_device(bus_num,device_num);

write_ow_byte(bus_num,OW_CMD_READ_SCRATCH); /* Start at address 0 */ write_ow_byte(bus_num,0); read_ow_array(bus_num,data,32); }

/********************************************************************* One-wire Temperature Sensor DS1822 Functions

*********************************************************************/

find_ow_temp() { short i; for (i=0; i>4|((short)(data[1]&0x7))last) { /* set rom(bit_index) to 0 */ rom[bit_index] = 0; mark = bit_index; } else { /* Check if rom(bit_index) = 0 */ if (rom[bit_index]==0) { mark = bit_index; } } } } else { /* Set rom(bit_index) to bit_a */ rom[bit_index] = bit_a; }

/* Send rom(bit_index) to 1-wire bus */ write_ow_bit(ow_bus_num,rom[bit_index]);

bit_index++; } while(bit_index

Reply to
rickman

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.