PIC programming LCD countdown timer

Thread Starter

bluebrakes

Joined Oct 17, 2009
252
I was wondering if someone could help me write the bare bones to my 16f628a LCD driven countdown timer.

Essentially there are three buttons one to change the increment in minutes only (up to 60mins), a set digit button and finally a start/reset button. I figured the internal timer is good enough for this project, as timing precision isn't exactly critical.

LED1 will flash with every button press and when the timer is up.

LED2 and LED 3 will turn on when the timer is up.


I built this project as the next step in my learning curve, but I'm still getting to grips with the pic programming. Any snippets of code would be greatly appreciated. :)
 

Attachments

Thread Starter

bluebrakes

Joined Oct 17, 2009
252
; ========== 16F628A LCD COUNTDOWN TIMER =================
; Description: ..........
;
; 16F628A driven LCD countdown timer for a period
; of up to 60 minutes.
;
; Switch One increments the digits of the timer.
; Switch Two sets the digits of the timer.
; Switch Three starts/resets the timer.
;
;
;==========================================================
LIST p=16F628 ; TELLS THE PROGRAMMER WHAT CHIP WE'RE USING.
include "P16F628.inc" ; INCLUDES DEFAULTS FOR THE CHIP.
ERRORLEVEL 0, -302 ;suppress bank selection messages
__config 0x3D18 ;sets the configuration settings (oscillator type etc.)
;__config _INTRC_OSC_NOCLKOUT & _LVP_OFF & _WDT_OFF & _PWRTE_OFF

cblock 0x20 ;start of general purpose registers
count ;used in looping routines
count1 ;used in delay routine
counta ;used in delay routine
countb ;used in delay routine
tmp1 ;temporary storage
tmp2
templcd ;temp store for 4 bit mode
templcd2
endc
;=====================================
; LCD SETUP, DATA LINES, CONTROL LINES
LCD_PORT Equ PORTA
LCD_TRIS Equ TRISA
LCD_RS Equ 0x04 ;LCD handshake lines
LCD_RW Equ 0x06
LCD_E Equ 0x07
; END OF LCD SETUP
;=====================================
;=============================
; Additional LEDs and Switches
LEDPORT Equ PORTB ;set constant LEDPORT = 'PORTA'
SWPORT Equ PORTB ;set constant SWPORT = 'PORTA'
LEDTRIS Equ TRISB

SW1 Equ 0x00 ; Identifies Switch One on Schematic diagram
SW2 Equ 0x01 ; Identifies Switch Two on Schematic diagram
SW3 Equ 0x02 ; Identifies Switch Three on Schematic diagram

LED1 Equ 0x04 ; Identifies LED One on the Schematic diagram
LED2 Equ 0x05 ; Identifies LED Two on the Schematic diagram
LED3 Equ 0x06 ; Identifies LED Three on the Schematic diagram

; end of LEDs and switches
;=============================
org 0x0000 ;org sets the origin, 0x0000 for the 16F628
movlw 0x07
movwf CMCON ;turn comparators off (make it like a 16F84)
Initialise clrf count
clrf PORTA
; clrf PORTB

SetPorts bsf STATUS, RP0 ;select bank 1
movlw b'00001111' ; 4 outputs (RB4-RB7), 4 inputs (RB0-RB3)
movwf SWTRIS
bcf STATUS, RP0 ;select bank 0
clrf LEDPORT ;set all outputs low
clrf SWPORT


movwf LCD_TRIS
bcf STATUS, RP0 ;select bank 0
call Delay100 ;wait for LCD to settle

call LCD_Init ;setup LCD

clrf count ;set counter register to zero
Message movf count, w ;put counter value in W
call Text ;get a character from the text table
xorlw 0x00 ;is it a zero?
btfsc STATUS, Z
goto NextMessage
call LCD_Char
call Delay255
incf count, f
goto Message
NextMessage call LCD_Line2 ;move to 2nd row, first column
clrf count ;set counter register to zero
Message2 movf count, w ;put counter value in W
call CrdText ;get a character from the credit text table
xorlw 0x00 ;is it a zero?
btfsc STATUS, Z
goto EndMessage
call LCD_Char
incf count, f
goto Message2
EndMessage

Stop goto Stop ;endless loop


