/* 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; }