Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

reseting after a set value

Status
Not open for further replies.

johnl69

Member
Hi all

Im having problems sorting out a subroutine.
Im trying to increase a time displayed on an lcd by pressing a button, I can get the time to increase from 0 to 23 but at the next press it increases to 30 instead of reseting to zero and I cant figure out how I can reset the file to zero.

any help would be much appreciated,

this is the code that I have so far

Code:
INC_HOURS
  BANKSEL HOURSUNIT
  INCF HOURSUNIT,F  ;INC UNITS BY 1
  MOVF HOURSUNIT,W
  SUBWF TIME,W   
  BTFSS STATUS,2  ;CHECK IF UNITS ARE 9/3
  RETURN     ;NO, GO BACK
  MOVLW 30H    ;YES SO... 
  MOVWF HOURSUNIT  ;RESET UNITS TO 0
  BANKSEL HOURSTEN  ;AND
  INCF HOURSTEN,F  ;INC HOURS BY 1
  MOVF HOURSTEN,W
  SUBLW 32H
  BTFSS STATUS,2  ;CHECK IF HOURS ARE 2
  RETURN     ;NO, GO BACK
  BANKSEL TIME
  MOVLW 34H    ;YES SO...
  MOVWF TIME   ;SET MAX UNITS TO 3
  RETURN
 
Code:
Movlw 30h    ;yes So... 
Movwf Hoursunit  ;reset Units To 0
Ummm.... If you want to set it to zero, why are you loading it with 30? :rolleyes:
Try,
Code:
clrf Hoursunit  ;reset Units To 0
Any reason for using hexadecimal time? Enter decimal numbers by prefixing them with a period:

.48 is equal to forty eight.
 
Last edited:
Its 30H because that is the hex code for 0 to be displayed on the lcd I did try clrf but it displays a blank characture,
 
I see what you are attempting now. A better method is to make the time reside in a 24bit number: HH:MM:SS. Then do regular math on this number (You'll need to break it into 3 8bit chunks on a 16F PIC. Then you write a separate subroutine to convert this 24bit number into codes for the LCD. This will make the math/code for incrementing the time, checking alarms, etc much more intuitive. It will also make the code easier to maintain. Imagine trying to port your code above to a different display.
 
I did try it with just 2 files (hours and minutes im not using the secounds) but as the file increased, the numbers displayed went from 0 to 9 and then carried on with : ; < = > ? before going to 10, so that why im increasing the digits individualy and then storing them as 8bit BCD to compare with the data from the RTC for the alarms.
 
If you intend to make a 12HR clock you can use 2 "files" to make a 16bit number. Since there are 43200 seconds on a 12HR period, you simply increment this 16bit number until you hit 43200 and then zero it. To display this number, as time on your LCD, you would subtract 3600 from it until the remainder is less than 3600. The number of subtractions to do this is the number of hours to display. Then you take this remainder and subtract 60 from it until the remainder is less than 60. The number of subtractions to do this is the number of minutes to display. The final remainder is the number of seconds to display.
The 16bit number is easy to compare to other similarly formatted numbers for the alarm settings, etc.
EDIT: Does your "RTC" output ASCII? What RTC chip are you using?
 
Last edited:
The RTC is the DS1307 and outputs in 8bit BCD, The program ive written read the time from the RTC and stores them in files HOURS and MINUTES then the BCD_BIN routine converts these files into 4 files HOURSTENS, HOURSUNITS (and the same for minutes) and adds on the extra 30h needed to output to ascii for the LCD
 
Doing BCD math is really messy. Much easier to save all as data with a granularity of 1 second. But if you insist on using BCD on a micro designed for binary:
You need to store the digits without the "extra 30h" added. Only add the "extra 30h" when you send the data to the display. Then incrementing the BCD digits becomes easier. To increment the minutes in pseudo code:

inc MinuteUnits
if MinuteUnits = 10 then (MinuteUnits = 0 and inc MinuteTens). else exit.
if MinuteTens = 6 then (MinuteTens = 0 and inc HoursUnits). else exit.
Here is gets messier, because the overflow for the HoursUnits is different depending on whether HoursTens is a 0,1 or 2. Remember we have already inc'd HoursUnits above.
if HoursTens < 2 AND HoursUnits = 10 then (HoursUnits = 0 and inc HoursTens).
if HoursTens = 2 AND HoursUnits = 4 then (HoursUnits = 0 and HoursTens = 0).
exit.
 
Last edited:
You might consider incrementing or decrementing a packed BCD field directly (00..23 or 00..59). It's easy enough to seperate the digits and add ASCII '0' (0x30) to each value afterwards for display on the LCD.

Good luck with your project. Mike

Code:
;
Inc_Hour
        incf    Hour,F          ; inc field                       |B0
        movf    Hour,W          ;                                 |B0
        addlw   h'06'           ; lo nybble < 10?                 |B0
        skpndc                  ; yes, skip                       |B0
        movwf   Hour            ; else update                     |B0
        movlw   h'24'           ; use 24 for upper limit          |B0
        xorwf   Hour,W          ; upper limit?                    |B0
        skpnz                   ; no, skip                        |B0
        clrf    Hour            ; else, reset to 00               |B0
;
Dec_Hour
        movf    Hour,W          ;                                 |B0
        skpnz                   ;                                 |B0
        movlw   h'24'           ;                                 |B0
        addlw   -1              ;                                 |B0
        skpdc                   ;                                 |B0
        addlw   -6              ;                                 |B0
        movwf   Hour            ;                                 |B0
;
 
Last edited:
You might consider incrementing or decrementing a packed BCD field directly (00..23 or 00..59). It's easy enough to seperate the digits and add ASCII '0' (0x30) to each value afterwards for display on the LCD.

Good luck with your project. Mike

Code:
;
Inc_Hour
        incf    Hour,F          ; inc field                       |B0
        movf    Hour,W          ;                                 |B0
        addlw   h'06'           ; lo nybble < 10?                 |B0
        skpndc                  ; yes, skip                       |B0
        movwf   Hour            ; else update                     |B0
        movlw   h'24'           ; use 24 for upper limit          |B0
        xorwf   Hour,W          ; upper limit?                    |B0
        skpnz                   ; no, skip                        |B0
        clrf    Hour            ; else, reset to 00               |B0
;
Dec_Hour
        movf    Hour,W          ;                                 |B0
        skpnz                   ;                                 |B0
        movlw   h'24'           ;                                 |B0
        addlw   -1              ;                                 |B0
        skpdc                   ;                                 |B0
        addlw   -6              ;                                 |B0
        movwf   Hour            ;                                 |B0
;


Now Im confused whats skpdc and skpnz mean? Ive never seen them before
 
The skpdc (skip on digit carry), skpndc (skip not digit carry), and skpnz (skip not zero) pseudo opcodes are documented in the MPASM section of the MPLAB Help file... Sorry for the confusion... I find "skpnz" (skip not zero) much more intuitive than the BTFSC STATUS,Z instruction...

Mike
 
Last edited:
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top