;Subroutines and text tables
;LCD routines
;Initialise LCD
LCD_Init movlw 0x20 ;Set 4 bit mode
call LCD_Cmd
movlw 0x28 ;Set display shift
call LCD_Cmd
movlw 0x06 ;Set display character mode
call LCD_Cmd
movlw 0x0d ;Set display on/off and cursor command
call LCD_Cmd
call LCD_Clr ;clear display
retlw 0x00
; command set routine
LCD_Cmd movwf templcd
swapf templcd, w ;send upper nibble
andlw 0x0f ;clear upper 4 bits of W
movwf LCD_PORT
bcf LCD_PORT, LCD_RS ;RS line to 0
call Pulse_e ;Pulse the E line high
movf templcd, w ;send lower nibble
andlw 0x0f ;clear upper 4 bits of W
movwf LCD_PORT
bcf LCD_PORT, LCD_RS ;RS line to 0
call Pulse_e ;Pulse the E line high
call Delay5
retlw 0x00
LCD_CharD addlw 0x30
LCD_Char movwf templcd
swapf templcd, w ;send upper nibble
andlw 0x0f ;clear upper 4 bits of W
movwf LCD_PORT
bsf LCD_PORT, LCD_RS ;RS line to 1
call Pulse_e ;Pulse the E line high
movf templcd, w ;send lower nibble
andlw 0x0f ;clear upper 4 bits of W
movwf LCD_PORT
bsf LCD_PORT, LCD_RS ;RS line to 1
call Pulse_e ;Pulse the E line high
call Delay5
retlw 0x00
LCD_Line1 movlw 0x80 ;move to 1st row, first column
call LCD_Cmd
retlw 0x00
LCD_Line2 movlw 0xc0 ;move to 2nd row, first column
call LCD_Cmd
retlw 0x00
LCD_Line1W addlw 0x80 ;move to 1st row, column W
call LCD_Cmd
retlw 0x00
LCD_Line2W addlw 0xc0 ;move to 2nd row, column W
call LCD_Cmd
retlw 0x00
LCD_CurOn movlw 0x0d ;Set display on/off and cursor command
call LCD_Cmd
retlw 0x00
LCD_CurOff movlw 0x0c ;Set display on/off and cursor command
call LCD_Cmd
retlw 0x00
LCD_Clr movlw 0x01 ;Clear display
call LCD_Cmd
retlw 0x00
LCD_HEX movwf tmp1
swapf tmp1, w
andlw 0x0f
call HEX_Table
call LCD_Char
movf tmp1, w
andlw 0x0f
call HEX_Table
call LCD_Char
retlw 0x00
Delay255 movlw 0xff ;delay 255 mS
goto d0
Delay100 movlw d'100' ;delay 100mS
goto d0
Delay50 movlw d'50' ;delay 50mS
goto d0
Delay20 movlw d'20' ;delay 20mS
goto d0
Delay5 movlw 0x05 ;delay 5.000 ms (4 MHz clock)
d0 movwf count1
d1 movlw 0xC7 ;delay 1mS
movwf counta
movlw 0x01
movwf countb
Delay_0
decfsz counta, f
goto $+2
decfsz countb, f
goto Delay_0
decfsz count1 ,f
goto d1
retlw 0x00
Pulse_e bsf LCD_PORT, LCD_E
nop
bcf LCD_PORT, LCD_E
retlw 0x00
;end of LCD routines
HEX_Table ADDWF PCL , f
RETLW 0x30
RETLW 0x31
RETLW 0x32
RETLW 0x33
RETLW 0x34
RETLW 0x35
RETLW 0x36
RETLW 0x37
RETLW 0x38
RETLW 0x39
RETLW 0x41
RETLW 0x42
RETLW 0x43
RETLW 0x44
RETLW 0x45
RETLW 0x46


; ========================================
; Main text for countdown timer (LCD text)
; ========================================
; "Countdown timer"
Text addwf PCL, f
retlw 'C' ; Character 1
retlw 'o' ; Character 2
retlw 'u' ; Character 3
retlw 'n' ; Character 4
retlw 't' ; Character 5
retlw 'd' ; Character 6
retlw 'o' ; Character 7
retlw 'w' ; Character 8
retlw 'n' ; Character 9
retlw ' ' ; Character 10
retlw 'T' ; Character 11
retlw 'i' ; Character 12
retlw 'm' ; Character 13
retlw 'e' ; Character 14
retlw 'r' ; Character 15
retlw 0x00
;========================================

; ==================================================
; Credits Text for program (LCD text)
; ==================================================
; "By DC"
CrdText addwf PCL, f
retlw 'B' ; Character 1
retlw 'y' ; Character 2
retlw ' ' ; Character 3
retlw 'D' ; Character 4

retlw 0x00
;===================================================

Text2 ADDWF PCL, f
RETLW 'R'
RETLW 'e'
RETLW 'a'
RETLW 'd'
RETLW 'y'
RETLW '.'
RETLW '.'
RETLW '.'
RETLW 0x00
end



This is what I put together last night so far....

Anyone got any tips or suggestions on how to progress...
 

Markd77

