Hi all
I am a beginner, trying to build a Temp controller that will keep the stats like temp at hour intervals for the last month etc. The temp controller will have one heating and one cooling output. Setting up the menus and outputs is not that hard, but I know reading the thermistor (ADC) and this RTC part will be the hardest. I am stuck on the RTC for now... I almost know the 2520 data sheets by hart by now, but that did not help me enough... In my code I just tried to display one digit of the secs for testing (must still figure out how to display the second digit), but it's not counting up...
Any help or info will be appreciated...
and the timer.inc file needed for the lcd:
Thanks again...
I am a beginner, trying to build a Temp controller that will keep the stats like temp at hour intervals for the last month etc. The temp controller will have one heating and one cooling output. Setting up the menus and outputs is not that hard, but I know reading the thermistor (ADC) and this RTC part will be the hardest. I am stuck on the RTC for now... I almost know the 2520 data sheets by hart by now, but that did not help me enough... In my code I just tried to display one digit of the secs for testing (must still figure out how to display the second digit), but it's not counting up...
Any help or info will be appreciated...
Code:
;******************************************************************************
; *
; Filename: Temperature Controller based on PIC18F2520 *
; ===================================================== *
; *
; *
; *
; Program written by D, Jordaan *
; *
; V1.00 Aug 2007 Initial menu *
; *
;******************************************************************************
;
; Processor Type
; ==============
;
LIST P=18F2520,r=hex,n=80,x=off,st=off
errorlevel -302 ; no bank warnings
#include <P18F2520.INC>
; DELAY PARAMETERS FOR 4MEG CRYSTAL
clock equ 4000000 ; my crystal frequency
dusec equ 1000 ; required delay (1 mSec)
#include <timer.inc> ; note, include must be after these two definitions
;******************************************************************************
;
; Configuration bits
; ==================
; specified here are changes to the .inc file defaults
CONFIG OSC=INTIO67, PWRT=ON, BOREN=OFF, WDT=OFF, MCLRE=OFF, LPT1OSC=OFF, PBADEN=OFF
CONFIG LVP=OFF, XINST=OFF, DEBUG=OFF
;******************************************************************************
;
; Variable definitions
; ====================
; Bank1 variables 0x100 to 0x1FF
cblock 0x100 ; BANK1
pntr
offset
dval
lcd_flags
lcd_temp
t0
t1
t2
t3
t4
t5
t6
t7
t8
t9
t10
t11
t12
t13
t14
t15
t16
t17
t18
t19
t20
c0
c1
c2
c3
c4
c5
c6
c7
c8
c9
c10
c11
c12
c13
c14
c15
c16
c17
c18
c19 ;40
c20
RB0CP
secs
mins
hours
endc ; last address entered max FF
LEDPORT1 Equ PORTA ;set constants for output ports
LEDPORT_1 Equ 2
LEDPORT2 Equ PORTA
LEDPORT_2 Equ 1
LEDPORT3 Equ PORTC
LEDPORT_3 Equ 3
LEDPORT4 Equ PORTB
LEDPORT_4 Equ 0
LEDPORT5 Equ PORTC
LEDPORT_5 Equ 4
LEDPORT6 Equ PORTC
LEDPORT_6 Equ 5
LEDPORT7 Equ PORTC
LEDPORT_7 Equ 6
LEDPORT8 Equ PORTC
LEDPORT_8 Equ 7
SWPORT1 Equ PORTA ;set constants for input ports
SWPORT_1 Equ 5
SWPORT2 Equ PORTA
SWPORT_2 Equ 4
SWPORT3 Equ PORTE
SWPORT_3 Equ 3
SWPORT4 Equ PORTA
SWPORT_4 Equ 3
SWPORT5 Equ PORTC
SWPORT_5 Equ 2
;******************************************************************************
;
; Reset vector
; ============
ORG 0x0000
bootup goto Main ;go to start of main code
ORG 0008h ; an interrupt redirects the program to here
RTCisr ; Start ISR here
; Insert the next 4 lines of code when TMR1
; can not be reliably updated before clock pulse goes low
; BTFSC TMR1L,0 ; wait for TMR1L<0> to become clear
; BRA $-2 ; (may already be clear)
; BTFSS TMR1L,0 ; wait for TMR1L<0> to become set
; BRA $-2 ; TMR1 has just incremented
; If TMR1 update can be completed before clock pulse goes low
BSF TMR1H, 7 ; Preload for 1 sec overflow
BCF PIR1, TMR1IF ; Clear interrupt flag
INCF secs, F ; Increment seconds
MOVLW .59 ; 60 seconds elapsed?
CPFSGT secs
RETFIE ;RETURN ; No, done
CLRF secs ; Clear seconds
INCF mins, F ; Increment minutes
MOVLW .59 ; 60 minutes elapsed?
CPFSGT mins
RETFIE; RETURN ; No, done
CLRF mins ; clear minutes
INCF hours, F ; Increment hours
MOVLW .23 ; 24 hours elapsed?
CPFSGT hours
RETFIE ;RETURN ; No, done
CLRF hours ; Reset hours
RETFIE ;RETURN ; Done
;******************************************************************************
;******************************************************************************
;
; Start of main program
; =====================
; initialisation of system, clear RAM , setup i/o ports
Main movlb D'1' ; define bank1, so it and bank 0/15 (access)
; can be addressed without banking
clrf INTCON ; clear interupts
clrf STATUS ; reset to bank 0
clearam clrf FSR1H ; FSR routine to clear ram banks 0 -4 only
clrf FSR1L
clrram clrf POSTINC1 ; clear location and inc
movlw 0x05 ; now in bank5 ?
subwf FSR1H,W
bnz clrram ; carry on clearing if not at bank5
; *****************************************************************************
;
; Port Allocation - Standard Multi Controller on 2520 chip
;
;
; PortA ra0 AI NTC1 PortB rb0 OUT TIMER3
; ra1 OUT HEATER rb1 lcd e1
; ra2 OUT COOLER1 rb2 lcd rs
; ra3 IN SW3 rb3 lcd rw
; ra4 IN KEY A rb4 lcd d4
; ra5 IN KEY B rb5 lcd d5
; ra7 IN Unalloc rb6 lcd d6
; ra6 IN Unalloc rb7 lcd d7
; PortC rc0 timer1 xtal PortE re3 IN EXT ALARM
; rc1 timer1 xtal1 ( set by config )
; rc2 IN SW4
; rc3 OUT COOLER2
; rc4 OUT LIGHT1
; rc5 OUT LIGHT2
; rc6 OUT TIMER4
; rc7 OUT ALARM
ports clrf PORTA
clrf PORTB
clrf PORTC
movlw b'00001110' ; set portA,0 as adc input bit 7 rjust
movwf ADCON1 ; by loading value to adcon1 reg
movlw b'00111001' ; set trisa direction is input
movwf TRISA ; bit0 adc, bit1,2 DO, bit3,4,5 DI , bit7,6 DO
movlw b'00000000' ; set portB as low outputs
movwf TRISB
movlw b'00000100' ; set portC low outputs, except rc2 DI
movwf TRISC
; ***************************************************************************
;
; Start Timers
; ============
; Timer0 as base for Delay 1ms
movlw b'11010000' | PRESCL
movwf T0CON
; movlw b'00000001'
; movwf PIE1
; movlw b'00000001'
; movwf IPR1
RTCinit
MOVLW 80h ; Preload TMR1 register pair
MOVWF TMR1H ; for 1 second overflow
CLRF TMR1L
MOVLW b'00001111' ; Configure for external clock,
MOVWF T1CON ; Asynchronous operation, external oscillator
CLRF secs ; Initialize timekeeping registers
CLRF mins ;
MOVLW .12
MOVWF hours
BSF PIE1, TMR1IE ; Enable Timer1 interrupt
; RETURN
; ***************************************************************************
;
; Init LCD Display
; ================
; eedata routines inserted in middle of initlcd routine
; needed to come after the setemps which restore eprom
call lcd_init ; initialise the LCD driver
; ***************************************************************************
;
; Running Program Starts Here
; ===========================
loop call dataone
call datatwo
call sendone
call sendtwo
MainMen btfss SWPORT1, SWPORT_1 ;enter menu if SW1 pushed
goto LED1ON
goto loop
;===============================================================================
;
; SUBROUTINES
;
;===============================================================================
;*************************************************************************
;Real-time Clock
;*************************************************************************
;*************************************************************************
; Main Menu
;*************************************************************************
LED1ON bsf LEDPORT1, LEDPORT_1 ;turn LED1 on
call DataLed1
call sendone ;Send Led 1 on message
call DoDelay30 ;wait a bit
goto LED1_2
LED1_2 btfss SWPORT1, SWPORT_1 ;check if switch pushed again
goto LED2ON ;yes, goto switch led2 on
goto LED1_2 ;no, loop and check again
LED2ON bcf LEDPORT1, LEDPORT_1 ;turn LED 1 off
bsf LEDPORT2, LEDPORT_2 ;turn LED2 on
call DataLed2
call sendone ;send LED 2 on message
call DoDelay30 ;wait a bit
goto LED2_2
LED2_2 btfss SWPORT1, SWPORT_1 ;is SW1 pushed?
call ClearPorts ;yes, turn all LED's off and exit menu
goto LED2_2 ;no, loop and check again
ClearPorts
bcf LEDPORT1, LEDPORT_1 ;Switch off led's
bcf LEDPORT2, LEDPORT_2
call DoDelay30
goto loop
; ***************************************************************************
;
; Delay Routine for LCD
; =====================
; using the internal timer, will delay for W times the value of
; "dusec" in microseconds. (used by lcd routine)
delay movwf dval
dy1 clrf TMR0L
bcf INTCON,T0IF
movlw TMRVAL ; set timer
movwf TMR0L
dy2 btfss INTCON,T0IF ; timer overflow yet?
goto dy2 ; no
decfsz dval,f ; yes, all cycles?
goto dy1 ; no
return ; yes, delay finished
; ***************************************************************************
;
; Macros for LCD routine
; ======================
dotris macro arg1, arg2
movlw arg1
movwf arg2
endm
dodelay macro arg1
movlw arg1
call delay
endm
DoDelay30
dodelay 30
return
;****************************************************************************
;
; Routines to display on a 2x16 character LCD Standard 7 bit version
; =========================================== ======================
;
; LcdInit - call this subroutine before using the display. It uses
; bits 7-1 of PORTB, leaving bit-0 free (although it will
; be configured as an output).
;
; Lcd_C - Sends the byte in W as a command to the display. Checks
; if busy first.
;
; Lcd_D - Sends the byte in W as data. Checks for busy first.
;
; Assumes it can call a routine called "delay" with a required
; time delay in mSecs in W.
; Uses an additional three (3) levels of the stack.
;
; Address of first line on the LCD is 0
; Address of second line is 64
;
; by Ron Kreymborg
;
;******************************************************************
lcd_com macro arg1
movlw arg1
call lcd_c
endm
; Flags -
lcd_Bflg equ 0
lcd_RSflg equ 1
; I/O portB -
lcd_BUSY equ 7 ; input - LCD is busy (0x80)
lcd_R_W equ 3 ; output - LCD Read/Write (0x08)
lcd_RS equ 2 ; output - Register Select (0x04)
lcd_E equ 1 ; output - LCD Enable (0x02)
lcd_init
clrf PORTB
dotris b'00000000',PORTB ; all outputs and low to start
bcf lcd_flags,lcd_RSflg
dodelay 15 ; 15mSec power up delay
movlw b'00110000' ; 8-bit mode
movwf PORTB
call lcd_clk
dodelay 4 ; 4mSec wait
movlw b'00110000' ; 8-bit mode
movwf PORTB
call lcd_clk
dodelay 1 ; 1 mSec wait
movlw b'00110000' ; 8-bit mode
movwf PORTB
call lcd_clk
dodelay 4 ; 4mSec wait
movlw b'00100000' ; set for 4-bit
movwf PORTB
call lcd_clk
; Reset sequence is done - initialise for us
lcd_com b'00101000' ; 4-bits, 2-lines, 5x7
lcd_com b'00001000' ; display off, cursor off, blink off
lcd_com b'00001100' ; display on
lcd_com b'00000001' ; clear display
lcd_com b'00000110' ; increment, no display shift
return
; Check whether the LCD is busy. Loop until it isn't. When
; it's free, output the byte passed in W, MS nibble first.
lcd_d bsf lcd_flags,lcd_RSflg ; set RS flag for data
goto lcd_o1
lcd_c bcf lcd_flags,lcd_RSflg ; clear RS flag for commands
lcd_o1 movwf lcd_temp ; save control word
dotris b'11110000',PORTB ; RB7-4 as inputs for busy
movlw 1 << lcd_R_W
movwf PORTB ; set up for read
lcd_o2 bcf lcd_flags,lcd_Bflg ; assume not busy
bsf PORTB,lcd_E ; clock high
nop ; little wait
btfsc PORTB,lcd_BUSY ; busy set?
bsf lcd_flags,lcd_Bflg ; yes
bcf PORTB,lcd_E ; clock low
nop ; little wait
nop
call lcd_clk ; get low bits but ignore (for now)
btfsc lcd_flags,lcd_Bflg ; was it busy?
goto lcd_o2 ; yes
dotris b'00000000',PORTB ; RB7-4 outputs again
movf lcd_temp,w ; get word to send
call lcd_o3 ; send high nibble
swapf lcd_temp,w ; get word again
lcd_o3 andlw 0xf0 ; just high bits (clears all control bits)
movwf PORTB
btfsc lcd_flags,lcd_RSflg ; was lcd_RS set?
bsf PORTB,lcd_RS ; yes
call lcd_clk ; write current nibble
return
lcd_clk bsf PORTB,lcd_E ; pulse E line high
nop
bcf PORTB,lcd_E
return
;****************************************************************************
; ***************************************************************************
;
; SR SEND LCD DISPLAY LINE 1
; ===========================
sendone
movf c0,w ; get 1st ram
iorlw 0x80 ; add address for command line
call lcd_c ; for line of lcd
movf c1,w
call lcd_d
movf c2,w
call lcd_d
movf c3,w
call lcd_d
movf c4,w
call lcd_d
movf c5,w
call lcd_d
movf c6,w
call lcd_d
movf c7,w
call lcd_d
movf c8,w
call lcd_d
movf c9,w
call lcd_d
movf c10,w
call lcd_d
movf c11,w
call lcd_d
movf c12,w
call lcd_d
movf c13,w
call lcd_d
movf c14,w
call lcd_d
movf c15,w
call lcd_d
movf c16,w
call lcd_d
movf c17,w
call lcd_d
movf c18,w
call lcd_d
movf c19,w
call lcd_d
movf c20,w
call lcd_d
return
; ***************************************************************************
;
; SR SEND LCD DISPLAY LINE 2
; ===========================
sendtwo
movf t0,w ; get 1st ram
iorlw 0x80 ; add address for command line
call lcd_c ; for line2 of lcd
movf t1,w
call lcd_d
movf t2,w
call lcd_d
movf t3,w
call lcd_d
movf t4,w
call lcd_d
movf t5,w
call lcd_d
movf t6,w
call lcd_d
movf t7,w
call lcd_d
movf t8,w
call lcd_d
movf t9,w
call lcd_d
movf t10,w
call lcd_d
movf t11,w
call lcd_d
movf t12,w
call lcd_d
movf t13,w
call lcd_d
movf t14,w
call lcd_d
movf t15,w
call lcd_d
movf t16,w
call lcd_d
movf t17,w
call lcd_d
movf t18,w
call lcd_d
movf t19,w
call lcd_d
movf t20,w
call lcd_d
return
; ***************************************************************************
;
; SR LCD DATA MESSAGES
; ====================
dataone movlw 0x00 ; lcd line1 ram message
movwf c0
movlw 'T'
movwf c1
movlw 'I'
movwf c2
movlw secs ;'M'
movwf c3
movlw 'E'
movwf c4
movlw ' '
movwf c5
movlw '2'
movwf c6
movlw '3'
movwf c7
movlw ':'
movwf c8
movlw '0'
movwf c9
movlw '0'
movwf c10
movlw ' '
movwf c11
movlw ' '
movwf c12
movlw ' '
movwf c13
movlw ' '
movwf c14
movlw ' '
movwf c15
movlw ' '
movwf c16
movlw ' '
movwf c17
movlw ' '
movwf c18
movlw ' '
movwf c19
movlw ' '
movwf c20
return
datatwo movlw 0x40 ; lcd line2 ram message
movwf t0
movlw 'T'
movwf t1
movlw 'E'
movwf t2
movlw 'M'
movwf t3
movlw 'P'
movwf t4
movlw ' '
movwf t5
movlw 'C'
movwf t6
movlw 'O'
movwf t7
movlw 'N'
movwf t8
movlw 'T'
movwf t9
movlw 'R'
movwf t10
movlw 'O'
movwf t11
movlw 'L'
movwf t12
movlw 'L'
movwf t13
movlw 'E'
movwf t14
movlw 'R'
movwf t15
movlw ' '
movwf t16
movlw ' '
movwf t17
movlw ' '
movwf t18
movlw ' '
movwf t19
movlw ' '
movwf t20
return
DataLed1
movlw 0x00 ; lcd line1 ram message
movwf c0
movlw 'L'
movwf c1
movlw 'E'
movwf c2
movlw 'D'
movwf c3
movlw ' '
movwf c4
movlw 'O'
movwf c5
movlw 'N'
movwf c6
movlw 'E'
movwf c7
movlw ' '
movwf c8
movlw 'O'
movwf c9
movlw 'N'
movwf c10
movlw ' '
movwf c11
movlw ' '
movwf c12
movlw ' '
movwf c13
movlw ' '
movwf c14
movlw ' '
movwf c15
movlw ' '
movwf c16
movlw ' '
movwf c17
movlw ' '
movwf c18
movlw ' '
movwf c19
movlw ' '
movwf c20
return
DataLed2
movlw 0x00 ; lcd line1 ram message
movwf c0
movlw 'L'
movwf c1
movlw 'E'
movwf c2
movlw 'D'
movwf c3
movlw ' '
movwf c4
movlw 'T'
movwf c5
movlw 'W'
movwf c6
movlw 'O'
movwf c7
movlw ' '
movwf c8
movlw 'O'
movwf c9
movlw 'N'
movwf c10
movlw ' '
movwf c11
movlw ' '
movwf c12
movlw ' '
movwf c13
movlw ' '
movwf c14
movlw ' '
movwf c15
movlw ' '
movwf c16
movlw ' '
movwf c17
movlw ' '
movwf c18
movlw ' '
movwf c19
movlw ' '
movwf c20
return
END
and the timer.inc file needed for the lcd:
Code:
; PRESCL and TIMER computation
nolist
; Take the processor clock frequency in Hz (clock), and
; the required time delay in uSecs (dusec), and compute
; a value for the prescaler (PRESCL) and another for
; TMR0 (TIMER).
_cycle equ clock >> 2
_dfreq equ 1000000 / dusec
_divr equ _cycle / _dfreq
if (_divr < 512)
error "Delay time too short. Assign PSA to WDT."
endif
_test set _divr / 256
_testB equ _divr % 256
if (_testB > 0)
_test set _test + 1
endif
if (_test > 1)
_temp set 2
PRESCL set 0
endif
if (_test > 2)
_temp set 4
PRESCL set 1
endif
if (_test > 4)
_temp set 8
PRESCL set 2
endif
if (_test > 8)
_temp set 16
PRESCL set 3
endif
if (_test > 16)
_temp set 32
PRESCL set 4
endif
if (_test > 32)
_temp set 64
PRESCL set 5
endif
if (_test > 64)
_temp set 128
PRESCL set 6
endif
if (_test > 128)
error "Timer requirement is outside range"
endif
TMRVAL equ 256 - (_cycle / _temp / _dfreq)
list
Thanks again...