Code:
Pause 10 ' This statement is placed at beginning of code for ICD use
'Disable Debug
;-- if you un-comment these, you must comment the ones in the .inc file --
;ASM ; 18F2550/4550, 8mhz crystal
; __CONFIG _CONFIG1L, _PLLDIV_2_1L & _CPUDIV_OSC4_PLL6_1L & _USBDIV_2_1L
; __CONFIG _CONFIG1H, _FOSC_HSPLL_HS_1H
; __CONFIG _CONFIG2L, _PWRT_ON_2L & _BOR_OFF_2L & _VREGEN_ON_2L
; __CONFIG _CONFIG2H, _WDT_ON_2H & _WDTPS_512_2H
; __CONFIG _CONFIG3H, _PBADEN_OFF_3H
; __CONFIG _CONFIG4L, _LVP_OFF_4L & _XINST_OFF_4L
;ENDASM
'--------------[ Define Hardware / Set Registers ]------------------------
DEFINE OSC 8
DEFINE I2C_SLOW 1 ' Set i2c to the standard speed
DEFINE I2C_HOLD 1 ' Enable recieving i2c device to pause communication
Include "Modedefs.Bas" ' Mode definitions for Debug,Serin/out,
' Shiftin/out, Xin/out.
INCLUDE "ALLDIGITAL.pbp" ' Sets all registers for digital ops.
' User must make sure AllDigital.pbp file
' is in same or higher directory location as
' this source code before compiling.
'DEFINE SHOWDIGITAL 1 ' When uncommented will show analog settings
' in Assembler Results window.
' A/D & Comparators disabled for digital ops
' All of these statements should be commented out when using the
' INCLUDE "AllDigital.pbp" statement to set digital ops.
'ADCON1 = %00001111
'CMCON = 7
'INCLUDE "DT_INTS-18.bas" ' Base Interrupt System
'INCLUDE "ReEnterPBP-18.bas" ' Include if using PBP high priority interrupts
' Allows re-entry to PBP from a High Priority
' ASM interrupt. Must have DT_INTS-18.bas
' loaded first.
'OSCCON.7 = 0 ' Clear IDLEN bit to allow SLEEP mode
' According to data sheet, must clear CONFIG2H.0 (WDTEN bit)
' in order to use WDTCON. Not clear from Data sheet how to reach
' WDTEN bit with with config fuses??
'WDTCON.0 = 1 ' Set SWDTEN bit to turn on WDT
TRISA = 0 ' PortA all outputs for LCD use
TRISB = 0 ' PortB all outputs
TRISC = %10000000 ' PortC.0 is output to LED_GRN
' PortC.1 is output to LED_RED
' PortC.2 is output to the LCD R/W connection
' PortC.3 is output to SCL on I2C bus
' PortC.4 is output to SDA on I2C bus
' PortC.5 is not connected
' PortC.6 is TX output to the RX connection on WiFi
' PortC.7 is Rx input from the TX connection on WiFi
TRISE = %00000001 ' PortE.0 is A/D input for AN5 from LM34 output
' PortE.1 is output for controlling exteranl SF02 power
ADCON1=7
CLEAR
'--- Variables -----------------------------------------------------------
day_cnt VAR BYTE ' Counter for day number during monthly epoch
deviceID1 VAR BYTE ' Serial # of MCU (MSB)
deviceID2 VAR BYTE ' Serial # of MCU (LSB)
ext_pwr VAR PortE.1 ' MCU controlled external power to A/D & SRF02
I VAR Byte ' Index for loop counters
ID VAR BYTE(8) ' Array for storing device ID parameters
J VAR BYTE ' Index to EEPROM address for logging
LCD_Flag VAR Bit ' Flag when set indicates LCD is installed/used
LED_RED VAR PortC.1 ' Red LED
LED_GRN VAR PortC.0 ' Green LED used to indicate Routine entries
logflag VAR BYTE ' Flag used in ISR to indicate to log time stamp
LowVolt VAR BYTE ' Flag used in ISR to indicate low supply voltage
SCL VAR PORTC.3 ' I2C clock pin
SDA VAR PORTC.4 ' I2C data pin
Spare_1 VAR PORTB.7 ' PGD for ICSP & Spare I/O for normal ops
Spare_2 VAR PORTB.6 ' PGC for ICSP & Spare I/O for normal op
temp VAR WORD ' Stores measured temperature
list VAR BYTE ' Used as embedded step variable for troubleshooting
'ENABLE DEBUG
'--- Initialize ----------------------------------------------------------
' Set FLAGS for current configuration
LCD_Flag = 1 ' Set for LCD installed/used; cleared otherwise
;--- Read MCU Serial Number from device ID Locations
TBLPTRU=$20 ' Address $200000
TBLPTRH=$00
TBLPTRL=$00
For i = 0 To 7
@ TBLRD*+ ; Get value and increment the address
ID(i) = TABLAT ; Store the byte as ID(i)
Next
deviceID1 = ID(0) ' MSB of MCU Device Serial Number
deviceID2 = ID(1) ' LSB of MCU Device Serial Number
WRITE 240, ID(0) ' Write fixed values to EEPROM for test
WRITE 241, ID(1)
'--- Initialize epoch indexes at time of powerup/reset
day_cnt = 0
WRITE 9, day_cnt ' Store new epoch initialized day_count
GOTO JumpPoint ' Jump over all subroutines so they don't execute on powerup
' ----------------------[ START SUBROUTINES ]--------------------------
InitializeDisplay: ' Subroutine to initialize 2X16 or 2x8 LCD display
'=================
'-----SETUP FOR USING 2x16 or 2x8 LCD THAT IS INSTALLED IN EASYPIC6--------
' LCD DEFINES FOR USING 2x16 LCD with PortA in EASYPIC6
DEFINE LCD_DREG PORTA ' Use PORTA for LCD Data
DEFINE LCD_DBIT 0 ' Use lower(4) 4 bits of PORTA
' PORTA.0 thru PORTB.3 connect to
' LCD DB4 thru LCD DB-7 respectively
DEFINE LCD_RSREG PORTA ' PORTA for RegisterSelect (RS) bit
DEFINE LCD_RSBIT 6 ' PORTA.6 pin for LCD's RS line
DEFINE LCD_RWREG PORTC ' LCD read/write port to GND
DEFINE LCD_RWBIT 2 ' LCD read/write bit
DEFINE LCD_EREG PORTA ' PORTA for Enable (E) bit
DEFINE LCD_EBIT 4 ' PORTA.4 pin for LCD's E line
DEFINE LCD_BITS 4 ' Using 4-bit bus
DEFINE LCD_LINES 2 ' Using 2 line Display
DEFINE LCD_COMMANDUS 2000' Command Delay (uS)
DEFINE LCD_DATAUS 50 ' Data Delay (uS)
' DEFINE LCD Control Constants
Line1 CON 128 ' Point to beginning of line 1 ($80)
Line2 CON 192 ' Point to beginning of line 2 ($C0)
' Test the LCD during initialization
LED_RED = 1 ' Blink red LED during LCD initialization
LCDOut $fe,1:FLAGS=0:Pause 250 ' Clear Display
LCDOUT $fe,Line1,"POWER ON" ' Display on 1st line
LCDOUT $fe,Line2,"LCD TEST" ' Display on 2nd line
PAUSE 2000
LED_RED = 0 ' Blink red LED during LCD initialization
Return
Temperature: ' Subroutine to measure temperature from LM34
'===========
' This subroutine is an adaptation from below reference to 10-bit A/D
'****************************************************************
'* Name : LM34.BAS *
'* Author : Bruce Reynolds *
'* Date : 10/23/2001 *
'* Version : 1.0 *
'* Notes : 8-bit A/D temperature conversion with National *
'* ; LM34CAZ analog temperature sensor. *
'* : See http://www.rentron.com/PicBasic/LM34.htm *
'****************************************************************
'DEFINE osc 8 ' Using a 16 MHz oscillator..already defined
DEFINE ADC_BITS 10 ' Set A/D for 10-bit operation
DEFINE ADC_CLOCK 5 ' Set A/D clock Fosc/16
DEFINE ADC_SAMPLEUS 50 ' Set A/D sampling time @ 50 uS
samples VAR WORD ' Multiple A/D sample accumulator
sample VAR BYTE ' Holds number of samples to take
value VAR WORD ' Holds LM34 measured temperature value
samples = 0 ' Clear samples accumulator on entry
W0 VAR WORD '
IF LCD_Flag = 1 THEN ' This code block FOR TESTING ONLY
LCDOUT $fe,1' Clear Display
LCDOUT $fe,Line1,"Temp"
LCDOUT $fe,Line2,"Measurement"
PAUSE 1000
ENDIF
' Setup registers for A/D input per Sec 21.0 of datasheet
'1. Configure the A/D module:
' Configure analog pins, voltage reference AND I/O (ADCON1)
ADCON1 = %11000000 'right justified,Fosc/16, all analog
' SELECT A/D INPUT channel (ADCON0)
ADCON0 = %01101000 'Fosc/16,Disable AN5 (PORTE.0),powered down
' SELECT A/D acquisition time & A/D conversion clock (ADCON2)
'ADCON2 = %10110101 'Right justified;TAD=16;A/D clock=Fosc/16
' Turn ON A/D module (ADCON0)
ADCON0.0 = 1 'Power up the A/D module
'2. Configure A/D INTERRUPT (IF desired):
' CLEAR ADIF BIT
' Set ADIE BIT
' Set GIE BIT
'3. WAIT the required acquisition time (IF required).
'PAUSE 250 ' Wait approximately 1/4 seconds per loop
'4. Start conversion-Set GO/DONE BIT (ADCON0 register)
ADCON0.2 = 1
'5. WAIT FOR A/D conversion TO complete, by either:
' Polling FOR the GO/DONE BIT TO be cleared
'OR
' Waiting FOR the A/D INTERRUPT
FOR sample = 1 TO 10 ' Take 10 samples
ADCIN 5, value ' Read channel 5 into temp variable
'PAUSE 2
' or use alternative manual method to read A/D input
'WHILE ADCON0.1 : WEND
'6. READ A/D Result registers (ADRESH:ADRESL);
'CLEAR BIT ADIF, if required.
'W0.HIGHBYTE = ADRESH
'W0.LOWBYTE = ADRESL
samples = samples + value ' Accumulate 10 samples
'7. FOR NEXT conversion, go TO STEP 1 or STEP 2, as
'required. The A/D conversion time per BIT IS
'defined as TAD. A minimum WAIT of 3 TAD IS
'required before the NEXT acquisition starts.
PAUSE 250 ' Wait approximately 1/4 seconds per loop
NEXT sample
value = samples/10 ' Determine average of 10 measurements
'ADC Math for 10-bit A/D when using Vdd as referenc
'ADC Resolution = 4.99 V/1024 COUNT = 4.912109 mV/COUNT
'=> LM34DZ OUTPUT voltage (mV) = 2 x COUNT
'Temperature ( F) = LM34 OUTPUT voltage in mV/10
'=> Temperature ( F) = 4.912109 x COUNT/10 = 0.4912109*COUNT
' Therefore temp = 0.4912109*Count or approx. = Count/2.036
' To avoid floating point math, multiply by 1000 and then DIV32
value = 1000 * value
temp = DIV32 2036
samples = 0 ' Clear old sample accumulator for next cycle
ADCON1=7 ' Return to digital ops.
RETURN
' ----------------------[ END OF SUBROUTINES ]--------------------------
JumpPoint:
'Setup for starting Main Program
IF LCD_Flag = 1 THEN GOSUB InitializeDisplay ' Initialize LCD before
' starting mainloop
IF LCD_Flag = 1 THEN ' This code block FOR TESTING ONLY
LCDOUT $fe,1' Clear Display
LCDOUT $fe,Line1,"Entered"
LCDOUT $fe,Line2,"JumpPoint"
PAUSE 1000
ENDIF
'Initialize epoch indexes at time of powerup/reset
Pause 20
J = 0 ' Initialize EEPROM logging index
'WRITE 11,hr ' Log program start time
'WRITE 12,MINs
'WRITE 13,sec
'WRITE 242,mon ' Log program start date
'WRITE 243,date
'WRITE 244,yr
'Initialize LEDs to off
LED_GRN = 0
LED_RED = 0
' Enable the interrupts that are to be active during main loop.
'logflag = 0 ' Clear flags before mainloop
'LowVolt = 0
;@ INT_ENABLE INT2_INT ; enable DT_18-INTS interrupts
;@ INT_ENABLE HLVD_INT
'--------------------[ Begin Main Program Loop ]-------------------------
;@ StartSize(MainLoop) ; FOR TEST ONLY
mainloop:
' Put code here for temperature measurement
' Blink Green LED as heartbeat
LED_GRN = 1
PAUSE 250
LED_GRN = 0
PAUSE 250
'Put code here to measure/log temperature from LM34 analog sensor
temp = 0 'Initialize temperature variable
ext_pwr = 1 'Power up temperature circuit
GOSUB Temperature
ext_pwr = 0 'Power-down temperature circuit
IF J > 220 THEN ' If logging space is full start over with logging
J = 0 ' Reset logging index to start of logging space
' Logging space covers time stamps for 220 interrupts
ENDIF
WRITE 16+J, temp ' temperature value to EEPROM
J = J+1
'If LCD installed reset to all digital ops before display of temperature
IF LCD_Flag = 1 THEN ' This code block FOR TESTING ONLY
ADCON1 = 7 ' All Digital
LCDOUT $fe,1 ' Clear Display
LCDOUT $fe,Line1,"Temp:" ' Display measured temperature
LCDOUT $FE,Line2, DEC temp, " DEG F"
PAUSE 1000
' Will be reset to analog use in Temperature routine
ENDIF
GOTO mainloop
;@ EndSize(MainLoop) ; Uncomment FOR TEST ONLY
'--------------------[ Begin Interrupt Handlers ]------------------------
' ISRs all commented out for this application.
;Alarm:
;logflag = 1 ' Set flag for logging this interrupt
;@ INT_RETURN
'VoltLow:
'LowVolt = 1 ' Set flag for low voltage warning
;@ INT_RETURN
'------------------{ End of Interrupt Handlers }-------------------------
End ' Safety measure to insure program stops if reaches here
Bookmarks