Joined Sep 7, 2009
2,806
Have you run it in MPLab Sim? If so what was wrong? I like the code coverage feature in Sim which shows you which lines have been run - it can show up some problems pretty quickly.
Also can I recommend enclosing code in code tags in the forum. Just click "go advanced", highlight the section and click the "#" icon. It keeps the formatting and makes it a lot easier to read.
 

delmasli

Joined Sep 17, 2009
17
Schematic seem not so difficult but I cannot say same for the code. Try to write this code in "Structured or Generic Programming Style" at C. Assembler seems somehow complicated and not easy to resolve (for me) if the code line count is more than 100.
 

Thread Starter

bluebrakes

Joined Oct 17, 2009
252
Thanks for the quick response guys.

I never did understand how the simulator works on MPLABs software.... can anyone suggest a website with a good tutorial of how to use it?

I guess the problem for me is getting the timer routine to tie in with the rest of the code. I'm using the internal clock of the 16f628 for this, what code would people suggest for the minute timer sub routine?
 

Markd77

Joined Sep 7, 2009
2,806
I don't know any MPlab tutorials but there must be some out there. It was similar to other stuff I've used.
There are a few ways of doing this:
For the 1 second tick you could write a 1 second loop and knock a bit off for your overheads - LCD etc. You could instead use Timer1 interrupts to get a regular tick which would be independant of your other code which would make getting good accuracy easier but make the code harder.
For the counter you could either convert the minutes and seconds into a 16 bit number held in 2 registers and then convert back to display it or deal with it in 4 registers, each holding decimal values for the minutes, 10s of minutes, seconds and 10s of seconds.
There are plenty of other ways too.
I'd also suggest looking at AN526 on the microchip site which has 16 bit math and binary to decimal conversion routines.
 

Thread Starter

bluebrakes

Joined Oct 17, 2009
252
Can anyone see where i'm going wrong...

I'm doing bit by bit and testing the code, but now the screen comes up with nothing... (PIC is OK, as I put another program on it and it works).

; *********** 16F628A LCD COUNTDOWN TIMER ****************
; Description: ..........
;
; 16F628A driven LCD countdown timer for a period
; of up to 60 minutes.
;
; Switch One increments the digits of the timer.
; Switch Two sets the digits of the timer.
; Switch Three starts/resets the timer.
;
;
; *********************************************************
LIST p=16F628 ; TELLS THE PROGRAMMER WHAT CHIP WE'RE USING.
include "P16F628.inc" ; INCLUDES DEFAULTS FOR THE CHIP.
ERRORLEVEL 0, -302 ;suppress bank selection messages
__config 0x3D18 ;sets the configuration settings (oscillator type etc.)
;__config _INTRC_OSC_NOCLKOUT & _LVP_OFF & _WDT_OFF & _PWRTE_OFF

cblock 0x20 ;start of general purpose registers
count ;used in looping routines
count1 ;used in delay routine
counta ;used in delay routine
countb ;used in delay routine
tmp1 ;temporary storage
tmp2
templcd ;temp store for 4 bit mode
templcd2
endc
; **************************************
; LCD SETUP, DATA LINES, CONTROL LINES
LCD_PORT Equ PORTA
LCD_TRIS Equ TRISA
LCD_RS Equ 0x04 ;LCD handshake lines
LCD_RW Equ 0x06
LCD_E Equ 0x07
; END OF LCD SETUP
; **************************************
; Additional LEDs and Switches
LEDPORT Equ PORTB ;set constant LEDPORT = 'PORTA'
SWPORT Equ PORTB ;set constant SWPORT = 'PORTA'
LEDTRIS Equ TRISB
SWTRIS Equ TRISB

SW1 Equ 0x00 ; Identifies Switch One on Schematic diagram
SW2 Equ 0x01 ; Identifies Switch Two on Schematic diagram
SW3 Equ 0x02 ; Identifies Switch Three on Schematic diagram

LED1 Equ 0x04 ; Identifies LED One on the Schematic diagram
LED2 Equ 0x05 ; Identifies LED Two on the Schematic diagram
LED3 Equ 0x06 ; Identifies LED Three on the Schematic diagram

; **************************************
; end of LEDs and switches
org 0x0000 ;org sets the origin, 0x0000 for the 16F628
movlw 0x07
movwf CMCON ;turn comparators off (make it like a 16F84)
Initialise clrf count
clrf PORTA
clrf PORTB

SetPorts bsf STATUS, RP0 ;select bank 1
movlw b'00001111' ; 4 outputs (RB4-RB7), 4 inputs (RB0-RB3)
movwf SWTRIS
bcf STATUS, RP0 ;select bank 0
clrf LEDPORT ;set all outputs low
clrf SWPORT


movwf LCD_TRIS
bcf STATUS, RP0 ;select bank 0
call Delay100 ;wait for LCD to settle

