' ========================================================================= ' ' File....... DS1620_TO_LCD.BS2 ' Purpose.... ' Author..... Jon Williams -- Parallax, Inc. ' E-mail..... jwilliams@parallax.com ' Started.... ' Updated.... 30 NOV 2004 ' ' {$STAMP BS2p} ' {$PBASIC 2.5} ' ' ========================================================================= ' -----[ Program Description ]--------------------------------------------- ' -----[ Revision History ]------------------------------------------------ ' -----[ I/O Definitions ]------------------------------------------------- E PIN 1 ' LCD Enable (1 = enabled) RW PIN 2 ' Read/Write\ RS PIN 3 ' Reg Select (1 = char) LcdCtrl VAR DIRL ' dirs for all LCD control LcdDirs VAR DIRB ' dirs for I/O redirection LcdBusOut VAR OUTB LcdBusIn VAR INB DQ PIN 15 ' DS1620.1 (data I/O) Clock PIN 14 ' DS1620.2 Reset PIN 13 ' DS1620.3 ' -----[ Constants ]------------------------------------------------------- #DEFINE _LcdReady = ($STAMP >= BS2P) LcdCls CON $01 ' clear the LCD LcdHome CON $02 ' move cursor home LcdCrsrL CON $10 ' move cursor left LcdCrsrR CON $14 ' move cursor right LcdDispL CON $18 ' shift chars left LcdDispR CON $1C ' shift chars right LcdDDRam CON $80 ' Display Data RAM control LcdCGRam CON $40 ' Character Generator RAM LcdLine1 CON $80 ' DDRAM address of line 1 LcdLine2 CON $C0 ' DDRAM address of line 2 CTmpPos CON LcdLine1 + 8 FTmpPos CON LcdLine2 + 8 RdTmp CON $AA ' read temperature WrHi CON $01 ' write TH (high temp) WrLo CON $02 ' write TL (low temp) RdHi CON $A1 ' read TH RdLo CON $A2 ' read TL StartC CON $EE ' start conversion StopC CON $22 ' stop conversion WrCfg CON $0C ' write config register RdCfg CON $AC ' read config register DegSym CON 186 ' degrees symbol ' -----[ Variables ]------------------------------------------------------- addr VAR Word ' address pointer char VAR Byte ' character sent to LCD idx VAR Byte ' loop counter idx2 VAR Byte ' loop counter width VAR Nib ' width of field tempIn VAR Word ' raw temperature sign VAR tempIn.BIT8 ' 1 = negative temperature tempC VAR Word ' Celsius tempF VAR Word ' Fahrenheit ' -----[ EEPROM Data ]----------------------------------------------------- L1 DATA "TEMP 0.0 C", 0 L2 DATA " 0.0 F", 0 ' -----[ Initialization ]-------------------------------------------------- Initialize: PAUSE 500 ' let LCD self-initialize LcdCtrl = %11111110 ' setup pins for LCD LCD_Init: #IF _LcdReady #THEN LCDCMD E, %00110000 : PAUSE 5 ' 8-bit mode LCDCMD E, %00110000 : PAUSE 0 LCDCMD E, %00110000 : PAUSE 0 LCDCMD E, %00100000 : PAUSE 0 ' 4-bit mode LCDCMD E, %00101000 : PAUSE 0 ' 2-line mode LCDCMD E, %00001100 : PAUSE 0 ' no crsr, no blink LCDCMD E, %00000110 ' inc crsr, no disp shift #ELSE LcdBusOut = %0011 ' 8-bit mode PULSOUT E, 3 : PAUSE 5 PULSOUT E, 3 : PAUSE 0 PULSOUT E, 3 : PAUSE 0 LcdBusOut = %0010 ' 4-bit mode PULSOUT E, 3 char = %00101000 ' 2-line mode GOSUB LCD_Command char = %00001100 ' on, no crsr, no blink GOSUB LCD_Command char = %00000110 ' inc crsr, no disp shift GOSUB LCD_Command #ENDIF DS1620_Init: HIGH Reset ' alert the DS1620 SHIFTOUT DQ, Clock, LSBFIRST, [WrCfg, %10] ' use with CPU; free-run LOW Reset PAUSE 10 HIGH Reset SHIFTOUT DQ, Clock, LSBFIRST, [StartC] ' start conversions LOW Reset Setup_LCD: char = LcdCls GOSUB LCD_Command PAUSE 1 addr = L1 GOSUB LCD_Put_String char = LcdLine2 GOSUB LCD_Command addr = L2 GOSUB LCD_Put_String ' -----[ Program Code ]---------------------------------------------------- Main: DO GOSUB Get_Temperature ' read the DS1620 DEBUG HOME, "DS1620", CR, "------", CR, DegSym, "C:", " " + (tempC.BIT15 * 13), DEC (ABS tempC / 10), ".", DEC1 (ABS tempC), CR, DegSym, "F:", " " + (tempF.BIT15 * 13), DEC (ABS tempF / 10), ".", DEC1 (ABS tempF), CR char = CTmpPos ' move to C temp position GOSUB LCD_Command tempIn = tempC GOSUB Temp_To_LCD ' write C temp to LCD char = FTmpPos ' move to F temp position GOSUB LCD_Command tempIn = tempF GOSUB Temp_To_LCD ' write F temp to LCD PAUSE 1000 ' pause between readings LOOP ' -----[ Subroutines ]----------------------------------------------------- ' Send command to LCD ' -- put command byte in 'char' LCD_Command: ' write command to LCD #IF _LcdReady #THEN LCDCMD E, char RETURN #ELSE LOW RS GOTO LCD_Write #ENDIF ' Write character to current cursor position ' -- but byte to write in 'char' LCD_Write: ' write character to LCD #IF _LcdReady #THEN LCDOUT E, 0, [char] #ELSE LcdBusOut = char.HIGHNIB ' output high nibble PULSOUT E, 3 ' strobe the Enable line LcdBusOut = char.LOWNIB ' output low nibble PULSOUT E, 3 HIGH RS ' return to character mode #ENDIF RETURN ' Reads byte from LCD ' -- put byte address in 'addr' ' -- returns byte read in 'char' LCD_Read: ' read character from LCD #IF _LcdReady #THEN LCDIN E, addr, [char] #ELSE char = addr ' move cursor GOSUB LCD_Command HIGH RS ' data command HIGH RW ' read LcdDirs = %0000 ' make LCD bus inputs HIGH E char.HIGHNIB = LcdBusIn ' get high nibble LOW E HIGH E char.LOWNIB = LcdBusIn ' get low nibble LOW E LcdDirs = %1111 ' return data lines to outputs LOW RW #ENDIF RETURN ' Writes stored (in DATA statement) zero-terminated string to LCD ' -- position LCD cursor ' -- point to 0-terminated string (first location in 'addr') LCD_Put_String: DO READ addr, char IF (char = 0) THEN EXIT GOSUB LCD_Write addr = addr + 1 LOOP RETURN ' Reads temperature from DS1620 ' -- returns values in 'tempC' and 'tempF' ' -- resolution is 0.5 degrees C (0.9 F) Get_Temperature: HIGH Reset ' alert the DS1620 SHIFTOUT DQ, Clock, LSBFIRST, [RdTmp] ' give command to read temp SHIFTIN DQ, Clock, LSBPRE, [tempIn\9] ' read it in LOW Reset ' release the DS1620 IF (sign = 0) THEN ' temp C is positive tempC = tempIn * 5 ' convert to tenths tempF = tempC * 9 / 5 + 320 ' convert to F ELSE ' temp C is negative tempC = tempIn | $FF00 * 5 ' convert to negative tenths tempF = 320 - ((ABS tempC) * 9 / 5) ' convert to F ENDIF RETURN ' Writes a (right-justified) 3.1 digit value to the LCD ' -- move cursor before calling this routine ' -- pass temp to display in 'tempIn' ' -- displays sign as " " (positive) or "-" Temp_To_LCD: IF (tempIn.BIT15) THEN ' check sign bit char = "-" ELSE char = " " ENDIF GOSUB LCD_Write ' write sign char tempIn = ABS tempIn ' remove sign from value ' pad value with spaces LOOKDOWN tempIn, <[10, 100, 1000, 10000], width LOOKUP width, [2, 2, 1, 0], idx ' calculate space pad char = " " DO WHILE (idx > 0) ' write the pad GOSUB LCD_Write idx = idx - 1 LOOP LOOKUP width, [1, 1, 2, 3], idx2 ' get first digit to print FOR idx = idx2 TO 0 ' loop through digits char = tempIn DIG idx + "0" ' convert digit to ASCII GOSUB LCD_Write ' write it IF (idx = 1) THEN char = LcdCrsrR GOSUB LCD_Command ' skip over dec point ENDIF NEXT RETURN