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.
'<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
'<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
Re: Starting with PBP: how to restart with PBP today
I use the MeLabs USB programmer, with backup PicKit4.
Demon - 14th April 2025, 01:37Latest PBP and MCS+.