call LCD_Init ;setup LCD
; ***************************************
; BEGINNING OF PROGRAM
clrf count ;set counter register to zero
Message movf count, w ;put counter value in W
call Text ;get a character from the text table
xorlw 0x00 ;is it a zero?
btfsc STATUS, Z
goto NextMessage
call LCD_Char
call Delay100 ; puts a delay in between characters.
incf count, f
goto Message
NextMessage call LCD_Line2 ;move to 2nd row, first column
clrf count ;set counter register to zero
Message2 movf count, w ;put counter value in W
call CrdText ;get a character from the credit text table
xorlw 0x00 ;is it a zero?
btfsc STATUS, Z
goto StartProg
call LCD_Char
call Delay100 ; puts a delay in between characters.
incf count, f
goto Message2
StartProg ; Start of countdown program
;call asecond ; Puts a second before starting program
;call LCD_Clr ; Clears LCD screen
;call LCD_CurOff ; Turns off the LCD cursor


Stop goto Stop ;endless loop
; ***************************************
;Subroutines and text tables
;LCD routines
;Initialise LCD
LCD_Init movlw 0x20 ;Set 4 bit mode
call LCD_Cmd
movlw 0x28 ;Set display shift
call LCD_Cmd
movlw 0x06 ;Set display character mode
call LCD_Cmd
movlw 0x0d ;Set display on/off and cursor command
call LCD_Cmd
call LCD_Clr ;clear display
retlw 0x00
; command set routine
LCD_Cmd movwf templcd
swapf templcd, w ;send upper nibble
andlw 0x0f ;clear upper 4 bits of W
movwf LCD_PORT
bcf LCD_PORT, LCD_RS ;RS line to 0
call Pulse_e ;Pulse the E line high
movf templcd, w ;send lower nibble
andlw 0x0f ;clear upper 4 bits of W
movwf LCD_PORT
bcf LCD_PORT, LCD_RS ;RS line to 0
call Pulse_e ;Pulse the E line high
call Delay5
retlw 0x00
LCD_CharD addlw 0x30
LCD_Char movwf templcd
swapf templcd, w ;send upper nibble
andlw 0x0f ;clear upper 4 bits of W
movwf LCD_PORT
bsf LCD_PORT, LCD_RS ;RS line to 1
call Pulse_e ;Pulse the E line high
movf templcd, w ;send lower nibble
andlw 0x0f ;clear upper 4 bits of W
movwf LCD_PORT
bsf LCD_PORT, LCD_RS ;RS line to 1
call Pulse_e ;Pulse the E line high
call Delay5
retlw 0x00
LCD_Line1 movlw 0x80 ;move to 1st row, first column
call LCD_Cmd
retlw 0x00
LCD_Line2 movlw 0xc0 ;move to 2nd row, first column
call LCD_Cmd
retlw 0x00
LCD_Line1W addlw 0x80 ;move to 1st row, column W
call LCD_Cmd
retlw 0x00
LCD_Line2W addlw 0xc0 ;move to 2nd row, column W
call LCD_Cmd
retlw 0x00
LCD_CurOn movlw 0x0d ;Set display on/off and cursor command
call LCD_Cmd
retlw 0x00
LCD_CurOff movlw 0x0c ;Set display on/off and cursor command
call LCD_Cmd
retlw 0x00
LCD_Clr movlw 0x01 ;Clear display
call LCD_Cmd
retlw 0x00
LCD_HEX movwf tmp1
swapf tmp1, w
andlw 0x0f
call HEX_Table
call LCD_Char
movf tmp1, w
andlw 0x0f
call HEX_Table
call LCD_Char
retlw 0x00
; ***************************************
; DELAY ROUTINES

asecond movlw d'1000' ; delay one second (1000milliseconds)
goto d0
Delay255 movlw 0xff ;delay 255 mS (0xff in hexadecimal)
goto d0
Delay100 movlw d'100' ;delay 100mS
goto d0
Delay50 movlw d'50' ;delay 50mS
goto d0
Delay20 movlw d'20' ;delay 20mS
goto d0
Delay5 movlw 0x05 ;delay 5.000 ms (4 MHz clock)
d0 movwf count1
d1 movlw 0xC7 ;delay 1mS
movwf counta
movlw 0x01
movwf countb
Delay_0
decfsz counta, f
goto $+2
decfsz countb, f
goto Delay_0
decfsz count1 ,f
goto d1
retlw 0x00

; END OF DELAY ROUTINES
; ***************************************
; PULSE THE LCD E LINE
Pulse_e bsf LCD_PORT, LCD_E
nop
bcf LCD_PORT, LCD_E
retlw 0x00

; ***************************************
;end of LCD routines


