| ||
PIC Tutorial - A Clever Button
This is one of my favorite subroutine! When i design a project, i always try to make the user interface minimal. For this, you need to have to buttons doing more than just one click. This tutorial will demonstrate how to distinguish three different button states. Then, according to how the button was pressed, a different routine shall be executed. The three states are:
The mSec times given are fully parametric and can be changed at will. This is important because it it different if the button is mechanical, different if it is a touch button, different for menu systems and different for critical applications such as light control. In Action The Circuit The circuit has one button and three LEDs:
Each LED is lit from another subroutine. The RED LED will light on a single click, the GREEN on a long press and the yellow on a double click. The Code The code is a little bit complicated, as many parameters needs to be taken into account during a click. Also, some extra delays are added for avoiding false triggers (debounce technique). ; RAM preserved ----------------------------------------------------------- cblock 0x20 WaitCounter,WaitCounter2 IntervalCounter endc ; Conastants -------------------------------------------------------------- GLDoubleClick_Interval = d'15' ;mSec x 10 GLDoubleClick_MaxDelay = d'30' ;mSec x 10 GLLongClick_Interval = d'80' ;mSec x 10 ; Main Program ------------------------------------------------------------ Start bank1 ;Go to bank 1 movlw b'11111111' ; movwf TRISA ;Set the port pin types of the RA movlw b'11111000' ; movwf TRISB ;Set the port pin types of the RB bank0 ;Go to bank 0 bcf ClickOutput bcf DblClickOutput bcf LngClickOutput MainLoop btfss ButtonInput goto MainLoop movlw GLLongClick_Interval movwf IntervalCounter CheckForLongClick call Wait10mSec btfss ButtonInput ;Check if it is a long click goto NoLongClick decfsz IntervalCounter,f goto CheckForLongClick ;It WAS a long click goto Run_Long_Click NoLongClick ;It was NOT a long click movf IntervalCounter,w sublw GLLongClick_Interval ;Check How many mSeconds was the first keypress sublw GLDoubleClick_MaxDelay ;Was it MORE thant the max dbl initial click? btfss Carry ;If the result is negative goto Run_Single_Click ;Then it was a single click. ;Else, we will wait more to see if it will be a dbl click movlw GLDoubleClick_Interval movwf IntervalCounter CheckForDblgClick call Wait10mSec btfsc ButtonInput goto It_Is_A_Dbl_Click decfsz IntervalCounter,f goto CheckForDblgClick ;It WAS a Single click goto Run_Single_Click It_Is_A_Dbl_Click call Wait2mSec btfsc ButtonInput goto It_Is_A_Dbl_Click ;Wait untill the button is released goto Run_Dbl_Click Run_Single_Click bsf ClickOutput call Wait1Sec bcf ClickOutput goto WaitForKeyReleaseBeforeReturn Run_Dbl_Click bsf DblClickOutput call Wait1Sec bcf DblClickOutput goto WaitForKeyReleaseBeforeReturn Run_Long_Click bsf LngClickOutput call Wait1Sec bcf LngClickOutput ; goto WaitForKeyReleaseBeforeReturn ;This instrruction is not really nesecary here! WaitForKeyReleaseBeforeReturn call Wait4mSec btfsc ButtonInput goto WaitForKeyReleaseBeforeReturn call Wait10mSec goto MainLoop We start by defining the pin types. Right after, we clear the three outputs so that the LEDs are turned off. The MainLoop this time is... 2 instructions long! It checks if the button is pressed. If not, it loops back to MainLoop. If it is, it will continue with the click type check. Trying to describe this subroutine with words would complicate the things even further. Therefore, i have add the following flow chart that describes only this subroutine: You can download it also as pdf:
So, after this subroutine, one of the three click-subroutines shall run. It will be either a single, a double or a long click. According to the subroutine call, the corresponding LED shall lit. Also, the LED shall remain ON for one second and then it will turn off again. Then, the program flow shall return back to MainLoop. But before this is done, we need to ensure that the button is not still pressed (for example after a double click that the second click could be still active). Therefore, i have add another small subroutine that is called after every click/dbl click/lng click subroutine execution. This subroutine will check every 4mSec the state of the button. If the button is not pressed, then it will wait another 10mSec (for debouncing) and it will go back to MainLoop. The project Files Following are the files for this project:
Comments
No part of this publication may be reproduced, stored in a retrieval system or transmitted in any form or by any means, electronic, mechanical, photocopying, recording, scanning or otherwise without the prior written permission of the author. Read the Disclaimer
All trademarks used are properties of their respective owners.
Copyright © 2007-2009 Lazaridis Giorgos. All rights reserved. |
![]() ![]() ![]()
|
Home
Contact
Forum
Projects
Experiments
Circuits
Theory
BLOG
PIC Tutorials
Tech-News
RSS
Site design: Giorgos Lazaridis © Copyright 2008 Please read the Terms of services and the Privacy policy |