|
|
View previous topic :: View next topic |
Author |
Message |
walxar
Joined: 01 Nov 2014 Posts: 2
|
interrupt on change Rb4-Rb7 16F877A |
Posted: Sat Nov 01, 2014 10:12 pm |
|
|
Hi, I have the follow situation. Both codes have the same problem. When I push a button, the ISR does not disable the interrupt on change and make more than one action. Any idea why?
first code
Code: |
#int_RB
void RB_isr (void) {
static char i;
// Clear the change condition by reading Port B.
i = portb;
delay_ms(50); //antirrebote
int current;
current=input_b(); //lee el puerto inhabilita la interrupcion
static int last=0;
//SET_TRIS_B(0x00); //Configura el puerto B: 0=Salida; 1=Entrada
//output_b(0x00); //Limpia el registro del puerto
// set_tris_b(0xF1); // B7 B6 B5 B4 B3 B2 B1 B0
// 0 0 0 0 0 1 0 1 = 0x05 --- 1 1 1 1 0 0 0 1 = 0xF1 tambien pone el pin B0 como alta impedacia
//bit_test lee la posicion
#if LOWTOHIGH
if ((!bit_test(last,4))&&(bit_test(current,4))) //avanzar arriba
{}
if ((!bit_test(last,5))&&(bit_test(current,5))) //tecla abajo
{}
if ((!bit_test(last,6))&&(bit_test(current,6))) //tecla aceptar
{}
if ((!bit_test(last,7))&&(bit_test(current,7))) //tecla atras/cancelar
{}
#elif HIGHTOLOW //deteccion por flanco de bajada
//TECLA ARRIBA //
if ((!bit_test(current,4))&&(bit_test(last,4)))
{
}
//TECLA ABAJO //
if ((!bit_test(current,5))&&(bit_test(last,5)))
{
}
//TECLA ACEPTAR //
if ((!bit_test(current,6))&&(bit_test(last,6)))
{
}
//TECLA CANCELAR/ATRAS //
if ((!bit_test(current,7))&&(bit_test(last,7))) //atras -cancelar
{
}
lcdclear=1;
#endif
last=current; // dejo como registro el anterior estado para la comparacion
//output_b(input_b()); //habilito la interrupcion
}
|
second
Code: |
#int_RB
void Rbinterrup(void){
static char i;
// Clear the change condition by reading Port B.
i = portb;
lcdclear=1;
if(input(PIN_B4)==0)
{
//TECLA ARRIBA //
}
if(input(PIN_B5)==0)
{
//TECLA ABAJO //
}
if(input(PIN_B6)==0)
{
//TECLA ACEPTAR//
}
if(input(PIN_B7)==0)
{
//TECLA CANCELAR/ATRAS //
}
}
|
main
Code: |
set_tris_b(0xF1);
clear_delta();
clear_interrupt(int_rb); // borro el flag de interrupciĆ³n para que no entre al principio
port_b_pullups(False); // disable
enable_interrupts(int_ext);
enable_interrupts(INT_RB);
ext_int_edge( H_TO_L ); //inicialmente de 5V a 0V
enable_interrupts(GLOBAL);
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19499
|
|
Posted: Sun Nov 02, 2014 5:40 am |
|
|
The code looks (insert rude word here).....
Delays in the interrupt. Don't.
Basic structure. Poor.
Trying to do more in an interrupt than you should.....
You show two interrupts being enabled, but only one handler. For posting/testing, _simplify_. Have code that is complete, and shows the problem. Yours is not complete (we can't compile it and look what it is doing), and it is impossible to know wat you may be doing wrong in all the other routines in the interrupt.
If this is being used to read something like switches, then 'think again'.
Also use the C standard and declare variables at the start of code sections. C (historically) requires this. CCS 'allows' mid code declarations, but every version I have tried eventually gives odd problems if these are used. So stick to standard coding.
Things like keys and switches _will_ bounce. Multiple triggers will be common.
Get rid on the INT_RB entirely. This should _only_ be used, where you are triggering off stable reliable signals, where you need a fast response. Your delay, says this is not the case.
Instead just have a 'tick' interrupt running at perhaps 50* per second. Have this read the port, and go something like:
Code: |
//Your processor header
struct
{
int1 job1;
int1 job2;
int1 job3;
int1 job4;
} jobs = {FALSE,FALSE,FALSE,FALSE};
#byte direct=jobs
//allow direct access to bit fields
#define ALL_OFF 0xF0 //pattern for all signals high
#int_Timer1//for whatever interrupt you use
void tick(void)
{
//here every few mSec
static int8 last_read = ALL_OFF;
static int8 processed = ALL_OFF;
int8 read, changed, ctr;;
int8 mask=0x11;
read=input_b() & 0xF0; //top four bits of port b.
//Now situation is that immediate changes are ignored. If the signal has been
//stable for two calls, and has not been 'processed', then flag the job
//assuming pins go low when button is pushed.
if (read!=ALL_OFF)
{
//At least one button is pushed
if (last_read==read)
{
//signal has been the same for two calls
if (processed!=read)
{
//and the signal has not been processed
changed=processed^read;
//Now changed has bits set for each pin which has not been handled
swap(changed); //move bits into low nibble
for (ctr=0;ctr<4;ctr++)
{
if (mask & changed)
{
if (mask & read)
{
//here signal has gone off
processed|=(mask&0xF0); //turn off processed bit
}
else
{
processed&=(~mask); //turn on processed bit (low)
direct|=(mask&0xF); //turn on the job flag to say what to do
}
}
mask<<=1;
}
}
}
else
processed=ALL_OFF;
}
last_read=read;
}
void main(void)
{
setup_adc(ADC_OFF);
setup_adc_ports(NO_ANALOGS);
setup_comparator(NC_NC_NC_NC);
port_b_pullups(True); // enable to ensure the pins pull-up
setup_timer_1(T1_INTERNAL);
enable_interrupts(INT_TIMER1); //chose to suit your timer.
//With a master clock at (say) 16MHz, this would tick at 61* per second.
//for lower clock rates use timer2 or advance the tick in the interrupt
enable_interrupts(GLOBAL);
do
{
if (jobs.job1)
{
//button 1 pressed
delay_cycles(1);
jobs.job1=FALSE; //up to you if you want to keep processing
}
if (jobs.job2)
{
//button 2 pressed
delay_cycles(1);
jobs.job2=FALSE; //up to you if you want to keep processing
}
if (jobs.job3)
{
//button 3 pressed
delay_cycles(1);
jobs.job3=FALSE; //up to you if you want to keep processing
}
if (jobs.job4)
{
//button 4 pressed
delay_cycles(1);
jobs.job4=FALSE; //up to you if you want to keep processing
}
} while(TRUE);
}
|
The key point to understand, is that the interrupt on change, is _not_ suitable for receiving signals with bounce. You can use it to decode buttons, but only if you add signal processing to actually ensure you get clean button signals. It is designed for logic signals that are _clean_.
This has been explained many times here.
There are ways of using it by (for instance) having it enable a timer, and come back in this a few mSec later, and 'double check' that the signal is still good, but if you are going to do this then you might as well just use the timer in the first place.
The code handles each button just _once_ If you want the handler to be repeatedly called so long as the button is pressed, then don't clear the 'job' until you have finished processing it. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9221 Location: Greensville,Ontario
|
|
Posted: Sun Nov 02, 2014 6:02 am |
|
|
First thing I'd do is look at the example that CCS supplies in the FAQ section of the manual !! It's been in there since v2.5xx.
jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19499
|
|
Posted: Sun Nov 02, 2014 7:49 am |
|
|
However 'beware', that is for polling a button, not anything interrupt driven.... |
|
|
walxar
Joined: 01 Nov 2014 Posts: 2
|
|
Posted: Sun Nov 02, 2014 8:16 am |
|
|
Ttelmah wrote: | The code looks (insert rude word here).....
Delays in the interrupt. Don't.
Ok, my bad
Thanks for the reply , I deleted the code, use flags and masks , but I saw no need to put all code
this answer is fine for me,
It is designed for logic signals that are _clean_.
This has been explained many times here. |
I assumed that the signals were clean in ISIS. Polling is the right answer for my purpose . |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9221 Location: Greensville,Ontario
|
|
Posted: Sun Nov 02, 2014 8:23 am |
|
|
OK..NOW we know this isn't a real PIC in the real world, rather a silly ISIS 'simulation'
1) please read PIC101 on the top of the heap here
2) get a PIC, breadboard and other components.
3) come back when you get a 1Hz LED program to run THEN we can help you.
You will NEVER, ever be able to 'simulate' a PIC in ISIS properly.
ISIS is full of bugs, errors, faulty DRCs...bottom line, 'it's busted',
All the 'regulars' here know this and most will not reply to queries posted with ISIS or Proteus. The fact is this is a CCS C compiler forum and no one here cares to spend anytime trying to rewrite ISIS.
Yes, we 'deviate' a bit to help with hardware issues(EMI, glitches, etc.) as well as oddball drivers for weird chips or recoding another compiler to CCS.
jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19499
|
|
Posted: Sun Nov 02, 2014 9:40 am |
|
|
and (of course), if you 'assume they are clean', when you try to move to the real world, you will have to write the code _again_ to cope with real events. This is why unless you are already experienced, Isis can actually waste time, rather than saving it..... |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Sun Nov 02, 2014 11:20 am |
|
|
I can't help but add:
Quote: |
unless you are already experienced |
And those who ARE experienced wouldn't
fool with Proteus / Isis under any conditions !!
That ought to be food for thought.
|
|
|
|
|
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
|