HEX_Table ADDWF PCL , f
RETLW 0x30
RETLW 0x31
RETLW 0x32
RETLW 0x33
RETLW 0x34
RETLW 0x35
RETLW 0x36
RETLW 0x37
RETLW 0x38
RETLW 0x39
RETLW 0x41
RETLW 0x42
RETLW 0x43
RETLW 0x44
RETLW 0x45
RETLW 0x46


; ***************************************
; Main text for countdown timer (LCD text)

; Countdown timer
Text addwf PCL, f
retlw 'C' ; Character 1
retlw 'o' ; Character 2
retlw 'u' ; Character 3
retlw 'n' ; Character 4
retlw 't' ; Character 5
retlw 'd' ; Character 6
retlw 'o' ; Character 7
retlw 'w' ; Character 8
retlw 'n' ; Character 9
retlw ' ' ; Character 10
retlw 'T' ; Character 11
retlw 'i' ; Character 12
retlw 'm' ; Character 13
retlw 'e' ; Character 14
retlw 'r' ; Character 15
retlw 0x00


; ***************************************
; Credits Text for program (LCD text)

; By Dominic Rawle
CrdText addwf PCL, f
retlw 'B' ; Character 1
retlw 'y' ; Character 2
retlw ' ' ; Character 3
retlw 'D' ; Character 4
retlw 'o' ; Character 5
retlw 'm' ; Character 6
retlw 'i' ; Character 7
retlw 'n' ; Character 8
retlw 'i' ; Character 9
retlw 'c' ; Character 10
retlw ' ' ; Character 11
retlw 'R' ; Character 12
retlw 'a' ; Character 13
retlw 'w' ; Character 14
retlw 'l' ; Character 15
retlw 'e' ; Character 15
retlw 0x00

; ***************************************

Text2 ADDWF PCL, f
RETLW 'R'
RETLW 'e'
RETLW 'a'
RETLW 'd'
RETLW 'y'
RETLW '.'
RETLW '.'
RETLW '.'
RETLW 0x00
end
 

Markd77

Joined Sep 7, 2009
2,806
At first glance I see a couple of potential problems:
LEDPORT Equ PORTB ;set constant LEDPORT = 'PORTA'
SWPORT Equ PORTB ;set constant SWPORT = 'PORTA'
LEDTRIS Equ TRISB
SWTRIS Equ TRISB
Is everything supposed to be portB?
and

asecond movlw d'1000' ; delay one second (1000milliseconds)
Max value 255 for files. You will have to find some other way to to get 1 second - possibly the easiest way is to call delay 4 times at 250ms.
 

Thread Starter

bluebrakes

Joined Oct 17, 2009
252
you are the best...

I can't believe i never noticed that.

As for the delay, I never knew that.

The timer is starting to take some real shape now. I'm working on the bleeper routine at this very minute. I bought a piezo buzzer today (perfect as it only draws 10mA), so i should be able to connect it straight up.
 

Thread Starter

bluebrakes

Joined Oct 17, 2009
252
Ok guys i've hit a brick wall...

Below is next step to the program, the actual countdown timer.
The problem i'm facing is when the 'StartTimer' routine is present in the program, the PIC keeps repeating the intro routine over and over. If i remove the 'StartTimer' routine, everything works as it should. There is clearly a conflict somewhere, but i just can't see it.

here is the code...

Rich (BB code):
call Delay100 ;wait for LCD to settle
call LCD_Init ;setup LCD
; ***************************************
; BEGINNING OF PROGRAM
clrf count ;set counter register to zero
call SngBeep
Message movf count, w ;put counter value in W
call Text ;get a character from the text table
xorlw 0x00 ;is it a zero?
btfsc STATUS, Z
goto NextMessage
call LCD_Char
call Delay100 ; puts a delay in between characters.
incf count, f
goto Message
NextMessage call LCD_Line2 ;move to 2nd row, first column
clrf count ;set counter register to zero
Message2 movf count, w ;put counter value in W
call CrdText ;get a character from the credit text table
xorlw 0x00 ;is it a zero?
btfsc STATUS, Z
goto StartProg
call LCD_Char
call Delay100 ; puts a delay in between characters.
incf count, f
goto Message2
StartProg ; Start of countdown program
call Delay255 ; Puts a delay before starting program
call Delay255 ; Puts a delay before starting program
call Delay255 ; Puts a delay before starting program
call Delay255 ; Puts a delay before starting program
 
call LCD_Clr ; Clears LCD screen
call LCD_CurOff ; Turns off the LCD cursor
clrf NumL ; Clears the memory of the variable
clrf NumH ; Clears the memory of the variable
 
clrf count ;set counter register to zero
Message3 movf count, w ;put counter value in W
call SetText ;get a character from the credit text table
xorlw 0x00 ;is it a zero?
btfsc STATUS, Z
goto stage2
call LCD_Char
incf count, f
goto Message3
stage2 movlw d'2'
call LCD_CurOn ; turn the LCD cursor on
call LCD_Line2W ; move to 2nd row, third column
 
