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