View previous topic :: View next topic |
Author |
Message |
Got-Got
Joined: 26 Feb 2012 Posts: 17
|
Push Button and Interrupt problem |
Posted: Fri May 25, 2012 3:35 pm |
|
|
Hello,
I have a problem with my program. It is supposed to go to several "modes" mode 1,2 and 3 when i push a button. It doesn't work, i can't build it successfully. Always the same error:
Code: |
Error 51 "shailene.c" Line 55(9,28): A numeric expression must appear here |
( this is the line #INT_RB //Interrupt routine)
I think that my ISR is not at the good place but when i move it before or after "main(void)", some other errors appears :
Code: |
Warning 204 "shailene.c" Line 45(1,1): Condition always FALSE
*** Error 12 "shailene.c" Line 45(28,34): Undefined identifier select
*** Error 12 "shailene.c" Line 47(12,18): Undefined identifier select
*** Error 12 "shailene.c" Line 47(18,24): Undefined identifier select
|
Is there any easier way to do that ? I checked the program named PBUTT in the example files of CCS but i don't really understand it.
my version of CCS compiler is : Version 4.068
I use the plugin of CCS in MPLAB version 8.36.00.00
here is the code:
Code: |
#include <16F887.h>
#device adc=8
#FUSES NOWDT // No WDT
#FUSES INTRC // internal oscillator
#FUSES PUT //power Up Timer
#FUSES NOPROTECT //pas de protection en ecriture
#FUSES NODEBUG //No ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //eeprom protection
#use delay(internal=8Mhz) //Internal oscillator 8 Mhertz
#define BUTTON_SELECT PIN_B0
#define LED1 PIN_D0
#define LED2 PIN_D1
#define LED3 PIN_D2
#define mode1 0x01010001
#define mode2 0x01011001
#define mode3 0x01101111
#define princp 0x01000000
void init_io()
{
// port A In
SET_TRIS_A(0x11); // bit 0 = Out, 1 = In
// Port B In
SET_TRIS_B(0x11); // bit 0 = Out, 1 = In
// port D Out
SET_TRIS_D(0x00); // bit 0 = Out, 1 = In
// init Ports
OUTPUT_A(0x00);
OUTPUT_C(0x00);
OUTPUT_D(0x00);
OUTPUT_E(0x00);
}
void main(void)
{
int8 temp=0;
int8 temps=0;
int8 select=0;
int8 time=0;
enable_interrupts(INT_RB0);
enable_interrupts(GLOBAL);
set_timer0(0);
setup_counters(RTCC_INTERNAL, RTCC_DIV_256 | RTCC_8_BIT);
#INT_RB //Interrupt routine
void RB(void)
{
if (BUTTON_SELECT == 0) {++select;} // test if the Push Button is maintained and incrementing "select" variable to switch to another mode
if (select > 3) {select==0;}
}
while(true){
if (select==1) {goto_address(mode1);}
if (select==2) {goto_address(mode2);}
if (select==3) {goto_address(mode3);}
}
// mode1 LED1 blink very slowly
while(true) {
time=get_timer0();
if (time==250) {++temps; set_timer0(0);}
if (select!=1) {goto_address(princp);}
if (temps==150) {output_high(PIN_D7); temps = 0;}
}
//mode2 LED2 turned on if temp >100
SETUP_ADC(ADC_CLOCK_INTERNAL); //configur ADC converter
SETUP_ADC_PORTS(sAN0 | VSS_VDD);
while(true)
{
set_adc_channel(0);//reading AN0
delay_us(20);// delaiy 20us
temp=read_adc(); // reading AN0: 0<=temp<=255
if (temp>100) {output_high(LED2);}
else {output_low(LED2);}
if (select!=1) {goto_address(princp);}
}
//mode3 LED3 turned on continuously
while(true)
{
output_high(LED3);
if (select!=3) {goto_address(princp);}
}
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri May 25, 2012 3:42 pm |
|
|
Don't put an interrupt routine in the middle of main(). Put it above main(). |
|
|
WillysJeeps
Joined: 24 May 2012 Posts: 5
|
|
Posted: Fri May 25, 2012 3:45 pm |
|
|
I think you are missing a } at the end of the main() routine. |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Fri May 25, 2012 4:03 pm |
|
|
You're trying to define your RB interrupt routine within main().
Move it outside main().
And you will have to redefine select as global (OR do something else).
Your code still won't work.
If it still does not compile, the error messages should be more comprehensible.
Better use of indentation will make it easier to understand.
Mike |
|
|
Got-Got
Joined: 26 Feb 2012 Posts: 17
|
|
Posted: Fri May 25, 2012 5:07 pm |
|
|
Now, the ISR is out of the main() but i don't know how to define "select" as global.
"(OR do something else)." Yes may be but it is the simplest method i found to use a push button for this purpose. I don't see any other way. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Fri May 25, 2012 5:36 pm |
|
|
A few more hints:
Quote: | i don't know how to define "select" as global. | I think I don't understand the question. You already know you need a global variable, which part is it then that you don't understand? How to declare a variable as global is in every textbook on the C language and I'm sure you have looked this up, haven't you?
Code: | #define mode1 0x01010001 | Hmmm... I think you tried to define an 8-bit boolean variable but instead you declared a 32-bit hex-variable.
Not possible in most standard C variants, but easy to do in CCS. Check out the CCS manual, and yes, you'll have to find the page yourself.
Code: | if (BUTTON_SELECT == 0) | Again, this is not going to do what you want it to do. The preprocessor will do a direct text replacement and then you get:Look in the PIC16F887 header file and you will see PIN_B0 is defines as the integer 48 and then your code becomes:This is always false...
Look into the CCS manual for the input() function for the proper way to solve this.
Code: | goto_address(mode1) |
_never ever_ use the goto instruction in C or any of it's derived family members. It is considered bad programming as it leads to difficult to maintain programs. Every normal program can be written using other program flow instructions like: while, for and switch/case.
Your teacher will subtract points for using goto.
Besides all that, your goto is jumping to the wrong address so it won't work anyway. Jumping to address 'princip' at 0x01000000? The PIC16 doesn't have that much memory! What were you thinking?
Quote: | my version of CCS compiler is : Version 4.068 | This is an very old version and not a very good one. Not too bad, but it is still one of the early v4.0 compilers and full of bugs. The compiler started to work again around v4.075. You might run into troubles when you keep using this old version. Not too good a prospect considering the many basic errors you make. When it doesn't work, is it you or the compiler.......? |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Sat May 26, 2012 2:26 am |
|
|
My compiler complains, this line has not effect.
Code: | if (select > 3) {select==0;} |
By and large you don't have to set TRIS registers, CCS usually takes care of them.
You seem to be trying to set registers in binary, but using hex.
As I understand it, what you want is:-
(1) Operate in mode1 till button pressed, then advance to mode2.
(2) Operate in mode2 till button pressed, then advance to mode3.
(3) Operate in mode3 till button pressed, then return to mode1.
Is this basically correct?
When you press the switch:-
(i) How many times will the switch contact bounce?
(ii) Will each bounce generate an interrupt?
(iii) How will you prevent your system responding to bounce induced interrupts?
(iv) Will the switch contact bounce on release?
Mike |
|
|
Got-Got
Joined: 26 Feb 2012 Posts: 17
|
|
Posted: Sun May 27, 2012 3:35 am |
|
|
Ok... i was very far away from the solution. Mike, this is exactly what i want. I though it was the simplest solution but no...
For the switch contact bounce, i'd put a 10 ms delay in the ISR to avoid bouncing but i saw on ccsinfo that is was not recomended to put a delay in an ISR, so i choosed to deal with that later.
Thanks for you tips ckielstra, i will use switch/case or something like that, I saw on the CCS manual that the goto instruction is not recomended but it seems so easy to use. |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Sun May 27, 2012 5:13 am |
|
|
There's loads of button type code on this forum.
This is the bones of A WAY to deal with button bounce:-
(1) Use a timer interrupt ISR to sample switch state at ~10ms intervals.
(2) If switch is closed for two successive samples you've got a valid closure.
(3) If switch is open for two successive samples you've got a valid release.
Here's A POSSIBLE outline for a complete program:- Code: |
// declare variables
...
// define ISR routine
...
void mode1(void)
{
while(select == 1)
{
//mode1_code goes here
...
}
}
// define mode2 & mode3 similar to mode1
void main(void)
{
// initialise_timer_interrupts_etc
....
while(1)
{
mode1;
mode2;
mode3;
}
}
|
Mike |
|
|
Got-Got
Joined: 26 Feb 2012 Posts: 17
|
|
Posted: Tue May 29, 2012 2:23 pm |
|
|
Ok it's pretty easy. I wrote a very complicated ( and false) program for nothing.
Thanks a lot for the advices ! |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Tue May 29, 2012 2:55 pm |
|
|
Quote: | Ok it's pretty easy. I wrote a very complicated ( and false) program for nothing. | No.
Hopefully you have learned something, the hard way, same as the rest of us.
Best of luck.
Mike |
|
|
|