call Convert ;convert to decimal 
movf Tens, w
call LCD_CharD
movf Ones, w
call LCD_CharD
movlw ' ' ;display a 'space'
call LCD_Char
movlw 'M'
call LCD_Char
movlw 'i'
call LCD_Char
movlw 'n'
call LCD_Char
movlw 's'
call LCD_Char
call SngBeep
incfsz NumL, f
goto Loop1
incf NumH, f
;Next call Delay255 ;wait so you can see the digits change
 
 
; Loop waits for a button press.
Loop1 btfss SWPORT, SW1 ; Increase time button
call Switch1 ; Call sub routine when SW1 is pressed
btfss SWPORT, SW2 ; Reset time button
call Switch2 ; Call sub routine when SW2 is pressed
btfss SWPORT, SW3 ; Start Timer button
call Switch3
Goto Loop1
 
Switch1 goto stage2
retlw 0x00
 
Switch2 clrf NumL ; Clears the memory of the variable
clrf NumH ; Clears the memory of the variable
goto stage2
retlw 0x00
 
Switch3 call SngBeep
goto StartTimer
retlw 0x00
 
StartTimer call LCD_Clr
call LCD_CurOff
clrf count ;set counter register to zero
TimerMessage movf count, w ;put counter value in W
call TimStart ;get a character from the credit text table
xorlw 0x00 ;is it a zero?
btfsc STATUS, Z
goto stage3
call LCD_Char
incf count, f
goto TimerMessage 
 
stage3 call LCD_Line2W ; move to 2nd row, third column
 
call Convert ;convert to decimal 
movf Tens, w
call LCD_CharD
movf Ones, w
call LCD_CharD
movlw ' ' ;display a 'space'
call LCD_Char
movlw 'M'
call LCD_Char
movlw 'i'
call LCD_Char
movlw 'n'
call LCD_Char
movlw 's'
call LCD_Char
call SngBeep
decfsz NumL, f
goto Part2
decf NumH, f
Part2 call Delay255
goto stage3
 
Stop goto Stop ;endless loop
; ***************************************
;Subroutines and text tables
;LCD routines
;Initialise LCD
LCD_Init movlw 0x20 ;Set 4 bit mode
call LCD_Cmd
movlw 0x28 ;Set display shift
call LCD_Cmd
movlw 0x06 ;Set display character mode
call LCD_Cmd
; movlw 0x0c will turn off cursor, replacing c with d will turn it on.
movlw 0x0c ;Set display on/off and cursor command
call LCD_Cmd
call LCD_Clr ;clear display
retlw 0x00
; command set routine
LCD_Cmd movwf templcd
swapf templcd, w ;send upper nibble
andlw 0x0f ;clear upper 4 bits of W
movwf LCD_PORT
bcf LCD_PORT, LCD_RS ;RS line to 0
call Pulse_e ;Pulse the E line high
movf templcd, w ;send lower nibble
andlw 0x0f ;clear upper 4 bits of W
movwf LCD_PORT
bcf LCD_PORT, LCD_RS ;RS line to 0
call Pulse_e ;Pulse the E line high
call Delay5
retlw 0x00
LCD_CharD addlw 0x30
LCD_Char movwf templcd
swapf templcd, w ;send upper nibble
andlw 0x0f ;clear upper 4 bits of W
movwf LCD_PORT
bsf LCD_PORT, LCD_RS ;RS line to 1
call Pulse_e ;Pulse the E line high
movf templcd, w ;send lower nibble
andlw 0x0f ;clear upper 4 bits of W
movwf LCD_PORT
bsf LCD_PORT, LCD_RS ;RS line to 1
call Pulse_e ;Pulse the E line high
call Delay5
retlw 0x00
LCD_Line1 movlw 0x80 ;move to 1st row, first column
call LCD_Cmd
retlw 0x00
LCD_Line2 movlw 0xc0 ;move to 2nd row, first column
call LCD_Cmd
retlw 0x00
LCD_Line1W addlw 0x80 ;move to 1st row, column W
call LCD_Cmd
retlw 0x00
LCD_Line2W addlw 0xc0 ;move to 2nd row, column W
call LCD_Cmd
retlw 0x00
LCD_CurOn movlw 0x0d ;Set display on/off and cursor command
call LCD_Cmd
retlw 0x00
LCD_CurOff movlw 0x0c ;Set display on/off and cursor command
call LCD_Cmd
retlw 0x00
LCD_Clr movlw 0x01 ;Clear display
call LCD_Cmd
retlw 0x00
LCD_HEX movwf tmp1
swapf tmp1, w
andlw 0x0f
call HEX_Table
call LCD_Char
movf tmp1, w
andlw 0x0f
call HEX_Table
call LCD_Char
retlw 0x00
 
