DS2430 256-bit EEPROM


Overview

The DS2430 1-W 256-bit EEPROM might be used as a silicon serial number to uniquely identify a product and also to store site dependent data and calibration data.

A more complete discussion in the context of a PIC12C509 appears elsewhere.


// Program 2430_1.C (CCS PCM - PIC16F84)
//
// Illustrates use of DS2430A 1-W 256 bit EEPROM.
//
// Writes 8 bytes to DS2430A beginning at address 0x06 and then
// reads them back and displays them on serial LCD on RA.0.
//
// 16F84                                   DS2430A
// RB.0 (term 6) ------------------------------ DQ (term 2)
//
// copyright, P. H. Anderson, Baltimore, MD, Apr, '99

#case
#include <16F84.h>
#include <defs_f84.h>

#define TxData 0  // RA.0 for LCD display

void write_ds2430(int sensor, int adr, int *buff, int num_vals);
void read_ds2430(int sensor, int adr, int *buff, int num_vals);

// 1-wire prototypes
void _1w_init(int sensor);
int _1w_in_byte(int sensor);
void _1w_out_byte(int d, int sensor);
void _1w_pin_hi(int sensor);
void _1w_pin_low(int sensor);
void _1w_strong_pull_up(int sensor);	// not used in this routine

// delay routines
void delay_ms(long t);
void delay_10us(int t);

// LCD routines
void lcd_init(void);
void out_RAM_str(int *s);
void lcd_hex_byte(int val);
void lcd_dec_byte(int val, int digits);
int num_to_char(int val);
void lcd_char(int ch);
void lcd_new_line(void);


void main(void)
{
   int d[8]={0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e};
   // data to write to EEPROM

   int buff[8], n;

   lcd_init();
   write_ds2430(0, 6, d, 8);
         // sensor 0, adr 6, array d, 8 bytes
   read_ds2430(0, 6, buff, 8);
   	// sensor 0, adr 6, array buff, 8 bytes
   for(n=0; n<8; n++)
   {
      if ((!(n%4)) && (n!=0))   // 4 bytes to a line
      {
         lcd_new_line();
      }
      lcd_hex_byte(buff[n]);
      lcd_char(' ');
   }
   lcd_new_line();
}

void write_ds2430(int sensor, int adr, int *buff, int num_vals)
// write num_vals in array buff beginning at address adr
{
   int n;
   _1w_init(sensor);
   _1w_out_byte(0xcc, sensor);	// skip ROM
   _1w_out_byte(0xf0, sensor);	// read memory into scratch pad

   _1w_init(sensor);
   _1w_out_byte(0xcc, sensor);	// skip ROM
   _1w_out_byte(0x0f, sensor);	// write scratch pad

   _1w_out_byte(adr, sensor);	// starting address
   for(n=0; n<num_vals; n++)
   {
      _1w_out_byte(buff[n], sensor);
   }

   _1w_init(sensor);
   _1w_out_byte(0xcc, sensor);	// skip ROM
   _1w_out_byte(0x55, sensor);	// copy scratch pad

   _1w_out_byte(0xa5, sensor); 	// validation key

   _1w_strong_pull_up(sensor);	// while programming
}

void read_ds2430(int sensor, int adr, int *buff, int num_vals)
// reads num_vals bytes into array buff beginning at address adr
{
   int n;
   _1w_init(sensor);
   _1w_out_byte(0xcc, sensor);	// skip ROM
   _1w_out_byte(0xf0, sensor);	// read memory into scratch pad

   _1w_out_byte(adr, sensor);

   for(n=0; n<num_vals; n++)
   {
      buff[n]=_1w_in_byte(sensor);
   }
}

// The following are standard 1-Wire routines.
void _1w_init(int sensor)
{
   _1w_pin_hi(sensor);
   _1w_pin_low(sensor);
   delay_10us(50);

   _1w_pin_hi(sensor);
   delay_10us(50);
}

int _1w_in_byte(int sensor)
{
   int n, i_byte, temp, mask;
   mask = 0xff & (~(0x01<<sensor));
   for (n=0; n<8; n++)
   {
      PORTB=0x00;
      TRISB=mask;
      TRISB=0xff;
#asm
      CLRWDT
      NOP
      NOP
#endasm
      temp=PORTB;
      if (temp & ~mask)
      {
        i_byte=(i_byte>>1) | 0x80;	// least sig bit first
      }
      else
      {
        i_byte=i_byte >> 1;
      }
      delay_10us(6);
   }
   return(i_byte);
}

