Hi, welcome.Hi guys,
I am a newbie to the forum and I hope that someone can help me keep what hair I have remaining.
So then the data is on the pins of the decoder? How do you read them? Do you try to read them in your interrupt? Or do you set a flag in the interrupt and act on that in your main loop?I am trying to code a project with a Pic 16f877A that has a telephone style keypad with a dedicated keypad decoder chip for debouncing that provides a data valid signal for the interrupt function, an HD44780 based LCD module, and 40 relays for output.
Yes, timing loops are blocking... polling doesn't have to be. LCDs are slow...The display shows a welcoming message until you press a key on the keypad, at which time it shows a different display with spaces prompting for more keys ( numbers ) to be entered. After the 3rd key is pressed, the code checks for validity and activates the appropriate relay for a set time duration.
I am using the PORTB,0 interrupt feature to detect keypresses.
I have been able to code each of the routines for the different functions successfully, but when I try to combine the code snippets, I run into problems with the system not responding to keypresses and/or the display showing garbage.
I am pretty sure that the multiple timing loops needed for the display are causing the processor to be tied up for too long in some cases which is causing it to miss keypresses and other events.
I am going to want to activate the watchdog timer function for the finished device, as well, which means that I may need the pre-scaler for it.
My thought is to use Timer 1 or 2 to handle the timing for the display functions and eliminate, or at least reduce the number of delay loops in the code. I expect that I would have to change the timer settings on the fly, depending what times I needed for the various functions and poll the overflow bit(s).
Does this sound like the best way to go?
Will there be a problem with using either or both of these timers for the delays?
How will the keypad interrupt affect the timer(s) as I am polling them?
Sorry for the long post.
Any help would be greatly appreciated.
Cheers,
Soundguy
and
I am using the PORTB,0 interrupt feature to detect keypresses.
Hi Eric,
guess you were posting while I was typing...
He is...
hi BeeBop,
I thought no one else was going to answer.
Your post is far more useful than mine, I was trying to get a little more detail.
[I'll shut up!]
I saw the ref to one Intr but he didnt mention others.
I'd be more inclined to manually poll something as simple as the keypad, freeing up interrupt driven overheads for other tasks.
A code snippet would help out, other things might be at play such as context saving not incorporated?
So when you read the first key, do you disable interrupts while reading the other key presses? What I'm thinking is that while you are processing the first key an interrupt occurs...The idea was for the interrupt to clear the display and show a new message with spaces for the entered keypad digits to display with a blinking cursor as a prompt. As I mentioned before, this routine does work, including the response to the interrupt for the first digit. When the second digit is entered, then the problems surface.
but am wondering if you disable interrupts while collecting these.Once the keypad is decoded, the BCD number for each digit is stored in a seperate register according to whether the digit is the 1st, 2nd, or 3rd entry.
5 milliseconds is a long time for the micro, but not for us. I think most debounce routines are between 10 and 20 mSec.... and I don't think it is your display which is causing the problem (but I could be wrong,) or the way you are storing the strings in program memory.The delays used for housekeeping for the display are of 1-5 milliseconds in duration depending on what is being done at that time.(Sending commands or characters.)
Outputs are in 3-STATE until key is pressed, then data is placed on bus. When key is released, outputs return to 3-STATE.
on the screen. OK, I'm there, but what about the prompt? I would think the blinking cursor would be prompt enough, or am I missing something? The visitors must somehow know they have to enter three digits, no?routine that changes the displayed message and prompts for keypad input.What I have done in the code is to put the decoded digits into the display as they are received nad before the 2nd digit is multiplied. The display is set for cursor advancement, so I only need to set the location for the 1st digit. The cursor advances to the 2nd and 3rd locations by itself.
Hi again, MR. RB
Just to make sure that I understand, are you suggesting that I use timer0 for a system tick, for general use, and timer 1 for special items such as the 5 second countdown?
In response to your question about multiplying the 2nd digit, the idea was to add up the numbers created by the keypad decoding and end up with a number that would translate directly to the relay number that I want to activate. I originally wrote some code that simply incremented a register form 0-40, and output the appropriate code to work with the 5 X 8 matrix arrangement for the relays and output indicating LED's as a test.
When I first started designing this project, I built a circuit board with 40 LED's arranged in a 5 X 8 matrix in order to control all of them with a single port, including a seperate enable line, which is used to turn the selected output on for whatever length of time you want, as well as intoducing a cadence to the output, if needed, such as duplicating a telephone ring signal, be it either North American or European style ring cycles. This is the method I have used in the prtototype for controlling the relays.
Lastly, the message displayed in the LCD after the 1st keypress is really just a screen full of asterisks with a space in the middle of the bottom line where the entered digits go. This is based on a display used by a prominent manufacturer of similar type "user friendly" entry panels that I have seen.
After the 3 keypad digits have been entered, the display just shows "CALLING" whilst the relay is activated.That is the last message displayed in the whole sequence of events. After that, the system resets and reverts to the welcoming message.
sample
movf PORTB,W ; |B0
andlw b'00011111' ; mask off unused bits |B0
xorwf swlatch,W ; changes? |B0
bz GetLp ; no, branch, else |B0
xorwf swlatch,F ; update switch state latch |B0
btfss swlatch,4 ; new release? no, skip, else |B0
goto sample ; branch, try again |B0
call beep ; send new press beep |B0
movf swlatch,W ; get data again |B0
andlw 0x0F ; mask off unused bits |B0
addwf PCL,F ; return key value |B0
dt "0123456789ABCDEF"
;
; get key with 5 second time-out
;
GetKey
movlw 5 ; timeout = 5.000 seconds |B0
movwf secs ; |B0
clrf msecslo ; |B0
clrf msecshi ; |B0
GetLp DelayCy(1*msecs-23) ; sample at 1 msec intervals |B0
movlw d'99' ; reset value for 'msecslo' |B0
decf msecslo,F ; dec msecs lo |B0
btfsc msecslo,7 ; negative? no, skip, else |B0
decf msecshi,F ; dec msecs hi |B0
btfsc msecslo,7 ; negative? no, skip, else |B0
movwf msecslo ; reset msecslo = 100 |B0
movlw d'9' ; reset value for 'msecshi' |B0
btfsc msecshi,7 ; negative? no, skip, else |B0
decf secs,F ; dec seconds counter |B0
btfsc msecshi,7 ; negative? no, skip, else |B0
movwf msecshi ; reset msecshi = 10 |B0
setc ; preset timeout indicator |B0
movf secs,W ; |B0
iorwf msecslo,W ; |B0
iorwf msecshi,W ; timer timed out? |B0
skpnz ; no, skip, else |B0
return ; return W = 0 and C = 1 |B0
movf PORTB,W ; |B0
andlw b'00011111' ; mask off unused bits |B0
xorwf swlatch,W ; changes? |B0
bz GetLp ; no, branch, else |B0
xorwf swlatch,F ; update switch state latch |B0
btfss swlatch,4 ; new press? yes, skip, else |B0
goto GetLp ; branch, ignore 'new release' |B0
call beep ; send new press beep |B0
movf swlatch,W ; get data again |B0
andlw 0x0F ; mask off unused bits |B0
addwf PCL,F ; return W = key and C = 0 |B0
dt "0123456789ABCDEF"
;
; beep
;
beep
bsf beepctr,4 ; task 32 msec "beep" |B0
toggle movf PORTA,W ; |B0
xorlw 1<<spkr ; toggle spkr bit |B0
movwf PORTA ; toggle spkr pin |B0
DelayCy(1*msecs-6) ; interval for 500 Hz tone |B0
decfsz beepctr,F ; done? yes, skip, else |B0
goto toggle ; toggle spkr again |B0
return ; |B0
;
Loop
PutLCD (cmd,clearscreen); |B0
PutSTR "Welcome"
PutLCD (cmd,line2+0) ; line 2, htab 0 |B0
PutSTR "Resident code? "
Digit1 call GetKey ; get key (5 second timeout) |B0
bc Digit1 ; branch if timeout |B0
xorlw '0' ; is it '0'? |B0
bnz Digit1 ; no, branch, else |B0
movlw '0' ; |B0
call PutDat ; print the '0' |B0
Digit2 call GetKey ; get key (5 second timeout) |B0
bc Loop ; branch if timeout |B0
movwf tens ; save key, '0'..'9' |B0
sublw '3' ; '0'..'3' range? |B0
bnc Digit2 ; no, branch, else |B0
movf tens,W ; |B0
call PutDat ; print to LCD |B0
Digit3 call GetKey ; get key (5 second timeout) |B0
bc Loop ; branch if timeout |B0
.......
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?