SngBeep bsf LEDPORT, LED1
call Delay100
bcf LEDPORT, LED1
; ***************************************
; DELAY ROUTINES
 
Delay255 movlw 0xff ;delay 255 mS (0xff in hexadecimal)
goto d0
Delay100 movlw d'100' ;delay 100mS
goto d0
Delay50 movlw d'50' ;delay 50mS
goto d0
Delay20 movlw d'20' ;delay 20mS
goto d0
Delay5 movlw 0x05 ;delay 5.000 ms (4 MHz clock)
d0 movwf count1
d1 movlw 0xC7 ;delay 1mS
movwf counta
movlw 0x01
movwf countb
Delay_0
decfsz counta, f
goto $+2
decfsz countb, f
goto Delay_0
decfsz count1 ,f
goto d1
retlw 0x00
 
; END OF DELAY ROUTINES
; ***************************************
; PULSE THE LCD E LINE
Pulse_e bsf LCD_PORT, LCD_E
nop
bcf LCD_PORT, LCD_E
retlw 0x00
 
; ***************************************
;end of LCD routines
 
 
HEX_Table ADDWF PCL , f
RETLW 0x30
RETLW 0x31
RETLW 0x32
RETLW 0x33
RETLW 0x34
RETLW 0x35
RETLW 0x36
RETLW 0x37
RETLW 0x38
RETLW 0x39
RETLW 0x41
RETLW 0x42
RETLW 0x43
RETLW 0x44
RETLW 0x45
RETLW 0x46
 
 
; ***************************************
; Main text for countdown timer (LCD text)
 
; Countdown timer
Text addwf PCL, f
retlw 'C' ; Character 1
retlw 'o' ; Character 2
retlw 'u' ; Character 3
retlw 'n' ; Character 4
retlw 't' ; Character 5
retlw 'd' ; Character 6
retlw 'o' ; Character 7
retlw 'w' ; Character 8
retlw 'n' ; Character 9
retlw ' ' ; Character 10
retlw 'T' ; Character 11
retlw 'i' ; Character 12
retlw 'm' ; Character 13
retlw 'e' ; Character 14
retlw 'r' ; Character 15
retlw 0x00
 
 
; ***************************************
; Credits Text for program (LCD text)
 
; By Dominic Rawle 
CrdText addwf PCL, f
retlw 'B' ; Character 1
retlw 'y' ; Character 2
retlw ' ' ; Character 3
retlw 'D' ; Character 4
retlw 'o' ; Character 5
retlw 'm' ; Character 6
retlw 'i' ; Character 7
retlw 'n' ; Character 8
retlw 'i' ; Character 9
retlw 'c' ; Character 10
retlw ' ' ; Character 11
retlw 'R' ; Character 12
retlw 'a' ; Character 13
retlw 'w' ; Character 14
retlw 'l' ; Character 15
retlw 'e' ; Character 16
retlw 0x00
 
; ***************************************
 
SetText ADDWF PCL, f
retlw 'S' ; Character 1
retlw 'e' ; Character 2
retlw 't' ; Character 3
retlw ' ' ; Character 4
retlw 'T' ; Character 5
retlw 'i' ; Character 6
retlw 'm' ; Character 7
retlw 'e' ; Character 8
retlw 'r' ; Character 9
retlw 0x00
; ****************************************
TimStart ADDWF PCL, f
retlw 'T' ; Character 1
retlw 'i' ; Character 2
retlw 'm' ; Character 3
retlw 'e' ; Character 4
retlw 'r' ; Character 5
retlw ' ' ; Character 6
retlw 'S' ; Character 7
retlw 't' ; Character 8
retlw 'a' ; Character 9
retlw 'r' ; Character 10
retlw 't' ; Character 11
retlw 'e' ; Character 12
retlw 'd' ; Character 13
retlw 0x00
 
