DS1820 - Programming the User EEPROM and Calculating the CRC
/* Program 1820_3.C
**
** Illustrates how to write to and read from the two user EEPROM locations
** on the Dallas DS1820. These might be used to store trips points, but
** may be used in any application where user defined parameters must be
** stored.
**
** For illustration 0x4f and 0x3a are written to the user EEPROM. This is
** then read and displayed on the console.
**
** Note that the error handling has been improved;
**
** In _1w_init(), TRUE or FALSE is returned if the sensor was
** or wasn't detected.
**
** An 8-bit cyclic redundancy check is performed on the nine bytes
** received from the DS1820. A discussion of the CRC appears
** at http://www.phanderson.com/PIC/
**
** copyright, Peter H. Anderson, Towanda Malone, Baltimore, MD, Oct, '00
*/
#include <stdio.h>
#include <dos.h>
#include <conio.h>
#define SEG 0xf000
#define P2_OFFSET 0xff10
#define PM2_OFFSET 0xff11
#define PMC2_OFFSET 0xff12
#define TRUE !0
#define FALSE 0
#define DEBUG
typedef unsigned char byte;
byte write_user_bytes(byte sensor, byte ub1, byte ub2);
byte read_user_bytes(byte sensor, byte *p_ub1, byte *p_ub2);
byte calc_crc(byte buff[], byte num_vals);
byte _1w_init(byte sensor);
byte _1w_in_byte(byte sensor);
void _1w_out_byte(byte sensor, byte d);
void _1w_pin_hi(byte sensor);
void _1w_pin_low(byte sensor);
void _1w_strong_pull_up(byte sensor);
byte far *p2, far *pm2, far *pmc2; /* note global */
void main(void)
{
byte ub1, ub2;
p2 = MK_FP(SEG, P2_OFFSET);
pm2 = MK_FP(SEG, PM2_OFFSET);
pmc2 = MK_FP(SEG, PMC2_OFFSET);
*pmc2 = 0x00;
*pm2 = 0xff; /* all of port 2 are inputs */
clrscr();
if (!write_user_bytes(0, 0x4f, 0x3a))
{
printf("Write Failed\n");
exit(0);
}
if (!read_user_bytes(0, &ub1, &ub2))
{
printf("Read Failed\n");
exit(0);
}
printf("%0.2x %0.2x\n", ub1, ub2);
}
byte write_user_bytes(byte sensor, byte ub1, byte ub2)
{
if (!_1w_init(sensor))
{
return(FALSE); /* no sensor detected */
}
_1w_out_byte(sensor, 0xcc); /* skip ROM */
_1w_out_byte(sensor, 0x4e); /* write to scratch pad */
_1w_out_byte(sensor, ub1);
_1w_out_byte(sensor, ub2);
if (!_1w_init(sensor))
{
return(FALSE);
}
_1w_out_byte(sensor, 0xcc); /* skip ROM */
_1w_out_byte(sensor, 0x48); /* scratch pad to eeprom */
_1w_strong_pull_up(sensor);
return(TRUE);
}
byte read_user_bytes(byte sensor, byte *p_ub1, byte *p_ub2)
{
byte buff[9], crc, n;
if (!_1w_init(sensor))
{
return(FALSE);
}
_1w_out_byte(sensor, 0xcc); /* skip ROM */
_1w_out_byte(sensor, 0xb8); /* EEPROM to scrath pad */
if (!_1w_init(sensor))
{
return(FALSE);
}
_1w_out_byte(sensor, 0xcc); /* skip ROM */
_1w_out_byte(sensor, 0xbe); /* EEPROM to scratch pad */
for (n=0; n<9; n++)
{
buff[n] = _1w_in_byte(sensor);
#ifdef DEBUG
printf("%0.2x ", buff[n]);
#endif
}
#ifdef DEBUG
printf("\n");
#endif
crc = calc_crc(buff, 9);
if (crc) /* if it is non zero, there must have been an error */
{
printf("%0.2x ...........\n", crc);
return(FALSE);
}
*p_ub1 = buff[2];
*p_ub2 = buff[3];
return(TRUE);
}
byte calc_crc(byte buff[], byte num_vals)
{
byte shift_reg=0, data_bit, sr_lsb, fb_bit, i, j;
for (i=0; i<num_vals; i++) /* for each byte */
{
for(j=0; j<8; j++) /* for each bit */
{
data_bit = (buff[i]>>j)&0x01;
sr_lsb = shift_reg & 0x01;
fb_bit = (data_bit ^ sr_lsb) & 0x01;
shift_reg = shift_reg >> 1;
if (fb_bit)
{
shift_reg = shift_reg ^ 0x8c;
}
}
}
return(shift_reg);
}
byte _1w_init(byte sensor)
{
/* brings DQ low for 500 usecs and then back to high Z. Returns
** TRUE if presence pulse dected from DS1820 */
byte i, j;
_1w_pin_low(sensor);
for(i=167; i>0; i--) ; /* bring low for 500 us */
_1w_pin_hi(sensor);
for (j=0; j<100; j++)
{
if ((*(p2) & 0x01) == 0) /* if it goes to zero, it is present */
{
for(i=167; i>0; i--) ; /* assure high for 500 us */
return(TRUE);
}
}
return (FALSE); /* DS1820 never went to zero */
}
byte _1w_in_byte(byte sensor)
{
byte m, n, i_byte=0, temp, mask_0, mask_1;
mask_1 = 0x01<<sensor;
mask_0 = ~mask_1;
for (n=0; n<8; n++)
{
*p2 = 0x00;
*pm2 = mask_0;
*pm2 = 0xff;
temp = *p2;
if (temp & mask_1)
{
i_byte=(i_byte>>1) | 0x80; /* least sig bit first */
}
else
{
i_byte=i_byte >> 1;
}
for(m=19; m>0; m--) /* 60 us */ ;
}
return(i_byte);
}
void _1w_out_byte(byte sensor, byte d)
{
byte m, n, mask_0, mask_1;
mask_1 = 0x01<<sensor;
mask_0 = ~mask_1;
for(n=0; n<8; n++)
{
if (d&0x01)
{
*p2 = 0x00;
*pm2 = mask_0;
*pm2 = 0xff;
for(m=19; m>0; m--) /* 60 us */ ;
}
else
{
*p2 = 0x00;
*pm2 = mask_0;
for(m=19; m>0; m--) /* 60 us */ ;
*pm2 = 0xff;
}
d=d>>1;
}
}
void _1w_pin_hi(byte sensor)
{
*pm2 = 0xff;
}
void _1w_pin_low(byte sensor)
{
byte mask_0, mask_1;
mask_1 = 0x01 << sensor;
mask_0 = ~mask_1;
*p2 = mask_0;
*pm2 = mask_0;
}
void _1w_strong_pull_up(byte sensor)
{
byte mask_0, mask_1;
mask_1 = 0x01 << sensor;
mask_0 = ~mask_1;
*p2 = mask_1; /* bring bit to a hard logic one */
*pm2 = mask_0; /* dirs configured as output */
delay(500);
*pm2 = 0xff;
}