RRITESH KAKKAR
- Joined Jun 29, 2010
- 2,829
I can do this with pic16f887 or 72
PWM hardware
if you want code take from me.
PWM hardware
if you want code take from me.
Post #8 is a method you can do your button press. Just poll in a loop for one second. It is really the number of instructions that equate to a second. This is what time delays do. They simply execute instructions in a loop.Come again.
They also consume 100% of the CPU time, eventually eating your sack lunch. A better way is to use an interrupt-driven timer chain which we can get to pretty easily. Burning 1E6 Tcyc of processing to look at a switch is maybe not the best way to go.Post #8 is a method you can do your button press. Just poll in a loop for one second. It is really the number of instructions that equate to a second. This is what time delays do. They simply execute instructions in a loop.
True enough but that means recalculating the loop each time the other code changes. Branches and other input-determined things can make that a formidable task. I've been there.Other code could be executed in the loop. There is nothing that says code has to be blocked while detecting the switch press.
;*****************************************
;** GETKEY -- Process keys every 8 ms **
;** by JoeyD999 posted 11/3/15 **
;*****************************************
getkey retbc TC8ms ;process kbd row every 8 ms (total 32 ms debounce time)
;shift debounce table
lfsr 0,kbddb+2 ;point to bottom of keyboard debounce table
movff postdec0,kbddb+3 ;shift entries
movff postdec0,kbddb+2
movff indf0,kbddb+1
;fsr0 -> top of debounce table
gktop comf portb,w ;get new keypad pattern
andlw keymsk ;mask actual keys
movwf indf0 ;and save new entry
;now, test buffer pattern -- all 1s = pressed/all 0s=released/mixed no action
movf postinc0,w ;get all the 1's
andwf postinc0,w
andwf postinc0,w
andwf indf0,w ;w has all keys held for 4 passes
iorwf keyhld,f ;set them in keyhld
movf postdec0,w ;get all the 0's
iorwf postdec0,w
iorwf postdec0,w
iorwf indf0,w ;w has all keys released for 4 passes
andwf keyhld,f ;clear them in keyhld
movfw keyhld ;get current pattern
xorwf keylst,w ;compare to last full scan
andwf keyhld,w ;keep only those pressed since last
movwf keychg ;flag new key presses this scan
movff keyhld,keylst ;save new pattern as last
return
#define WhiteMask 0x01
#define OFFmask (~0x01)
#define PWMbaseK 255
#define Whitepct 50
unsigned char PWMbase;
unsigned char WhiteDUTY;
unsigned char OutMask;
void outPWM()
{
OutMask &= OFFmask;
if(WhiteDuty){
WhiteDuty--;
OutMask |= WhiteMask;
}
GPIO = OutMask;
}
void main()
{
CMCON = 0x07; //Comparator off
OPTION_REG = 0x97;
// b'1001011'
//GPPU = 1 --> Pull ups disabled
//INTEDG = 0 --> Interrupt on Falling edge of GP2
//TOCS = 0 --> Internal Inst Cyc clock
//TOSE = 1 --> TMRO Increment on Hi to lo
//PSA = 0 --> Prescaler to TMRO 0
//PS2:PSO = 1--> 1:256 Prescaler Rate
TRISIO = 0x3C; //GPO & GP1 AS Out rest In
GPIO = 0; //Clear Outputs
OutMask = 0; //Clear OutMask
PWMbase = PWMbaseK; // Load PWMbase with PWMbaseK value
while(1)
{
if(PWMbase)
{
PWMbase--;
outPWM();
}
else
PWMbase = PWMbaseK;
WhiteDuty = (Whitepct * PWMbaseK)/100;
}
}
Interesting method, if not a bit clumsy. Wouldn't it be simpler/smaller/faster to use cumulative 'change' bits to toggle the debounced state latch?Since hardly anyone ever posts good debounce code, I'm going to post mine here.
;
; 8-ms sample intervals (24 to 32 millisecond debounce time)
;
sample
movf kbddb+2,W ; shift 'delta' accumulator
movwf kbddb+3 ;
movf kbddb+1,W ;
movwf kbddb+2 ;
movf kbddb+0,W ;
movwf kbddb+1 ;
comf GPIO,W ; sample active lo switches
andlw b'00000011' ; on the GP1..GP0 pins only
xorwf keylst,W ; changes, press or release
movwf kbddb+0 ; get cumulative delta bits
andwf kbddb+1,W ; "
andwf kbddb+2,W ; "
andwf kbddb+3,W ; "
xorwf keylst,F ; update switch state latch
andwf keylst,W ; filter out 'release' bits
movwf keychg ; set "new press" flag bits
;
; 8-ms sample intervals (24 to 32 millisecond debounce time)
;
sample
comf GPIO,W ; sample active lo switches
andlw b'00111000' ; on the GP5..GP3 pins only
xorwf latch,W ; changes, press or release
movwf vmask ; save temporarily
;
; reset inactive vertical counters
;
andwf vcnt0,F ; reset inactive counters
andwf vcnt1,F ; "
;
; increment vertical counters
;
comf vcnt0,F ; inc vertical counters
movf vcnt0,W ; "
xorwf vcnt1,F ; "
;
; debounced state logic (4 samples at same state in 24-msec span)
;
movf vmask,W ; changes, press or release
andwf vcnt0,W ; check for overflow
andwf vcnt1,W ; "
xorwf latch,F ; update switch state latch
andwf latch,W ; filter out 'release' bits
movwf flags ; set "new press" flag bits
In fact, what was really clumsy was that, in my haste to extract the useful parts of my code, I neglected to include the code that clears 'keychg' register upon entry to the routine, prior to the 'tc8ms' test. Without it, the 'keychg' register is persistent through each main loop -- resulting in a mess. The 'keychg' should hold only new keys pressed for a single main loop pass. Here is the corrected code:Interesting method, if not a bit clumsy.
;*****************************************
;** GETKEY -- Process keys every 8 ms **
;** by JoeyD999 posted 11/4/15 **
;*****************************************
getkey clrf keychg ;clear new keypresses for each main loop pass
retbc TC8ms ;process kbd row every 8 ms (total 32 ms debounce time)
;shift debounce table
lfsr 0,kbddb+2 ;point to bottom of keyboard debounce table
movff postdec0,kbddb+3 ;shift entries
movff postdec0,kbddb+2
movff indf0,kbddb+1
;fsr0 -> top of debounce table
gktop comf portb,w ;get new keypad pattern
andlw keymsk ;mask actual keys
movwf indf0 ;and save new entry
;now, test buffer pattern -- all 1s = pressed/all 0s=released/mixed no action
movf postinc0,w ;get all the 1's
andwf postinc0,w
andwf postinc0,w
andwf indf0,w ;w has all keys held for 4 passes
iorwf keyhld,f ;set them in keyhld
movf postdec0,w ;get all the 0's
iorwf postdec0,w
iorwf postdec0,w
iorwf indf0,w ;w has all keys released for 4 passes
andwf keyhld,f ;clear them in keyhld
movfw keyhld ;get current pattern
xorwf keylst,w ;compare to last full scan
andwf keyhld,w ;keep only those pressed since last
movwf keychg ;flag new key presses this scan
movff keyhld,keylst ;save new pattern as last
return
But your code is not equivalent. Your history is lost the instant a '1' on the port is detected (button presumably released). In 99% of cases, this is ok and correct -- and the way I used to write debounce code years ago.Wouldn't it be simpler/smaller/faster to toggle cumulative 'change' bits into the debounced state latch? ...consider an equivalent...
Debouncing both ways also accommodates the variety of switches, sensors etc. found in harsh industrial environments. Even solidly closed switches can give flaky outputs due to vibration/bumps etc. I always debounce both ways after going through many alternatives approaches over the years.Note that my code requires both a 32ms press to activate and a 32 ms release to deactivate. Any chatter is eaten by the debounce table. This works 100% of the time, even with aged, cheap keypads and dirty switches. It is well worth the extra code and registers.
No problem. Well written code breaks functions down into individual modules with clearly defined functions. Once the PWM is written, it will accept Increase / Decrease commands. Buttons or encoder will be a module that just generate the increase/decrease commands without any mods necessary to the PWM code.@JohnInTX
Ummm..you are forgetting that I like to vary the PWM using a rotary encoder.
What are you talking about? Your 'keychg' variable isn't persistent. You overwrite it each time through the routine.In fact, what was really clumsy was that, in my haste to extract the useful parts of my code, I neglected to include the code that clears 'keychg' register upon entry to the routine, prior to the 'tc8ms' test. Without it, the 'keychg' register is persistent through each main loop -- resulting in a mess. The 'keychg' should hold only new keys pressed for a single main loop pass.
Nonsense!But your code is not equivalent. Your history is lost the instant a '1' on the port is detected (button presumably released). In 99% of cases, this is ok and correct -- and the way I used to write debounce code years ago.
Actually, four samples at the same state at 8-msec intervals is a span of 24-msecs so your code requires a minimum steady 'press' or 'release' state of between 24 and 32 msecs. BTW, my code also debounces both the 'press' and 'release' states.But those clumsy Chinese have a habit of manufacturing cheap keypads that are not as reliable as the expensive American types. A weak press can (and has, in my experience) cause a string of make/breaks resulting in erratic operation. Note that my code requires both a 32ms press to activate and a 32 ms release to deactivate. Any chatter is eaten by the debounce table.
My routines work just as well, even when using a pair of bare wires. In this case, if the extra code and registers don't improve performance or add features they're simply unnecessary extra code and registers (grin).This works 100% of the time, even with aged, cheap keypads and dirty switches. It is well worth the extra code and registers.
char swnew = 0; // switch sample var
char swold = 0; // switch state latch
char flags = 0; // switch new press flags
#define norm 0 // flag for "short" press
#define long 1 // flag for "long" press
#define newpress swnew.3 == 1 && swold.3 == 0
#define newrelease swnew.3 == 0 && swold.3 == 1
while(1) //
{ bam(); // do 25-msecs worth of PWM
swold = swnew; // update switch state latch
swnew = ~gpio; // sample active lo switches
if(newpress) // if "new press"
{ swtmr = 1000/25 // start 1-second timer
} //
if(newrelease) // if "new release"
{ if(swtmr) // if not 1-second timeout
{ flags.norm ^= 1; // toggle "short" flag and
swtmr = 0; // clear 1 second timer
} //
} //
if(swtmr) // if timer running
{ swtmr--; // decrement it
if(swtmr == 0) // if timed out
{ flags.long ^= 1; // toggle "long" flag
} //
} //
if(flags.long) // if long new press
{ //
} //
if(flags.norm) // if short new press
{ //
} //
} //
Thread starter | Similar threads | Forum | Replies | Date |
---|---|---|---|---|
A | 12F629 outputs to 0V | Microcontrollers | 27 | |
M | Write 12f629 pickit 2 or pickit 3 | General Electronics Chat | 10 | |
P | PIC 12F629 IR Remote .hex file | General Electronics Chat | 0 | |
I need your help to build 8 LEDs chaser with 12f629 please. | General Electronics Chat | 7 | ||
O | Old guy needs help with 12F629 program | Microcontrollers | 24 |