; ****************************************
TimStop ADDWF PCL, f
retlw 'T' ; Character 1
retlw 'i' ; Character 2
retlw 'm' ; Character 3
retlw 'e' ; Character 4
retlw 'r' ; Character 5
retlw ' ' ; Character 6
retlw 'S' ; Character 7
retlw 't' ; Character 8
retlw 'o' ; Character 9
retlw 'p' ; Character 10
retlw 'p' ; Character 11
retlw 'e' ; Character 12
retlw 'd' ; Character 13
retlw 0x00 
; ******************************************************************
;This routine downloaded from http://www.piclist.com
Convert: ; Takes number in NumH:NumL
; Returns decimal in
; TenK:Thou:Hund:Tens:Ones
swapf NumH, w
iorlw B'11110000'
movwf Thou
addwf Thou,f
addlw 0XE2
movwf Hund
addlw 0X32
movwf Ones
movf NumH,w
andlw 0X0F
addwf Hund,f
addwf Hund,f
addwf Ones,f
addlw 0XE9
movwf Tens
addwf Tens,f
addwf Tens,f
swapf NumL,w
andlw 0X0F
addwf Tens,f
addwf Ones,f
rlf Tens,f
rlf Ones,f
comf Ones,f
rlf Ones,f
movf NumL,w
andlw 0X0F
addwf Ones,f
rlf Thou,f
movlw 0X07
movwf TenK
; At this point, the original number is
; equal to
; TenK*10000+Thou*1000+Hund*100+Tens*10+Ones
; if those entities are regarded as two's
; complement binary. To be precise, all of
; them are negative except TenK. Now the number
; needs to be normalized, but this can all be
; done with simple byte arithmetic.
movlw 0X0A ; Ten
Lb1:
addwf Ones,f
decf Tens,f
btfss 3,0
goto Lb1
Lb2:
addwf Tens,f
decf Hund,f
btfss 3,0
goto Lb2
Lb3:
addwf Hund,f
decf Thou,f
btfss 3,0
goto Lb3
Lb4:
addwf Thou,f
decf TenK,f
btfss 3,0
goto Lb4
retlw 0x00
end
Edit: Thanks Ke5nnt, ref the code tag.
 
Last edited:

ke5nnt

Joined Mar 1, 2009
384
Here are a couple things from reading your thread:

When entering code in the forums, it makes it easier/cleaner to wrap in in code tag, e.g. [ code ] insert code here [ /code ] (without spaces of course).

If you're having trouble with delay routines for longer delays (the one second delay for instance) there is a great tool you can use HERE.

Just enter your clock speed in MHz and the time in seconds. If using a 32KHz clock enter 0.032 and enter 1 in the delay line and it generates code in Assembly. Using those figures, a one second delay would be:
Rich (BB code):
1secDLY movlw    0x3F
    movwf    d1 (or the name of your file, I use "count1")
    movlw    0x07
    movwf    d2 (or the name of your file, I use "count2")
Delay_0
    decfsz    d1, f
    goto    $+2
    decfsz    d2, f
    goto    Delay_0
        return
Then you can "call 1secDLY"...

I'll continue to look at your code and see if I can spot something causing your repeat problem.
 

Markd77

Joined Sep 7, 2009
2,806
I gave it a quick run through MPLab Sim and got the attached error:
It probably means you have nested calls too deep or there is a call without a return somewhere. The stack can only hold 8 addresses and when it gets full unexpected things happen.
Your code is progressing at an impressive rate, but I think you might have to take a while to look at the sim.
 

Attachments

Thread Starter

bluebrakes

Joined Oct 17, 2009
252
Thanks Mark.

I found something quite interesting about this...

I removed a single line of code, the same thing happens but it displays an extra character before going back to the intro routine.

Would this be something to do with the quantity of the code and that the PIC has reached it's maximum instruction length?
 

Markd77

Joined Sep 7, 2009
2,806
That's to be expected with the stack overflow problem. Every time a call is made, the address that the call was made from is put onto the stack.
The return statement moves the program counter back to that point. If more that 8 calls have happened without returns then the first item on the stack is overwritten. That means that at some point the program counter is going to be set to the wrong value and the code jumps to the wrong point.

There is also a type of problem that is caused by data tables that cross the page boundaries that you could be running into. The problem is that PCL is 8 bit and adding something to PCL that causes it to go over 255 (0xFF).
If you click view and then disassembly listing, the first column is the location of the instruction on the chip. Any table that encompasses 0xFF or 0x1FF, etc will have problems.
 

Markd77

Joined Sep 7, 2009
2,806
Other code that crosses a boundary should be OK I think.
You can use ORG 0x0100 to move the start of a table to just after the page boundary.
 

Thread Starter

bluebrakes

Joined Oct 17, 2009
252
is there any alternatives i could use to avoid this altogether?

i've been trying to strip down the number of calls in the code. This has helped alot but still hasn't solved the problem entirely.

How do I know when i've reached the maximum storage capacity of the PIC anyway?
 

Markd77

Joined Sep 7, 2009
2,806
Unfortunately not on this PIC. I think I heard the PIC18s don't have this problem.
You are OK on storage so far - click 'view', 'Memory usage gauge'.
Data memory gauge doesn't work for me but program usage does.
 

Thread Starter

bluebrakes

Joined Oct 17, 2009
252
So as i understand it, my problem is that the PIC is getting confused due to the number of calls being made on subroutines.

So for the subroutines that consist of a matter of a couple of lines, should i get rid of these and put the code directly in place to cut down that way?

It would make it a bit more complex to read to but if it solves the problem i'm up for anything.
 
Top