DS1337C (RTC) with a backup battery
LM34
SERIAL(USART)
USB
SD card
A few extra pins for external circuitry
18F2550 with a 4 MHz resonator running at 48 MHz
In practice data is saved to the SD card along with a time and date stamp. The USB port is used for real time system monitoring if needed. Normal operation feed back is from one LED.
To set this up Darrel's Instant Interrupts will be needed. Thanks Darrel!!
http://www.picbasic.co.uk/forum/showthread.php?t=3251
SD card routines are from http://melabs.com/samples/PBP-mixed/sdfs3.htm for SD cards up to 2GB.
The USB will need six files copied from the PBP\USB18 directory to the project directory. This is for PBP 2.60, if another version of PBP is used the files will be different and not covered here.
cdc_desc.bas
usb_scd.asm
usb_cdc.inc
usb_dev.asm
usb_dev.inc
usb_mem.asm
click on schematic to view if it is to large here.
The first block of code does not write to the SD card. It is for testing the USB and RTC. The LED is a "heart beat" on this one.
The second code has the SD routines added in. Along with the SD routines some more feed back has been added.
If a SD card is not present the USB will still output the time, date, temperature, and now "NO CARD".
The LED will blink as a 1 Hz heart beat as the first code if a card is present and the card is not being written. If the card is being written to then the the LED blink will be faster and dimmer. Do not remove the SD card while it is being written to.
If the SD card is not present then the LED will be off.
Code:
'<FL_PIC18F2550>'
'<FL_PBPW>'
DEFINE OSC 48
@ __CONFIG _CONFIG1L, _PLLDIV_1_1L & _CPUDIV_OSC1_PLL2_1L & _USBDIV_2_1L
@ __CONFIG _CONFIG1H, _FOSC_HSPLL_HS_1H
@ __CONFIG _CONFIG2H, _WDT_OFF_2H & _WDTPS_512_2H
@ __CONFIG _CONFIG2L, _PWRT_ON_2L & _VREGEN_ON_2L
@ __CONFIG _CONFIG3H, _PBADEN_OFF_3H & _MCLRE_OFF_3H
@ __CONFIG _CONFIG4L, _LVP_OFF_4L & _XINST_OFF_4L
INCLUDE "cdc_desc.bas"
INCLUDE "DT_INTS-18.bas"
INCLUDE "ReEnterPBP-18.bas"
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler INT_INT, _CNT_PLUS, PBP, yes
INT_Handler USB_INT, _SERVICE_USB, ASM, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM
'#########
'START USB AND INTERRUPTS
PAUSE 100 'TIME TO SETTLE
USBINIT 'INITIALIZE USB
USBSERVICE 'SERVICE USB
UIE = $7F 'ENABLE USB INTERRUPTS
UEIE = $9F 'ENABLE USB ERROR INTERRUPTS
PAUSE 500 'MORE TIME
USBINIT
USBSERVICE
@ INT_ENABLE USB_INT
USBSERVICE
@ INT_ENABLE INT_INT
'#########
'VARs AND DEFINEs
ADCON1 = 001110
LED VAR PORTA.2
TEXT_TIME VAR BYTE[6]
TEXT_DATE VAR BYTE[6]
TEXT_TEMP VAR BYTE[8]
B0 VAR BYTE
B1 VAR BYTE
CNT VAR WORD
CRON VAR BYTE[11]
CRON_D VAR BYTE[11]
SPACE VAR BYTE[2]
T_BUFFER VAR BYTE[8]
T_ONES VAR BYTE
T_TENS VAR BYTE
T_HUNS VAR BYTE
OUT_TEMP VAR BYTE
ADC_TEMP VAR WORD
S_TEMP VAR BYTE
X_TEMP VAR BYTE
'RTC DEFINES
DS_SCL VAR PORTB.1 'CLOCK
DS_SDA VAR PORTB.2 'DATA
RTC CON 010000
SEC_REG CON $00
CONT_REG CON $0E
CNTRL CON 000000
'RTC VARS
sec VAR BYTE: mins VAR BYTE: hr VAR BYTE: day VAR BYTE
date VAR BYTE: mon VAR BYTE: yr VAR BYTE
'RTC DEC VARS
SEC_O VAR BYTE: SEC_T VAR BYTE: MIN_O VAR BYTE: MIN_T VAR BYTE
HR_O VAR BYTE: HR_T VAR BYTE: MON_O VAR BYTE: MON_T VAR BYTE
DATE_O VAR BYTE: DATE_T VAR BYTE: YR_O VAR BYTE: YR_T VAR BYTE
'#########
'SETS THE RTC TO PULSE OUT AT 1HZ
I2CWRITE DS_SDA, DS_SCL, RTC, CONT_REG, [CNTRL]
'BUILD SOME USB TEXT
FOR B0 = 0 TO 5
LOOKUP B0,[" TIME "],B1
TEXT_TIME(B0) = B1
NEXT B0
FOR B0 = 0 TO 5
LOOKUP B0,[" DATE "],B1
TEXT_DATE(B0) = B1
NEXT B0
FOR B0 = 0 TO 7
LOOKUP B0,[" TEMP F "],B1
TEXT_TEMP(B0) = B1
NEXT B0
SPACE[0] = $d
SPACE[1] = $a
'#########
'IF THE RTC NEEDS SET GOTO THE SET_RTC ROUTINE AND
'ENTER THE TIME AND DATE. RUN THE CODE ONCE THEN RE-COMMENT.
'GOSUB SET_RTC
'#########
'MAIN PROGRAM
CHECK:
IF CNT >= 60 THEN 'NUMBER OF SECONDS
CNT = 0
GOSUB GET_T
GOSUB READ_RTC
GOSUB USB_DISPLAY
ENDIF
GOTO CHECK
'#########
'#########
'ISRs
CNT_PLUS:
TOGGLE LED
CNT = CNT + 1
@ INT_RETURN
SERVICE_USB:
USBSERVICE
@ INT_RETURN
'#########
SET_RTC:
yr = $10
mon = $10
date = $09
sec = $00
mins = $52
hr = $02
I2CWRITE DS_SDA, DS_SCL, RTC, SEC_REG, [sec,mins,hr,day,date,mon,yr]
RETURN
'#########
READ_RTC:
I2CREAD DS_SDA, DS_SCL, RTC, SEC_REG, [sec,mins,hr,day,date,mon,yr]
SEC_T = sec & $70
SEC_T = SEC_T>>4
SEC_O = sec & $0F
MIN_T = mins & $70
MIN_T = MIN_T>>4
MIN_O = MINs & $0F
HR_T = hr & $70
HR_T = HR_T>>4
HR_O = hr & $0F
MON_T = mon & $70
MON_T = MON_T>>4
MON_O = mon & $0F
DATE_T = date & $70
DATE_T = DATE_T>>4
DATE_O = date & $0F
YR_T = yr & $70
YR_T = YR_T>>4
YR_O = yr & $0F
CRON[0] = " "
CRON[1] = $30+HR_T
CRON[2] = $30+HR_O
CRON[3] = ":"
CRON[4] = $30+MIN_T
CRON[5] = $30+MIN_O
CRON[6] = ":"
CRON[7] = $30+SEC_T
CRON[8] = $30+SEC_O
CRON[9] = $d
CRON[10] = $a
CRON_D[0] = " "
CRON_D[1] = $30+MON_T
CRON_D[2] = $30+MON_O
CRON_D[3] = "/"
CRON_D[4] = $30+DATE_T
CRON_D[5] = $30+DATE_O
CRON_D[6] = "/"
CRON_D[7] = $30+YR_T
CRON_D[8] = $30+YR_O
CRON_D[9] = $d
CRON_D[10] = $a
RETURN
'#########
GET_T:
ADC_TEMP = 0
FOR X_TEMP = 1 TO 20
ADCON0=00000001
GOSUB READ_AD
S_TEMP = ADRESH
ADC_TEMP = ADC_TEMP + S_TEMP
PAUSE 250
NEXT X_TEMP
OUT_TEMP = ADC_TEMP / 20
OUT_TEMP = OUT_TEMP * 13/10
T_HUNS = OUT_TEMP/100
T_TENS = (OUT_TEMP - T_HUNS * 100)/10
T_ONES = OUT_TEMP-((T_HUNS*100)+(T_TENS*10))
T_BUFFER[0] = $30+T_HUNS
T_BUFFER[1] = $30+T_TENS
T_BUFFER[2] = $30+T_ONES
T_BUFFER[3] = " "
T_BUFFER[4] = " "
T_BUFFER[5] = " "
T_BUFFER[6] = $d
T_BUFFER[7] = $a
RETURN
READ_AD:
PAUSE 50
ADCON0.1=1
WHILE ADCON0.2=1:WEND
RETURN
'#########
USB_DISPLAY:
PAUSE 1
USBOUT 3, SPACE, 2, CHECK
PAUSE 1
USBOUT 3, TEXT_TIME, 6, CHECK
PAUSE 1
USBOUT 3, CRON, 11, CHECK
PAUSE 1
USBOUT 3, TEXT_DATE, 6, CHECK
PAUSE 1
USBOUT 3, CRON_D, 11, CHECK
PAUSE 1
USBOUT 3, TEXT_TEMP, 8, CHECK
PAUSE 1
USBOUT 3, T_BUFFER, 8, CHECK
PAUSE 1
RETURN
Code:
'<FL_PIC18F2550>'
'<FL_PBPL>'
DEFINE OSC 48
@ __CONFIG _CONFIG1L, _PLLDIV_1_1L & _CPUDIV_OSC1_PLL2_1L & _USBDIV_2_1L
@ __CONFIG _CONFIG1H, _FOSC_HSPLL_HS_1H
@ __CONFIG _CONFIG2H, _WDT_OFF_2H & _WDTPS_512_2H
@ __CONFIG _CONFIG2L, _PWRT_ON_2L & _VREGEN_ON_2L
@ __CONFIG _CONFIG3H, _PBADEN_OFF_3H & _MCLRE_OFF_3H
@ __CONFIG _CONFIG4L, _LVP_OFF_4L & _XINST_OFF_4L
' Alias PIC pins and registers for SD/MMC card
SD_WE VAR PORTA.4 ' SD card write protect
SD_WE_TRIS VAR TRISA.4 ' SD card write protect direction
SDI VAR PORTA.5 ' SPI data in SD #7
SDI_TRIS VAR TRISA.5 ' SPI data in direction
SCL VAR PORTA.3 ' SPI clock SD #5
SCL_TRIS VAR TRISA.3 ' SPI clock direction
SD_CS VAR PORTC.2 ' SD card chip select SD #1
SD_CS_TRIS VAR TRISC.2 ' SD card chip select direction
SD_CD VAR PORTC.0 ' SD card detect
SD_CD_TRIS VAR TRISC.0 ' SD card detect direction
SDO VAR PORTC.1 ' SPI data out SD #2
SDO_TRIS VAR TRISC.1 ' SPI data out direction
INCLUDE "SDFS.BAS"
SDC_UseHardSPI = FALSE ' Use hardware SSP port for SPI.
INCLUDE "cdc_desc.bas"
INCLUDE "DT_INTS-18.bas"
INCLUDE "ReEnterPBP-18.bas"
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler INT_INT, _CNT_PLUS, PBP, yes
INT_Handler USB_INT, _SERVICE_USB, ASM, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM
'#########
'START USB AND INTERRUPTS
PAUSE 100 'TIME TO SETTLE
USBINIT 'INITIALIZE USB
USBSERVICE 'SERVICE USB
UIE = $7F 'ENABLE USB INTERRUPTS
UEIE = $9F 'ENABLE USB ERROR INTERRUPTS
PAUSE 500 'MORE TIME
USBINIT
USBSERVICE
@ INT_ENABLE USB_INT
USBSERVICE
@ INT_ENABLE INT_INT
'#########
'VARs AND DEFINEs
ADCON1 = 001110
LED VAR PORTA.2
TEXT_TIME VAR BYTE[6]
TEXT_DATE VAR BYTE[6]
TEXT_TEMP VAR BYTE[8]
TEXT_NO_CARD VAR BYTE[9]
MAC_FileName VAR BYTE[11]
B0 VAR BYTE
B1 VAR BYTE
CNT VAR WORD
CIU VAR BYTE 'CARD IN USE
CRON VAR BYTE[11]
CRON_D VAR BYTE[11]
SPACE VAR BYTE[2]
T_BUFFER VAR BYTE[8]
T_ONES VAR BYTE
T_TENS VAR BYTE
T_HUNS VAR BYTE
OUT_TEMP VAR BYTE
ADC_TEMP VAR WORD
S_TEMP VAR BYTE
X_TEMP VAR BYTE
'RTC DEFINES
DS_SCL VAR PORTB.1 'CLOCK
DS_SDA VAR PORTB.2 'DATA
RTC CON 010000
SEC_REG CON $00
CONT_REG CON $0E
CNTRL CON 000000
'RTC VARS
sec VAR BYTE: mins VAR BYTE: hr VAR BYTE: day VAR BYTE
date VAR BYTE: mon VAR BYTE: yr VAR BYTE
'RTC DEC VARS
SEC_O VAR BYTE: SEC_T VAR BYTE: MIN_O VAR BYTE: MIN_T VAR BYTE
HR_O VAR BYTE: HR_T VAR BYTE: MON_O VAR BYTE: MON_T VAR BYTE
DATE_O VAR BYTE: DATE_T VAR BYTE: YR_O VAR BYTE: YR_T VAR BYTE
'SD CARD FILE
FILE_seconds VAR BYTE: FILE_minutes VAR BYTE: FILE_hours VAR BYTE
FILE_day VAR BYTE: FILE_month VAR BYTE: FILE_year VAR BYTE
'#########
'SETS THE RTC TO PULSE OUT AT 1HZ
I2CWRITE DS_SDA, DS_SCL, RTC, CONT_REG, [CNTRL]
'SETS FILE NAME TO THE TIME BOARD IS POWERED
GOSUB READ_RTC
MAC_FileName[0] = $30+HR_T
MAC_FileName[1] = $30+HR_O
MAC_FileName[2] = $30+MIN_T
MAC_FileName[3] = $30+MIN_O
MAC_FileName[4] = $30+SEC_T
MAC_FileName[5] = $30+SEC_O
MAC_FileName[6] = " "
MAC_FileName[7] = " "
MAC_FileName[8] = "T"
MAC_FileName[9] = "X"
MAC_FileName[10] = "T"
'BUILD SOME USB TEXT
FOR B0 = 0 TO 5
LOOKUP B0,[" TIME "],B1
TEXT_TIME(B0) = B1
NEXT B0
FOR B0 = 0 TO 5
LOOKUP B0,[" DATE "],B1
TEXT_DATE(B0) = B1
NEXT B0
FOR B0 = 0 TO 7
LOOKUP B0,[" TEMP F "],B1
TEXT_TEMP(B0) = B1
NEXT B0
SPACE[0] = $d
SPACE[1] = $a
FOR B0 = 0 TO 9
LOOKUP B0,[" NO CARD",$d,$a],B1
TEXT_NO_CARD(B0) = B1
NEXT B0
'#########
'IF THE RTC NEEDS SET GOTO THE SET_RTC ROUTINE AND
'ENTER THE TIME AND DATE. RUN THE CODE ONCE THEN RE-COMMENT.
'GOSUB SET_RTC
'#########
'MAIN PROGRAM
CHECK:
IF CNT >= 60 THEN 'NUMBER OF SECONDS
CNT = 0
GOSUB GET_T
GOSUB READ_RTC
GOSUB USB_DISPLAY
IF (SD_WE = 0) AND (SD_CD = 0) THEN
GOTO SD_WRITE
ELSE
PWM LED,25,250
USBOUT 3, TEXT_NO_CARD, 10, CHECK
PAUSE 500
ENDIF
ENDIF
GOTO CHECK
'#########
'#########
'ISRs
CNT_PLUS:
IF CIU = 1 THEN
PWM LED,75,250
ELSE
IF (SD_WE = 0) AND (SD_CD = 0) THEN
TOGGLE LED
ELSE
LOW LED
ENDIF
ENDIF
CNT = CNT + 1
@ INT_RETURN
SERVICE_USB:
USBSERVICE
@ INT_RETURN
'#########
SET_RTC:
yr = $10
mon = $10
date = $09
sec = $00
mins = $52
hr = $02
I2CWRITE DS_SDA, DS_SCL, RTC, SEC_REG, [sec,mins,hr,day,date,mon,yr]
RETURN
'#########
READ_RTC:
I2CREAD DS_SDA, DS_SCL, RTC, SEC_REG, [sec,mins,hr,day,date,mon,yr]
SEC_T = sec & $70
SEC_T = SEC_T>>4
SEC_O = sec & $0F
MIN_T = mins & $70
MIN_T = MIN_T>>4
MIN_O = MINs & $0F
HR_T = hr & $70
HR_T = HR_T>>4
HR_O = hr & $0F
MON_T = mon & $70
MON_T = MON_T>>4
MON_O = mon & $0F
DATE_T = date & $70
DATE_T = DATE_T>>4
DATE_O = date & $0F
YR_T = yr & $70
YR_T = YR_T>>4
YR_O = yr & $0F
CRON[0] = " "
CRON[1] = $30+HR_T
CRON[2] = $30+HR_O
CRON[3] = ":"
CRON[4] = $30+MIN_T
CRON[5] = $30+MIN_O
CRON[6] = ":"
CRON[7] = $30+SEC_T
CRON[8] = $30+SEC_O
CRON[9] = $d
CRON[10] = $a
CRON_D[0] = " "
CRON_D[1] = $30+MON_T
CRON_D[2] = $30+MON_O
CRON_D[3] = "/"
CRON_D[4] = $30+DATE_T
CRON_D[5] = $30+DATE_O
CRON_D[6] = "/"
CRON_D[7] = $30+YR_T
CRON_D[8] = $30+YR_O
CRON_D[9] = $d
CRON_D[10] = $a
FILE_seconds = (SEC_T*10)+SEC_O
FILE_minutes = (MIN_T*10)+MIN_O
FILE_hours = (HR_T*10)+HR_O
FILE_day = (DATE_T*10)+DATE_O
FILE_month = (MON_T*10)+MON_O
FILE_year = (YR_T*10)+YR_O
RETURN
'#########
GET_T:
ADC_TEMP = 0
FOR X_TEMP = 1 TO 20
ADCON0=00000001
GOSUB READ_AD
S_TEMP = ADRESH
ADC_TEMP = ADC_TEMP + S_TEMP
PAUSE 250
NEXT X_TEMP
OUT_TEMP = ADC_TEMP / 20
OUT_TEMP = OUT_TEMP * 13/10
T_HUNS = OUT_TEMP/100
T_TENS = (OUT_TEMP - T_HUNS * 100)/10
T_ONES = OUT_TEMP-((T_HUNS*100)+(T_TENS*10))
T_BUFFER[0] = $30+T_HUNS
T_BUFFER[1] = $30+T_TENS
T_BUFFER[2] = $30+T_ONES
T_BUFFER[3] = " "
T_BUFFER[4] = " "
T_BUFFER[5] = " "
T_BUFFER[6] = $d
T_BUFFER[7] = $a
RETURN
READ_AD:
PAUSE 50
ADCON0.1=1
WHILE ADCON0.2=1:WEND
RETURN
'#########
USB_DISPLAY:
PAUSE 1
USBOUT 3, SPACE, 2, CHECK
PAUSE 1
USBOUT 3, TEXT_TIME, 6, CHECK
PAUSE 1
USBOUT 3, CRON, 11, CHECK
PAUSE 1
USBOUT 3, TEXT_DATE, 6, CHECK
PAUSE 1
USBOUT 3, CRON_D, 11, CHECK
PAUSE 1
USBOUT 3, TEXT_TEMP, 8, CHECK
PAUSE 1
USBOUT 3, T_BUFFER, 8, CHECK
PAUSE 1
RETURN
'#########
'SD CARD ROUTINES
SD_WRITE:
CIU = 1
SDINIT:
' FSInit initializes the card and reads all the preliminary information from it
GOSUB FSInit
IF (FAT_error != 0) THEN STOP
' Display card directory
GOSUB FINDfirst ' Find first file on card
WHILE (FAT_error = 0)
GOSUB FINDnext ' Find next file on card
WEND
SDFILENAME:
' This section defines a specific short (8.3) filename
' Note that spaces are use in empty elements and must be upper case for Windows
FAT_FileName[0] = MAC_FileName[0]
FAT_FileName[1] = MAC_FileName[1]
FAT_FileName[2] = MAC_FileName[2]
FAT_FileName[3] = MAC_FileName[3]
FAT_FileName[4] = MAC_FileName[4]
FAT_FileName[5] = MAC_FileName[5]
FAT_FileName[6] = MAC_FileName[6]
FAT_FileName[7] = MAC_FileName[7]
FAT_FileName[8] = MAC_FileName[8]
FAT_FileName[9] = MAC_FileName[9]
FAT_FileName[10] = MAC_FileName[10]
FAT_seconds = FILE_seconds
FAT_minutes = FILE_minutes
FAT_hours = FILE_hours
FAT_day = FILE_day
FAT_month = FILE_month
FAT_year = FILE_year+20
SDOPEN_W:
' Open a file for write
FAT_mode = "A" ' Write mode APPEND
GOSUB FSfopen ' Open file pointed to by Byte array FAT_FileName
IF (FAT_error = 10) THEN STOP
SD_WRITE_FILE:
' Write to file
FAT_src[0] = "T"
FAT_src[1] = "I"
FAT_src[2] = "M"
FAT_src[3] = "E"
FAT_src[4] = $d
FAT_src[5] = $a
FAT_src[6] = $30+HR_T
FAT_src[7] = $30+HR_O
FAT_src[8] = ":"
FAT_src[9] = $30+MIN_T
FAT_src[10] = $30+MIN_O
FAT_src[11] = ":"
FAT_src[12] = $30+SEC_T
FAT_src[13] = $30+SEC_O
FAT_src[14] = $d
FAT_src[15] = $a
FAT_src[16] = "D"
FAT_src[17] = "A"
FAT_src[18] = "T"
FAT_src[19] = "E"
FAT_src[20] = $d
FAT_src[21] = $a
FAT_src[22] = $30+MON_T
FAT_src[23] = $30+MON_O
FAT_src[24] = ":"
FAT_src[25] = $30+DATE_T
FAT_src[26] = $30+DATE_O
FAT_src[27] = ":"
FAT_src[28] = $30+YR_T
FAT_src[29] = $30+YR_O
FAT_src[30] = $d
FAT_src[31] = $a
FAT_src[32] = " "
FAT_src[33] = $30+T_HUNS
FAT_src[34] = $30+T_TENS
FAT_src[35] = $30+T_ONES
FAT_src[36] = " "
FAT_src[37] = "F"
FAT_src[38] = $d
FAT_src[39] = $a
FAT_src[40] = $d
FAT_src[41] = $a
FAT_count = 42
GOSUB FSfwrite
IF (FAT_error = 10) THEN STOP
IF (FAT_error != 0) THEN STOP
SDCLOSE:
' Close file
GOSUB FSfclose
IF (FAT_error != 0) THEN STOP
PAUSE 5000
CIU = 0
GOTO CHECK


Menu

Re: serial LCD 1602 Backpack using PIC16F690 for Hitach HD44780
one last update:
jackberg1 - 1st November 2025, 17:11added an PGM Sw on RA3
to edit the baud rate:
turn off the LCD display, press & hold the PGM sw, turn on the LCD
line 1 will show "Press to Select" , line 2 : "Baud Rate:"...