PIC C, Interfacing with a Dallas DS2401 Silicon Serial Number
// Program 2401_1.C (CCS PCM, PIC16F84)
//
// Illustrates use of DS2401 Silicon Serial Number.
//
// Reads 64 bit serial number, saves in 8-bit data buffer and displays
// on serial PIC-an-LCD in the form XXXX YYYY where X or Y is a two digit
// hex number.
//
// PIC16F84 DS2401
//
// PWR_ON (RA.1, term 18) --
// |
// 4.7K
// |
// ID_DQ (RB.0, term 6) -------------------- DQ
//
// Note that power to the DS2401 is only turned on when reading the
// ID. Such power savings might be important in data logging
// applications.
//
// Note that the 1-Wire routines may be used with any Dallas 1-W Device;
// e.g., DS1820.
//
// copyright, P. H. Anderson, Georgetown Co, SC, Mar, '99
#case
#include <16F84.h>
#include <string.h>
#include <defs_f84.h>
#define TxData 0 // RA.0 - interface to serial LCD
#define PWR_ON_PIN ra1 // RA.1 - power to DS2401
#define PWR_ON_DIR trisa1
#define ID_DQ_PIN rb0 // RB.0 - DQ for DS2401
#define ID_DQ_DIR trisb0
void read_2401_id(int sensor, int *buff);
// 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 buff[8], n, ch;
read_2401_id(0, buff); // fetch the silicon ID
lcd_init();
for (n=0; n<4; n++) // display the first 4 bytes
{
lcd_hex_byte(buff[n]);
}
lcd_char(' '); // followed by a space
for (n=4; n<8; n++)
{
lcd_hex_byte(buff[n]); // last four bytes
}
}
void read_2401_id(int sensor, int *buff)
{
int n;
// turn on power, set ID_DQ to high impedance
PWR_ON_DIR = 0;
PWR_ON_PIN = 1;
ID_DQ_DIR = 1;
delay_ms(500); // wait for 500 ms to be sure the device
// has stabilized.
_1w_init(sensor);
_1w_out_byte(0x33, sensor); // read ROM
for (n=0; n<8; n++)
{
buff[n]=_1w_in_byte(sensor);
}
// turn off power and be sure ID_DQ is in high impedance state
PWR_ON_PIN = 0;
PWR_ON_DIR = 1;
ID_DQ_DIR = 1;
} // note that 8-byte ID is returned in array buff
// 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)
{
PORTB = 0x01 << sensor;
TRISB = 0xff & (~(0x01 << sensor));
delay_ms(250);
TRISB = 0xff;
}
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);
}
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
}
// LCD routines
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);
}