View previous topic :: View next topic |
Author |
Message |
brianm
Joined: 08 Mar 2008 Posts: 17
|
interrupts for button(s) |
Posted: Tue Feb 02, 2010 1:18 pm |
|
|
Up until now I have been using polling for buttons....now like everything else I am moving onward to 'trying' to use interrupts.
I have a small program written that works....BUT if you hold the button too long it registers more than one increment to the count.
Here is my code less the LCD routines...the write rountine for the lcd is very basic and writes the count out
This code works but I feel my logic is wrong or should I say I don't understand interrupts fully.
Now when I get this working I will want to add a second button on pin_a1 to reset the count to zero.
Thanks for all the help.
Code: |
// version 1.0
//
#include <16F690.h>
#device adc=10
#fuses INTRC_IO, NOWDT, BROWNOUT, PUT , NOMCLR
#use delay(clock=4000000)
//-------------------------------------------------------------
// pin a0 - adc1
// pin a1 - button 2
// pin a2 - button 1
// pin a3 - NC
// pin a4 - lcd e
// pin a5 - lcd rw
// pin b4 - adc 4
// pin b5 - rs232 rx
// pin b6 - lcd rs
// pin b7 - rs232 tx
// pin c0 - lcd
// pin c1 - lcd
// pin c2 - lcd
// pin c3 - lcd
// pin c4 - lcd
// pin c5 - lcd
// pin c6 - lcd
// pin c7 - lcd
//-------------------------------------------------------------
#include <MATH.H>
#include <stdlib.h>
#define e pin_a4
#define rw pin_a5
#define rs pin_b6
int b;
int p;
int count;
int amount;
char const text1[] = {"bucket count"};
char const text2[] = {" "};
char const text3[] = {" "};
char const text4[] = {" "};
int i;
int j;
int k;
int y=0;
int z;
char char_count[4];
//
//the lcd functions go here
//
#INT_RA
void RA2_ISR(void)
{
y=1;
disable_interrupts(INT_RA2);
delay_ms(500);
count=count+1;
enable_interrupts(INT_RA2);
}
//------------------------------------------------------------
// MAIN
//------------------------------------------------------------
void main() {
set_tris_a(0b00000111);
set_tris_b(0b00001111); // 1 is input 0 is output
set_tris_c(0b00000000);
enable_interrupts(global);
enable_interrupts(INT_RA2);
init();
count = 0;
while (1){
z = sprintf(char_count,"%d",count);
home();
for (i=0;i<12;i++){
write(text1[i]);
}
j = strlen(char_count)-1;
for (k=0;k<=j;k++){
write(char_count[k]);
}
write(" ");
command(0xd0);
for (i=0;i<12;i++){
write(text2[i]);
}
j = strlen(char_count)-1;
for (k=0;k<=j;k++){
write(char_count[k]);
}
write(" ");
}
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Feb 02, 2010 1:45 pm |
|
|
Quote: |
#INT_RA
void RA2_ISR(void)
{
y=1;
disable_interrupts(INT_RA2);
delay_ms(500);
count=count+1;
enable_interrupts(INT_RA2);
}
|
The 16F690 says you must do these two things to clear the interrupt
condition:
Quote: |
4.4.2 INTERRUPT-ON-CHANGE
The user, in the Interrupt Service Routine, clears the interrupt by:
a) Any read or write of PORTA. This will end the mismatch
condition, then,
b) Clear the flag bit RABIF.
|
The compiler does item (b). You must put code in the isr to do item (a).
Example:
Code: |
void RA2_ISR(void)
{
int8 temp;
temp = input(PIN_A2); // Read pin to clear "mismatch" condition
.
.
.
}
|
You don't need to disable and re-enable interrupts inside the isr.
The reason is because there are no nested interrupts.
Also, I doubt that you need the 500 ms delay. I didn't look closely
at the rest of your program, though. |
|
|
brianm
Joined: 08 Mar 2008 Posts: 17
|
Still not getting desired results |
Posted: Wed Feb 17, 2010 2:48 pm |
|
|
I have added the read port a to clear the mismatch but I am still having trouble with slow button pushes
I have included the complete code which displays the results on an LCD...newhaven
I have this all set up on a breadboard and have an actual tipping bucket gauge here....but I have been using a push button to simulate the switch as I see a need to solve/undertand this for other applications.
A few days delay in my work as I sinus surgery....now my turn to do surgery!!!
Thanks
Code: |
// version 1.0
//
#include <16F690.h>
#device adc=10
#fuses INTRC_IO, NOWDT, BROWNOUT, PUT , NOMCLR
#use delay(clock=4000000)
//-------------------------------------------------------------
// pin a0 - NC
// pin a1 - reset switch
// pin a2 - tipping bucket switch
// pin a3 - NC
// pin a4 - lcd e
// pin a5 - lcd rw
// pin b4 - NC
// pin b5 - rs232 rx
// pin b6 - lcd rs
// pin b7 - rs232 tx
// pin c0 - lcd
// pin c1 - lcd
// pin c2 - lcd
// pin c3 - lcd
// pin c4 - lcd
// pin c5 - lcd
// pin c6 - lcd
// pin c7 - lcd
//-------------------------------------------------------------
#include <MATH.H>
#include <stdlib.h>
#define e pin_a4
#define rw pin_a5
#define rs pin_b6
char const text1[] = {"bucket count"};
char const text2[] = {" "};
char const text3[] = {" "};
char const text4[] = {" "};
char char_count[4];
int b;
int p;
int count;
int amount;
int i;
int j;
int k;
int y=0;
int z;
int temp;
//FUNCTIONS AND LABELS
void light_led(void);
void PORTA_ISR(void);
//DEFINES
#byte PORTA = 5
#byte PORTB = 6 //PIC b portb (6) replaced by string PORTB
//VARIABLES and CONSTANTS
int1 button;
static int prior_porta_state;
//------------------------------------------------------
// COMMAND SECTION for lcd newhaven 4 by 16
//--------------------------------------------------------
void command(char i){
output_c(i); // SET DATA PINS
delay_ms(50);
output_low(rw); // Rw LOW
output_low(rs) ; // Rs LOW
output_high(e) ; // ENABLE HIGH
Delay_ms(5);
output_low(e) ;
delay_ms(10);
output_c(0);
}
//------------------------------------------------------
// WRITE SECTION for lcd newhaven 4 by 16
//--------------------------------------------------------
void write(char i){
output_c(i); // SET DATA PINS
delay_ms(10);
output_high(rs); // RS HIGH
delay_us(10);
output_low(rw); // RW LOW
delay_us(10);
output_high(e); // ENABLE HIGH
Delay_ms(10);
Delay_ms(1);
output_low(e); // ENABLE LOW
output_low(rs); // Rs LOW
output_c(0); // set data pins low
}
//------------------------------------------------------
// Initialization section for lcd newhaven 4 by 16
//--------------------------------------------------------
void init(){
output_low(e);
command(0b00111100); //37 function set
Delay_ms(10);
command(0b00001100); //e display on / cursor off / blink on
Delay_ms(10);
command(0b00000001); //1 display clear
Delay_ms(10);
command(0b00000110); //6 entry mode set
Delay_ms(10);
}
//-----------------------------------------------------------
// CLEAR AND HOME for lcd newhaven 4 by 16
//-----------------------------------------------------------
void home(){
command(0x02);
Delay_ms(5);
}
//-----------------------------------------------------
//CODE turn on led routine
//-------------------------------------------------------
void light_led(void)
{
//disable_interrupts(INT_RA2);
//PORTB = 0x00;
output_low(pin_b4);
count= count+1;
//delay_ms(500);
output_high(pin_b4);
//PORTB=0xff;
PORTA = prior_porta_state;
//enable_interrupts(INT_RA2);
}
//-----------------------------------------------------
//CODE interrupt routine
//-------------------------------------------------------
#INT_RA
void PORTA_ISR(void)
{
disable_interrupts(INT_RA2);
temp = input(PIN_A2); // Read pin to clear "mismatch" condition
if (prior_porta_state != PORTA)
{
prior_porta_state = PORTA;
button = TRUE;
}
delay_ms(800);
enable_interrupts(INT_RA2);
}
//------------------------------------------------------------
// MAIN
//------------------------------------------------------------
void main() {
set_tris_a(0b00000111);
set_tris_b(0b00000000); // 1 is input 0 is output
set_tris_c(0b00000000);
// initilize the lcd
init();
// write a welcome power up message
home();
for (i=0;i<12;i++){
write(text1[i]);
}
// now set the count to 0 and set up the ports for starting points
count = 0;
PORTA=0;
button = FALSE;
PORTB=0xff;
//prior_porta_state=PORTA;
ext_int_edge(H_TO_L);
enable_interrupts(INT_RA2);
enable_interrupts(GLOBAL);
prior_porta_state=PORTA;
while(1) //hangs here until an interrrupt then returns?
{
if(button==TRUE)
{
button = FALSE;
light_led();
}
//----------------------------
//write the count to the lcd
//----------------------------
z = sprintf(char_count,"%d",count);
home();
for (i=0;i<12;i++){
write(text1[i]);
}
j = strlen(char_count)-1;
for (k=0;k<=j;k++){
write(char_count[k]);
} //for loop K
write(" ");
} //while loop
} //main loop
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Feb 17, 2010 2:56 pm |
|
|
Rather than work on your code, I'll just give you a link to a thread that
polls the buttons at a 10 ms interval in a timer isr. It puts the button
presses into a buffer, which you can then read:
http://www.ccsinfo.com/forum/viewtopic.php?t=39585 |
|
|
brianm
Joined: 08 Mar 2008 Posts: 17
|
compile error |
Posted: Wed Mar 03, 2010 9:01 pm |
|
|
I copied the files suggested and made a few changes to match my PIC and tried the compile but got this
It is looking for a device statement...I need help.
It fails at this line in Button.c
Code: |
// The following macro is used by the Button function.
#define read_bit_var(x) bit_test(*(int8 *)(x >> 3), x & 7)
|
Thanks
Clean: Deleting intermediary and output files.
Clean Warning: File "M:\microchip\interupts by time in c\interrupts inc by time.o" doesn't exist.
Clean Warning: File "M:\microchip\interupts by time in c\button.o" doesn't exist.
Clean: Deleted file "interrupts inc by time.HEX".
Clean: Deleted file "interrupts inc by time.LST".
Clean: Deleted file "interrupts inc by time.PJT".
Clean: Deleted file "interrupts inc by time.ERR".
Clean: Deleted file "interrupts inc by time.COF".
Clean: Deleted file "button.ERR".
Clean: Done.
Executing: "C:\Program Files (x86)\PICC\Ccsc.exe" +FM "interrupts inc by time.c" +EXPORT +DF +LN +T +A +M +Z +Y=9 +EA
>>> Warning 203 "interrupts inc by time.c" Line 101(1,1): Condition always TRUE
>>> Warning 202 "interrupts inc by time.c" Line 4(5,8): Variable never used: rs232_errors
Memory usage: ROM=11% RAM=15% - 20%
0 Errors, 2 Warnings.
Executing: "C:\Program Files (x86)\PICC\Ccsc.exe" +FM "button.c" +EXPORT +DF +LN +T +A +M +Z +Y=9 +EA
*** Error 128 "button.c" Line 103(1,41): A #DEVICE required before this line
1 Errors, 0 Warnings.
Halting build on first failure as requested.
BUILD FAILED: Wed Mar 03 20:48:44 2010
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Mar 04, 2010 11:45 am |
|
|
That line is not the problem. Here's the error message:
Quote: | *** Error 128 "button.c" Line 103(1,41): A #DEVICE required before this line |
Are you using MPLAB as the IDE ?
If so, you will get that error if you added the "button.c" file to the
Source Files list in the MPLAB Project window. The solution is delete
that file from the Project window. Just #include the button.c file in
your main source file. The only file that should be in the Project
window list is the main source file for your program. |
|
|
AL_PL Guest
|
Re: compile error |
Posted: Sun Mar 07, 2010 11:09 am |
|
|
Did you remove the enable and disable interrupt function-calls an the delay in the ISR? I have the feeling that every 500ms you generate another interrupt and therefor an increase of the counter if you keep the key pressed. Also just for being sure you might include a polling function for your port to see if there is any bouncing of the signal (=level on the pin). If so you must add a debouncing routine. |
|
|
|