CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

interrupts for button(s)

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
brianm



Joined: 08 Mar 2008
Posts: 17

View user's profile Send private message

interrupts for button(s)
PostPosted: Tue Feb 02, 2010 1:18 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Feb 02, 2010 1:45 pm     Reply with quote

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

View user's profile Send private message

Still not getting desired results
PostPosted: Wed Feb 17, 2010 2:48 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Feb 17, 2010 2:56 pm     Reply with quote

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

View user's profile Send private message

compile error
PostPosted: Wed Mar 03, 2010 9:01 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Mar 04, 2010 11:45 am     Reply with quote

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
PostPosted: Sun Mar 07, 2010 11:09 am     Reply with quote

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.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group