1-Wire Core

From embeddedTS Manuals

This core allows the board to act as a 1-Wire master to communicate with Dallas/Maxim 1-Wire buses. This core contains only 1 16-bit register and works by doing 1-wire read/write ops 8-bits at a time.

Register Map
Offset Bits Access Description
0x0 15-13 Read/Write LUN select (0-7)
12 Read Only Busy
12 Write Only Special CMD Enable [1]
11-8 Read/Write Bytes to read [2]
7-0 Read/Write Read data, write data, or special CMD
  1. When "special cmd" bit 12 is set, bits 7-0 have special meaning. Refer to the special commands table.
  2. While there are bytes to be read, writes will be ignored. You can write 0x0 to immediately perform a write. See the bytes to read table for values and how the data is returned.
Special Commands
Command Description
8'b0000_0000 no-op
8'b1xxx_xxxx Initiate 1-wire reset, presence returned in bit 0. Short detect return in bit 1.
8'b01xx_xxxx 1-bit write, bit written is bit 0
Bytes to Read
Value Read size
0x0 Read disabled
0x1 1 byte
0x2 2 bytes
... ...
0xd 13 bytes
0xe 1 bit (returned in data bit 7)
0xf 2 bits (returned in data bits 6 and 7)

This example below is for talking to a Maxim DS401 chip with a unique serial number. Since all 1-Wire devices contain a unique serial, this should be applicable for most devices.

#include <stdio.h>
#include <unistd.h>

#define OW_ADDR 0x58

unsigned char ow_read8()
{
	unsigned short ret;

	sbuslock();
	ret = sbus_peek16(OW_ADDR);
	sbusunlock();

//	printf("Ret: 0x%x\n", ret);

	// Check for busy bit
	if(ret & (1 << 12)) {
		printf("Busy... retrying\n");
		usleep(1);
		ret = ow_read8();
	}

	return (char)ret & 0xff;
}

unsigned short ow_write8(unsigned short val)
{
	sbuslock();
	sbus_poke16(OW_ADDR, val);
	sbusunlock();
}

int main()
{
	unsigned short ret;
	unsigned short crc;
	unsigned short fcode;
	unsigned long long serial = 0;
	int i;

	// Send reset
	ow_write8(0x1080);

	// Detect presence of 1-wire device
	ret = ow_read8();

	if(!(ret & (1 << 0))) {
		fprintf(stderr, "No presence detected on the one wire bus\n");
		return;
	}

	// Send Read ROM command 0x33, and request 8 bytes
	ow_write8(0x833);

	fcode = ow_read8();

	// Read in 48 bits of the serial
	for(i=0; i < 6; i++) {
		serial |= ((unsigned long long) (ow_read8() & 0xff) << (8*i));
	}
	crc = ow_read8();;

	printf("serial: 0x%llx\n", serial);
}