void _1w_out_byte(int d, int sensor)
{
   int n, mask;
   mask = 0xff & (~(0x01<<sensor));
   for(n=0; n<8; n++)
   {
      if (d&0x01)
      {
         PORTB=0;
         TRISB=mask;		// momentary low
         TRISB=0xff;
         delay_10us(6);
      }

      else
      {
          PORTB=0;
          TRISB=mask;
	  delay_10us(6);
          TRISB=0xff;
      }
      d=d>>1;
   }
}

void _1w_pin_hi(int sensor)
{
   TRISB = 0xff;
}

void _1w_pin_low(int sensor)
{
   PORTB = 0x00;
   TRISB = 0xff & (~(0x01 << sensor));
}

void _1w_strong_pull_up(int sensor)	// bring DQ to strong +5VDC
{
   PORTB = 0x01 << sensor;
   TRISB = 0xff & (~(0x01 << sensor));
   delay_ms(250);
   TRISB = 0xff;
}

// delay routines
void delay_10us(int t)
{
#asm
      BCF STATUS, RP0
DELAY_10US_1:
      CLRWDT
      NOP
      NOP
      NOP
      NOP
      NOP
      NOP
      DECFSZ t, F
      GOTO DELAY_10US_1
#endasm
}

void delay_ms(long t)	// delays t millisecs
{
   do
   {
     delay_10us(100);
   } while(--t);
}


// LCD routines
int num_to_char(int val)	// converts val to hex character
{
   int ch;
   if (val < 10)
   {
     ch=val+'0';
   }
   else
   {
     val=val-10;
     ch=val + 'A';
   }
   return(ch);
}

void lcd_char(int ch)	// serial output to PIC-n-LCD, 9600 baud
{
   int n, dly;
   		// start bit + 8 data bits

#asm
       BCF STATUS, RP0
       MOVLW 9
       MOVWF n
       BCF STATUS, C

LCD_CHAR_1:

       BTFSS STATUS, C
       BSF PORTA, TxData
       BTFSC STATUS, C
       BCF PORTA, TxData
       MOVLW 32
       MOVWF dly

LCD_CHAR_2:
       DECFSZ dly, F
       GOTO LCD_CHAR_2
       RRF ch, F
       DECFSZ n, F
       GOTO LCD_CHAR_1

       BCF PORTA, TxData
       CLRWDT
       MOVLW 96
       MOVWF dly

LCD_CHAR_3:
       DECFSZ dly, F
       GOTO LCD_CHAR_3
       CLRWDT
#endasm
}

void lcd_init(void)	// sets TxData in idle state and resets PIC-n-LCD
{
#asm
        BCF STATUS, RP0
        BCF PORTA, TxData
        BSF STATUS, RP0
        BCF TRISA, TxData
        BCF STATUS, RP0
#endasm
   lcd_char(0x0c);
   delay_ms(250);
}

void lcd_new_line(void)	// outputs 0x0d, 0x0a
{
   lcd_char(0x0d);
   delay_ms(10);	// give the PIC-n-LCD time to perform the
   lcd_char(0x0a);	// new line function
   delay_ms(10);
}

void out_RAM_str(int s)
{
   while(*s)
   {
      lcd_char(*s);
      ++s;
   }
}

void lcd_hex_byte(int val) // displays val in hex format
{
   int ch;
   ch = num_to_char((val>>4) & 0x0f);
   lcd_char(ch);
   ch = num_to_char(val&0x0f);
   lcd_char(ch);
}

void lcd_dec_byte(int val, int digits)
// displays byte in decimal as either 1, 2 or 3 digits
{
   int d;
   int ch;
   if (digits == 3)
   {
      d=val/100;
      ch=num_to_char(d);
      lcd_char(ch);
   }
   if (digits >1)	// take the two lowest digits
   {
       val=val%100;
       d=val/10;
       ch=num_to_char(d);
       lcd_char(ch);
   }
   if (digits == 1)	// take the least significant digit
   {
       val = val%100;
   }

   d=val % 10;
   ch=num_to_char(d);
   lcd_char(ch);
}