View previous topic :: View next topic |
Author |
Message |
Chrill3
Joined: 26 Dec 2014 Posts: 4 Location: Sweden
|
Press button interrupt help |
Posted: Sun Mar 01, 2015 6:32 am |
|
|
Hello everyone
I need some help with interrupts on PIC16F690.
I want to enable interrupts on PORT RA2,
I am running on the PICkit 2 low PIN count board.
here is my code:
Code: |
#include <16F690.h>
/*#include <stdio.h>
#include <stdlib.h>
*/
void init(void);
void run(void);
void button_isr(void);
int main(int argc, char** argv)
{
init();
run();
}
void init()
{
enable_interrupts(INT_EXT);
enable_interrupts(INT_EXT_H2L);
enable_interrupts(INT_RA2);
enable_interrupts(GLOBAL);
set_tris_c(0x00);
set_tris_a(0xff);
}
void run()
{
output_c(0x00);
}
#int_RA
void button_isr()
{
clear_interrupt(INT_RA);
output_c(0xff);
//clear_interrupt(INT_RA);
} |
The ISR never runs when i press the button.
There is some problem with
Code: |
#include <stdio.h>
#include <stdlib.h> |
The compiler doesn't find there files for some reason so I have commented these out.
I am very greatful about any help with this. |
|
![](templates/subSilver/images/spacer.gif) |
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Sun Mar 01, 2015 8:13 am |
|
|
Code: | int main(int argc, char** argv)
{
init();
run();
} |
What do you think happens after your code executes run() ?
In your ISR there's no need to disable interrupts.
Look at some of the CCS examples to see how things are done.
You could try a re-install if the compiler can't find standard files.
Mike |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19381
|
|
Posted: Sun Mar 01, 2015 9:41 am |
|
|
and, also, never ever enable an interrupt without a handler. INT_EXT enabled, no handler for this. Will result in code not working. |
|
![](templates/subSilver/images/spacer.gif) |
Chrill3
Joined: 26 Dec 2014 Posts: 4 Location: Sweden
|
|
Posted: Sun Mar 01, 2015 10:29 am |
|
|
Thanks for the swift reply.
I have now been checking the example code 'ex_butt.c' that i think are similar to my project.
I did also delete
Code: |
enable_interrupts(INT_EXT);
enable_interrupts(INT_EXT_H2L);
|
and made an infinite while loop on the run() function, but it didnt help...
here is an example of the code
Code: |
/*
* File: myTest1.c
* Author: christian
*
* Created on February 22, 2015, 5:44 PM
*/
#include <16F690.h>
/*#include <stdio.h>
#include <stdlib.h>
*/
void init(void);
void run(void);
void button_isr(void);
int main(int argc, char** argv)
{
init();
while(1){
run();
}
}
void init()
{
enable_interrupts(INT_RA);
enable_interrupts(GLOBAL);
set_tris_c(0x00);
set_tris_a(0xff);
}
void run()
{
output_c(0x00);
}
#int_RA
void button_isr()
{ while(1){
output_c(0xff);
}
} |
Best regards |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9177 Location: Greensville,Ontario
|
|
Posted: Sun Mar 01, 2015 11:42 am |
|
|
quick comments...
this...
Quote: | int main(int argc, char** argv) |
isn't the normal main() format
usually it's...
Code: | main() {
//do stuff here
}
|
You should look at some of the CCS supplied examples....
also...
this...
Quote: | #int_RA
void button_isr()
{ while(1){
output_c(0xff);
}
} | will stay in the loop forever !
also...
this...
Quote: | /*#include <stdio.h>
#include <stdlib.h>
*/ |
just delete it all as it's not necessary and 'looks messy'....
and...
Quote: |
set_tris_c(0x00);
set_tris_a(0xff); |
is not needed, as CCS automatically control the I/O pins when in 'standard' mode( the default).
One item...
Have you sucessfully got a '1Hz LED ' program to run ?
Jay |
|
![](templates/subSilver/images/spacer.gif) |
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Sun Mar 01, 2015 12:05 pm |
|
|
As it stands it's difficult to tell whether your code is doing anything or not.
I suggest you make run() flash an LED at say 1Hz, and get the ISR to toggle a different one.
I also prefer to align curly brackets so that the closing one is immediately underneath its opening one (with enclosed code indented).
That way it's easier to tell where a function begins and ends.
So your main becomes:- Code: | main()
{
init();
while(1)
{
run();
}
}
|
Mike |
|
![](templates/subSilver/images/spacer.gif) |
ELCouz
Joined: 18 Jul 2007 Posts: 427 Location: Montreal,Quebec
|
|
Posted: Sun Mar 01, 2015 12:09 pm |
|
|
^^ This...
Minimal code structure look like this:
Code: |
#include <yourdevice.h> here
#FUSES here
#use delay (only when you need them, 99.999% of the time)
void main (void){ //void main means MAIN return nothing and also accept nothing (no parameters) no required per se but it's the correct way to do it in C.
//your do stuff once here (inits and all)
while(true){
//code loop this is where you do your real stuff ;)
}
}
|
This is the minimum required code to make the magic thing happen , enjoy! ![Smile](images/smiles/icon_smile.gif) _________________ Regards,
Laurent
-----------
Here's my first visual theme for the CCS C Compiler. Enjoy! |
|
![](templates/subSilver/images/spacer.gif) |
ELCouz
Joined: 18 Jul 2007 Posts: 427 Location: Montreal,Quebec
|
|
Posted: Sun Mar 01, 2015 12:11 pm |
|
|
Mike Walne wrote: | As it stands it's difficult to tell whether your code is doing anything or not.
I suggest you make run() flash an LED at say 1Hz, and get the ISR to toggle a different one.
I also prefer to align curly brackets so that the closing one is immediately underneath its opening one (with enclosed code indented).
That way it's easier to tell where a function begins and ends.
So your main becomes:- Code: | main()
{
init();
while(1)
{
run();
}
}
|
Mike |
dang you beat me to it few mins before ![Very Happy](images/smiles/icon_biggrin.gif) _________________ Regards,
Laurent
-----------
Here's my first visual theme for the CCS C Compiler. Enjoy! |
|
![](templates/subSilver/images/spacer.gif) |
Chrill3
Joined: 26 Dec 2014 Posts: 4 Location: Sweden
|
|
Posted: Thu Mar 05, 2015 1:23 pm |
|
|
Hello thanks for the help
i have changed the code a little bit
Code: |
#include <16F690.h>
#use delay(clock=4000000)
void init(void);
void run(void);
void button_isr(void);
int main(void)
{
init();
while(1)
{
run();
}
}
void init()
{
set_tris_a(0x04);
enable_interrupts(INT_RA3);
enable_interrupts(GLOBAL);
}
void run()
{
while(1)
{
delay_ms(1000);
/*this is for manually polling port A3, but event I press the push button, the led doesnt flash/*
if(input(PIN_A3))
{
output_c(5);
delay_ms(5000);
}
output_c(0x00);
delay_ms(1000);
output_c(0xff);
}
}
//the ISR never runs, even if I press the pressbutton on RA3???
#INT_RA
void button_isr()
{ while(1)
{
output_c(0x7);
delay_ms(500);
output_c(0x00);
delay_ms(500);
}
}
|
The ISR never runs even I press the push button on RA3, it doesnt work with polling either. I have measured the push button with a multimeter and checked the RA3 port voltage level also, everything seems to be OK.
the int main(){} function is OK regarding to C language conventions.
with best regards
Christian |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19381
|
|
Posted: Thu Mar 05, 2015 2:54 pm |
|
|
int main is not really right, but doesn't matter.
The point is that most programs are run 'inside' another environment (called from another program or OS etc.), so can return a value to this.
When writing for the PIC, you are writing the entire code, so there is nothing for a value to be returned to, and it is pointless to try to return anything.
The same applies for arguments to the function, where a program called from the command line has these to arrive into the C code, but in CCS you don't.
There are a huge number of problems with what you are trying to do.
First, your interrupts will be disabled almost all the time. This is because of using delays both inside and outside the interrupt. A search here will find the limitations of this. Then there is the whole concept of using interrupts to detect a button. Not good. Buttons in the real world, do not go neatly on/off. They 'bounce', making and breaking several times. To use interrupts you need to have hardware debounce circuitry on the signals. Otherwise you are better off scanning the buttons using a timer 'tick' interrupt, and using a counter to verify that the button is genuinely on or off. Then I suspect your hardware may not actually be giving the required signal. How is the button wired?. Then you are setting the line you are trying to use for the button as an output.... You are setting TRIS to 4. 00000100 in binary. Only RA2 is set as an input. |
|
![](templates/subSilver/images/spacer.gif) |
ELCouz
Joined: 18 Jul 2007 Posts: 427 Location: Montreal,Quebec
|
|
Posted: Thu Mar 05, 2015 3:21 pm |
|
|
Chrill3 wrote: | Hello thanks for the help
i have changed the code a little bit
Code: |
#include <16F690.h>
#use delay(clock=4000000)
void init(void);
void run(void);
void button_isr(void);
int main(void)
{
init();
while(1)
{
run();
}
}
void init()
{
set_tris_a(0x04);
enable_interrupts(INT_RA3);
enable_interrupts(GLOBAL);
}
void run()
{
while(1)
{
delay_ms(1000);
/*this is for manually polling port A3, but event I press the push button, the led doesnt flash/*
if(input(PIN_A3))
{
output_c(5);
delay_ms(5000);
}
output_c(0x00);
delay_ms(1000);
output_c(0xff);
}
}
//the ISR never runs, even if I press the pressbutton on RA3???
#INT_RA
void button_isr()
{ while(1)
{
output_c(0x7);
delay_ms(500);
output_c(0x00);
delay_ms(500);
}
}
|
The ISR never runs even I press the push button on RA3, it doesnt work with polling either. I have measured the push button with a multimeter and checked the RA3 port voltage level also, everything seems to be OK.
the int main(){} function is OK regarding to C language conventions.
with best regards
Christian |
Also I don't see any fuses in there...
You need them to properly instruct the 16F690 which type of oscillator to use...
They are other important fuses but they can be skipped...
Don't forget CCS C compiler is not C standard compliant!!
Some functions are proprietary to the CCS Compiler also... _________________ Regards,
Laurent
-----------
Here's my first visual theme for the CCS C Compiler. Enjoy! |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Mar 05, 2015 4:58 pm |
|
|
Here is a demo program which shows how to debounce a push-button
switch by polling it in an interrupt routine which runs every 10 ms.
This program will display a 'P' in a terminal window (ex. TeraTerm)
each time you press the push-button. Example (pressed it 5 times):
Code: |
#include <18F4520.h>
#fuses INTRC_IO, BROWNOUT, PUT, NOWDT
#use delay(clock=4M)
#use rs232(baud=9600, UART1, ERRORS)
// This pushbutton must have a pull-up (4.7K or 10K, etc)
// on the PIC pin, and the other end of the switch must
// go to ground. The idle state will be at Vdd, and the
// "pushed" state of the button will be at ground.
#define BUTTON_PIN PIN_B0
// Example of external circuit for pushbutton
//
// +5v
// |
// <
// > 4.7K
// < ___ Pushbutton switch
// To | _|_|_
// PIC -----------------o o------
// pin |
// --- GND
// -
//
//----------------------------------------------
// The Timer0 preload value calculated below will
// will give a Timer0 interrupt rate of 100 Hz.
// This is intended for a PIC oscillator of 4 to 20 MHz.
// The code below saves you from having to manually
// calculate the Timer0 preload value. It's done for you.
#define FOSC getenv("CLOCK") // Get PIC oscillator frequency
#if(FOSC < 21000000)
#define TIMER0_PRELOAD (256 - (FOSC/4/256/100))
#else
#error Oscillator frequency is too high: FOSC
#endif
//----------------------------------------------
// Setup Timer0 to provide a 10ms tick for the pushbutton
// debounce interrupt.
void timer0_init(void)
{
setup_timer_0(T0_INTERNAL | T0_DIV_256 | T0_8_BIT);
set_timer0(TIMER0_PRELOAD);
clear_interrupt(INT_TIMER0);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
}
//------------------------------
// This global value is how the debounce interrupt
// routine communicates with the code in main()
// to inform it if the button has been pushed.
int8 button_pressed = FALSE;
//------------------------------
// The button pin is polled every 10ms in this interrupt
// routine. This assumes the "bounce" period for the
// button is less than 10 ms. Usually this will be the
// case, except for very cheap, sloppy switches.
#int_timer0
void timer0_isr(void)
{
int8 current_value;
static int8 previous_value = 1; // Idle state of button is a logic high
set_rtcc(TIMER0_PRELOAD); // Reload Timer0 for 10ms rate
current_value = input(BUTTON_PIN); // Read the button
// Look for a falling edge, which indicates the
// button has been pushed.
if((previous_value == 1) && (current_value == 0))
button_pressed = TRUE;
previous_value = current_value; // Save current value for next time
}
//===================================
void main()
{
printf("Start: ");
timer0_init();
while(TRUE)
{
if(button_pressed == TRUE)
{
button_pressed = FALSE; // Clear the button pushed flag
// Display a 'P' in TeraTerm every time the button is pushed.
putc('P');
}
}
}
|
This post has an alternative method of debouncing a push-button switch,
that does not use a timer interrupt:
http://www.ccsinfo.com/forum/viewtopic.php?t=53622&start=7
Edit: 'previous_value' must be a static variable.
Last edited by PCM programmer on Fri Jul 12, 2019 12:42 am; edited 1 time in total |
|
![](templates/subSilver/images/spacer.gif) |
Chrill3
Joined: 26 Dec 2014 Posts: 4 Location: Sweden
|
|
Posted: Sat Mar 14, 2015 4:19 pm |
|
|
Hi everyone
thanks for all help.
I had to right click on project and go to set configuration -> costumize and -> PICkit2 -> mark the 3 state on 'release on reset'.
everything work perfectly now ![Smile](images/smiles/icon_smile.gif) |
|
![](templates/subSilver/images/spacer.gif) |
|