/******* SSN.c ***************** * * Read the DS2401 serial number and then sleep with RD3 high and RD2 = input * Use Fosc = 4 MHz for Fcpu = Fosc/4 = 1 MHz. * Developed by Alex Singh. * ******* Program hierarchy ***** * * main * Initial * InitTX * DS2401 * PresenceTest * SendByte * ReadByte * SaveByte * SendSSNSTRING * ******************************* */ #include // Define PIC18LF4321 registers and bits /******************************* * Configuration selections ******************************* */ #pragma config OSC = INTIO1 // Use internal osc, RA6=Fosc/4, RA7=I/O #pragma config PWRT = ON // Enable power-up delay #pragma config LVP = OFF // Disable low-voltage programming #pragma config WDT = OFF // Disable watchdog timer initially #pragma config MCLRE = ON // Enable master clear pin #pragma config PBADEN = DIG // PORTB<4:0> = digital #pragma config CCP2MX = RB3 // Connect CCP2 internally to RB3 pin #pragma config BOR = SOFT // Brown-out reset controlled by software #pragma config BORV = 3 // Brown-out voltage set for 2.0V, nominal #pragma config LPT1OSC = OFF // Deselect low-power Timer1 oscillator /******************************* * Global variables ******************************* */ unsigned char i, j; // Loop counters unsigned int DELAY; // Sixteen-bit counter for obtaining a delay unsigned char BYTETOSEND; // Used by SendByte unsigned char SSNBYTE; // Used to store byte read from DS2401 char SSNSTRING[20] = "xxxxxxxxxxxxxxxx\n\r\0"; // To hold DS2401's serial number /******************************* * Constant array in program memory ******************************* */ const char rom FormHex[] = "0123456789ABCDEF"; /******************************* * Function prototypes ******************************* */ void Initial(void); void InitTX(void); void DS2401(void); char PresenceTest(void); void SendByte(void); void ReadByte(void); void SaveByte(void); void SendSSNSTRING(void); /******************************* * Macros ******************************* */ #define Delay(x) DELAY = x; while(--DELAY){ Nop(); Nop(); } #define TXascii(in) TXREG = in; while(!TXSTAbits.TRMT) #define OpenDrainHigh TRISDbits.TRISD2 = 1 #define OpenDrainLow PORTDbits.RD2 = 0; TRISDbits.TRISD2 = 0 /////// Main program ////////////////////////////////////////////////////////// /******************************* * main ******************************* */ void main() { Initial(); // Initialize everything InitTX(); // Initialize UART DS2401(); // Read and display SSN on PC Sleep(); // Done Nop(); } /******************************* * Initial * * This function performs all initializations of variables and registers. ******************************* */ void Initial() { OSCCON = 0b01100010; // Use Fosc = 4 MHz (Fcpu = 1 MHz) SSPSTAT = 0b00000000; // Set up SPI for output to LCD SSPCON1 = 0b00110000; ADCON1 = 0b00001011; // RA0,RA1,RA2,RA3 pins analog; others digital TRISA = 0b00001111; // Set I/O for PORTA TRISB = 0b01000100; // Set I/O for PORTB TRISC = 0b10000000; // Set I/O for PORTC TRISD = 0b10000100; // Set I/O for PORTD TRISE = 0b00000010; // Set I/O for PORTE PORTA = 0; // Set initial state for all outputs low PORTB = 0; PORTC = 0; PORTD = 0b00100000; // except RD5 that drives LCD interrupt PORTE = 0; Delay(50000); // Pause for 0.5 second for contact bounce RCONbits.SBOREN = 0; // After this delay, disable brown-out reset } /******************************* * InitTX * * This function initializes the UART for its TX output function. * It assumes Fosc = 4 MHz. ******************************* */ void InitTX() { RCSTA = 0b10010000; // Enable UART TXSTA = 0b00100000; // Enable TX SPBRG = 12; // Set baud rate BAUDCON = 0b00111000; // Invert TX output } /******************************* * DS2401 * * This function displays on the PC the serial number given * by the DS2401. If it is not present, turn on red LED and halt. ******************************* */ void DS2401() { PORTDbits.RD3 = 1; // Apply power to SSN part OpenDrainLow; Delay(50); // Master Reset with 500 us negative pulse OpenDrainHigh; if(!PresenceTest()) // Presence Test { PORTDbits.RD4 = 1; // Turn on LED Sleep(); // and be done Nop(); } else { BYTETOSEND = 0x33; // Send "Read ROM" command to get back SendByte(); // serial number for (j = 16; j > 0; j-=2) // Read and save 8 bytes { ReadByte(); SaveByte(); } SendSSNSTRING(); } OpenDrainHigh; // Leave I/O pin as an input PORTDbits.RD3 = 1; // Leave SSN part empowered } /******************************* * PresenceTest * * This function returns a 1 if DS2401 is present and a 0 otherwise. ******************************* */ char PresenceTest() { Delay(10); // After 100 us if (!PORTDbits.RD2) // check for Presence { while (!PORTDbits.RD2); // Wait for line to be released return 1; } return 0; } /******************************* * SendByte * * This function sends BYTETOSEND to DS2401. Tslot = 85 us for ONE or for ZERO. ******************************* */ void SendByte() { for (i = 0; i <= 7; i++) // Send 8 bits of command { if (BYTETOSEND & 1) // Test bit 0 { OpenDrainLow; OpenDrainHigh; // Send ONE Delay(6); } else { OpenDrainLow; Delay(6); // Send ZERO OpenDrainHigh; } BYTETOSEND >>= 1; // Move on to next bit } } /******************************* * ReadByte * * This function reads in the 64-bit serial number a byte at a time. * Tslot = 70 us for ONE or for ZERO. * DS2401 holds line low for zero for 35 us. ******************************* */ void ReadByte() { SSNBYTE = 0; // initialize SSNBYTE for (i = 0; i <= 7; i++) // Read 8 bits from DS2401 { SSNBYTE >>= 1; // move on to next bit OpenDrainLow; OpenDrainHigh; Delay(1); // Sample 13 us after 'clocking' if (PORTDbits.RD2) { SSNBYTE += 0b10000000; // Copy bit into SSNBYTE } Delay(3); } } /******************************* * SaveByte * * This function converts the binary value in SSNBYTE into two * ASCII-coded digits in SSNSTRING. ******************************* */ void SaveByte() { SSNSTRING[j - 2] = FormHex[SSNBYTE >> 4]; // Save upper nibble SSNSTRING[j - 1] = FormHex[SSNBYTE & 0x0F]; // Save lower nibble } /******************************* * SendSSNSTRING * * This function sends SSNSTRING to the PC. ******************************* */ void SendSSNSTRING() { for (i=0; SSNSTRING[i]; ++i) { TXascii(SSNSTRING[i]); // send all bytes until null terminator } }