3 Attachment(s)
A real live working example of ONE Button usage...
This appended example is the basis for the worlds most inaccurate clock.
It’s demonstrating ONE Button usage.
Press the Button momentarily and it will flip the display between 12/24 Hour Mode.
Press the Button for an extended time and it will jump into a Menu for you to set the time. Note the creative use of the CURSOR to indicate when a SET Function has been executed...
It’s just a ditty to show how you can do things with ONE Button.
And shows that code previously written (Olympic Timer) for a PIC16F876 can be quickly and easily ported and modified for a PIC16F628, or PIC16F628A or B or C...
It’s also a teaser for half a dozen recent (Timer) threads (and for a gentleman searching for an elapsed timer – hint – hint – somebody nudge him to look at this thread!!!!) to show what can be done with 10 minutes worth of code, half a bucket of Cafe Nero's finest and a plastic straw...
Code:
'
' Buttons.bas
' ---------------
' by Melanie
' written on a Laptop in a lunchbreak in a Cafe Nero
' in Londons famous Regent Street... 7th June 2006
'
' A simple demonstrator as to what can be done
' with just ONE Button and an LCD...
' Some Code stolen from OLYMPIC TIMER
'
'
' Device Programming Options
' --------------------------
@ DEVICE pic16F628, INTRC_OSC_NOCLKOUT
' System Clock Options
@ DEVICE pic16F628, WDT_ON ' Watchdog Timer
@ DEVICE pic16F628, PWRT_ON ' Power-On Timer
@ DEVICE pic16F628, BOD_ON ' Brown-Out Detect
@ DEVICE pic16F628, MCLR_OFF ' Master Clear Options (Internal)
@ DEVICE pic16F628, LVP_OFF ' Low-Voltage Programming
@ DEVICE pic16F628, CPD_OFF ' Data Memory Code Protect
@ DEVICE pic16F628, PROTECT_OFF ' Program Code Protection
'
' Hardware Defines
' ----------------
'
' LCD Display
' -----------
Define LCD_DREG PORTB ' Port for LCD Data
Define LCD_DBIT 4 ' Use upper 4 bits of Port
Define LCD_RSREG PORTB ' Port for RegisterSelect (RS) bit
Define LCD_RSBIT 3 ' Port Pin for RS bit
Define LCD_EREG PORTB ' Port for Enable (E) bit
Define LCD_EBIT 2 ' Port Pin for E bit
Define LCB_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)
'
' Buttons
' -------
MyButton var PortB.0
'
' Software Defines
' ----------------
AMPMFlag var BYTE ' Flag for 12/24 Hour Mode 0=24, 1=12
' - Yes I know it's a BYTE but I can't be bothered
ButtonPress var BYTE ' Button Counter Variable
DataA var BYTE
Hours var BYTE
Hundredths var BYTE
MenuStep var BYTE ' Status Indicator for Menu Display
Minutes var BYTE
Seconds var BYTE
TMR1Cal var BYTE ' Timer Calibration Value
TMR1CalAR var BYTE ' Timer Advance/Retard Indicator
TMR1RunOn var WORD ' variable holding TMR1 Run-On value
'
' EEPROM Settings
' ---------------
Data @0,0 ' Advance/Retard Indicator
Data 0 ' Calibration Value
Data 0 ' 12/24 Hour Flag
'
' Software Constants
' ------------------
LongPress con 20 ' Change this value for desired SET
' function trip-point in 50mS steps
' Currently set for 1 Second
TMR1CalMax con 100 ' Maximum adjustment (+/-100uS per 10mS interrupt)
TMR1Preset con $D910 ' 10mS Timer Reload value, offset by 20uS
' to allow for TMR1 Setting Calculations
'
' Initialise PIC
' --------------
TRISA=%00000000 ' PortA I/O Configuration
TRISB=%00000001 ' PortB I/O Configuration
CMCON=%00000111 ' Comparators OFF
OPTION_REG.7=0 ' Enable weak Pull-Ups (used for PressButton)
'
' Initialise Main Program
' -----------------------
Pause 2000 ' Timeout for LCD Hardware to wake-up...
Read 0,TMR1CalAR ' Read Calibration Advance/Retard Indicator
Read 1,TMR1Cal ' Read Calibration Value
Read 2,AMPMFlag ' It's what it says...
Hundredths=0 ' Reset Timer Counter variables
Seconds=0
Minutes=0
Hours=0
'
' Initialise TMR1 Interrupts
' --------------------------
Gosub SetTimer ' Set the Timer for next 10mS Interrupt
On Interrupt goto TickCount
PIE1.0=1 ' Enable TMR1 Interrupts
INTCON.6=1 ' Enable all unmasked Interrupts
INTCON.7=1 ' Enable Global Interrupts
DisplayRestart:
LCDOut $FE,1 ' Clear Display
'
' Main Program Loop
' -----------------
Enable
DisplayLoop:
LCDOut $FE,$0C
If AMPMFlag=0 then
'
' Here we have got a 24 Hour Clock Display
' ----------------------------------------
LCDOut $FE,$84,DEC2 Hours,":",DEC2 Minutes,":",DEC2 Seconds
else
'
' and here we have a 12 Hour Clock Display
' ----------------------------------------
LCDOut $FE,$82
DataA=Hours
If DataA=0 then DataA=12
If DataA>12 then DataA=DataA-12
If DataA<10 then LCDOut " "
LCDOut #DataA,":",DEC2 Minutes,":",DEC2 Seconds," "
If Hours>11 then
LCDOut "PM"
else
LCDOut "AM"
endif
endif
'
' Check For Button Press
' ----------------------
Gosub GetButton
'
' Toggle 24 Hour Mode
' -------------------
If ButtonPress=1 then
AMPMFlag=AMPMFlag^1
Write 2,AMPMFlag
Goto DisplayRestart
endif
If ButtonPress<>2 then goto DisplayLoop
Disable
'
' Setup Mode
' ----------
LCDOut $FE,1,"Set Time Please:"
LCDOut $FE,$C4,DEC2 Hours,":",DEC2 Minutes,":",DEC2 Seconds,$FE,$C5
MenuStep=0
MenuLoop:
Gosub GetButton
'
' SET Mode
' --------
If ButtonPress=2 then
MenuStep=MenuStep+1
If MenuStep=3 then
LCDOut $FE,1,$FE,$83,"Thank You",$FE,$C0,"Have a Nice Day"
Pause 2000
Goto DisplayRestart
endif
endif
If ButtonPress=1 then
'
' Hours
' -----
If MenuStep=0 then
Hours=Hours+1
If Hours>23 then Hours=0
LCDOut $FE,$C4,DEC2 Hours
endif
'
' Minutes
' -------
If MenuStep=1 then
Minutes=Minutes+1
If Minutes>59 then Minutes=0
LCDOut $FE,$C7,DEC2 Minutes
endif
'
' Seconds
' -------
If MenuStep=2 then
Seconds=Seconds+1
If Seconds>59 then Seconds=0
LCDOut $FE,$CA,DEC2 Seconds
endif
endif
'
' Ensure Cursor is in a nice place...
' --------------------------------
LCDOut $FE,$0E
If MenuStep=0 then
LCDOut $FE,$C5
else
If MenuStep=1 then
LCDOut $FE,$C8
else
LCDOut $FE,$CB
endif
endif
Goto MenuLoop
'
' Subroutine weighs-up users finger
' in multiples of 50mS
' Constant LONGPRESS determines boredom level
' -------------------------------------------
' on Exit...
' ButtonPress=0 - No Press
' ButtonPress=1 - Short Press
' ButtonPress=2 - Long Press
GetButton:
ButtonPress=0
While MyButton=0
If ButtonPress<255 then ButtonPress=ButtonPress+1
Pause 50 ' This is also our Debounce value
If ButtonPress=>LongPress then LCDOut $FE,$0F
Wend
If ButtonPress>0 then
If ButtonPress=>LongPress then
ButtonPress=2
else
ButtonPress=1
endif
endif
Return
'
' Subroutine Loads TMR1 values
' ============================
SetTimer:
T1CON.0=0 ' Stop the Clock
TMR1RunOn.Highbyte=TMR1H ' Load the Run-On (Over-Run) value (if any)
TMR1RunOn.Lowbyte=TMR1L
TMR1RunOn=TMR1Preset+TMR1RunOn ' Calculate the New (adjusted) value for TMR1
If TMR1CalAR=0 then ' Calibration ADVANCE (add) or RETARD (subtract)
TMR1RunOn=TMR1RunOn+TMR1Cal
else
TMR1RunOn=TMR1RunOn-TMR1Cal
endif
TMR1H=TMR1RunOn.Highbyte ' Save new values to TMR1
TMR1L=TMR1RunOn.Lowbyte
T1CON.0=1 ' Restart the Clock
PIR1.0=0 ' Reset TMR1's Interupt Flag
Return
'
' Timer Interrupt Handler
' =======================
TickCount:
Gosub SetTimer ' Set the Timer for next 10mS Interrupt
Hundredths=Hundredths+1 ' Increment 10mS Seconds Counter
If Hundredths>99 then
Hundredths=0
Seconds=Seconds+1
' Increment the Seconds
If Seconds>59 then
Seconds=0
Minutes=Minutes+1
' Increment the Minutes
If Minutes>59 then
Minutes=0
Hours=Hours+1
' Increment the Hours
If Hours>23 then Hours=0
endif
endif
endif
Resume
End
Re: Single button function
IF Button = Pressed THEN
WHILE Button = Pressed
LOOP
ENDIF
Re: Single button function
I did it in the different way:
Code:
setuploop:
if but2=0 then
dlycnt=dlycnt+1 'increase debounce variable while button is pressed
ticker=ticker+1
pause 1
endif
if ticker>1500 and BUT2=0 then gasvla 'if long pressed, then exit and (or) go to selector item
if BUT2=1 and dlycnt>100 then 'if short pressed, then do the rap
ticker=0
dlycnt=0
menuitem=menuitem+1 'this is incremental variable, substitute another next time you need it
lcdout $fe,$c0, " selection: " #menuitem," " 'debug just for case
pause 1
endif
goto setuploop
Re: Single button function
I did a setup to check for...... short press, then 2 second or 5 second then long press to enter program mode, for next for the timing, then go on to next check and goto's
Code:
FOR A1= 1 TO 5 '<.1 SECONDS FOR TIMER
PAUSE 3
GOSUB RDSW
if SWCH=0 then start
NEXT A1
HIGH 2
read 1,A4 :PAUSE 10: C1=60*A4:C2=C1
FOR A1 = 1 TO 100 '2 SECONDS FOR 8 HR
PAUSE 8
GOSUB RDSW
if SWCH=0 then TIMER
NEXT A1
C1=28800 '8 HRS
HIGH 5
FOR A1 = 1 TO 100 'CHECK FOR PROGRAM 5 SEC TOTAL
PAUSE 40
GOSUB RDSW
if SWCH=0 then TIMER
NEXT A1
LOW 2:GOTO PROGRAM