About PIC Timer And Interrupt

Thread Starter

ali1980

Joined Nov 12, 2011
7
Hello guys , the long_click function could not executed even I press the push button for long time ., always short_click function works
anybody advice ?



// ************************************************************//
/* PIC16F88 */


unsigned int volatile counter = 0 ;
bit flag ;

void Interrupt()
{
while (PORTB.F0==0 && INTCON.TMR0IF == 1) {
counter++ ;
INTCON.TMR0IF=0;
INTCON.GIE = 1 ;
if ( counter >6500) { // reset counter value
counter = 0 ;
}

}

void main() {


unsigned int Interval ;
OSCCON = 0b01111110 ; // Internal OSC 8 MHz
TRISA.F0 = 0 ; // RA0 as output
TRISB.F0 = 1 ; // RB0 as Input
PORTA.F0= 0 ; // ( Led connected )
PORTB.F0= 1 ; // push button
INTCON = 0b10000000 ;
OPTION_REG = 0b11000010 ; // interrupt on RB0 rising edge (push button) , prescaler 32 , Timer0 overflow interrupt every 1ms
ANSEL = 0 ; // All ports as digital I/O



while(1){ // infinite loop

Interval = counter ; // assign counter to Interval
if(PORTB.F0 == 0 ) { //if button pressed
delay_ms(10); // delay
INTCON.TMR0IE = 1 ; // enable timer0 Interrupt
INTCON.INT0IE = 1; // enable RB0 interrupt
INTCON.GIE = 0 ; // enable global interupt
flag = 1 ; // set flag
}

if (flag && PORTB.F0== 1 && INTCON.INT0IF == 1) // if flag and button released and INT flag do
{

if(Interval<=500){ // if Interval below 500ms do
Run_Short_Click();
Interval = 0;
counter = 0 ;
}
if(Interval>500){ // if Interval greater 500ms do // Note this not executed even long hold of button
Run_Long_Click();
Interval = 0;
counter =0 ;
}
INTCON.INT0IE = 0; // disable RB0 interrupt
flag=0 ; // clear flag
}

}

}


void Run_Short_Click() short click
{
unsigned char j ,x ;
for( j=0;j<2 ;j++ )
{
PORTA.F0 = 1 ;
delay_ms( 100);
PORTA.F0 = 0 ;
delay_ms( 100);

}

void Run_Long_Click()
{
unsigned char j ,x ;
for( j=0;j<4 ;j++ ) {
PORTA.F0 = 1 ;
delay_ms( 125);
PORTA.F0 = 0 ;
delay_ms( 125);

}
 

ErnieM

Joined Apr 24, 2011
8,377
It is almost missile to read your code as formatted. Perhaps using code tags would help (they keep your formatting intact unlike other test areas).

I did notice you enable the global interrupts inside the interrupt routine. DO NOT DO THAT. Ever. When you return from the interrupt C is smart enough to do that for you.

If you do it yourself you can retrigger interrupts while inside the routine. That can blow the return stack and make bad things happen.
 

Thread Starter

ali1980

Joined Nov 12, 2011
7
It is almost missile to read your code as formatted. Perhaps using code tags would help (they keep your formatting intact unlike other test areas).

I did notice you enable the global interrupts inside the interrupt routine. DO NOT DO THAT. Ever. When you return from the interrupt C is smart enough to do that for you.

If you do it yourself you can retrigger interrupts while inside the routine. That can blow the return stack and make bad things happen.
Thanks for your reply and advice
 

spinnaker

Joined Oct 29, 2009
7,830
You don't need to tell MikroC that is your interrupt function? Just call it interrupt?

This is really bad in an interrupt routine
while (PORTB.F0==0 && INTCON.TMR0IF == 1)

PORTB.F0 might always be 0 and TMR0IF might always be 1.

In fact TMR0IF will always be 1 at that point of your interrupt.

You don't need to use interrupts for a button push anyway. Polling with software debouncing will do. Unless you have some sort of hardware debouncing most humans will cause your interrupt routine to trigger several times with one press.


What where the results of your debugging? Have you monitored the SFR in a test loop?
 

John P

Joined Oct 14, 2008
2,025
No, I think it's OK, because TMR0IF does get cleared. But I don't see the need for a WHILE there instead of IF.

And look, formatting and code tags!

Code:
  while (PORTB.F0==0 && INTCON.TMR0IF == 1) 
  {
    counter++ ;
    INTCON.TMR0IF=0;
...
 

Thread Starter

ali1980

Joined Nov 12, 2011
7
Thank you Spinnaker and thank you John , I fixed my code it works with MPLAB but not works MikroC.
The code is attached
 

Attachments

spinnaker

Joined Oct 29, 2009
7,830
Sorry but I know nothing about Mikro C. If it works with whatever microchip compiler you are using then why not just use it? And MPLab is a development environment and not a compiler.
 

JohnInTX

Joined Jun 26, 2012
4,787
What @spinnaker said - just use X.
If you must use MikroC, realize that its syntax is different than XC8 in several areas.
Delete the #include <xc.h>, that's XC8-specific. MikroC includes the libraries you select when you create the project.
Bit-addressable SFRs (PORTS, INTCON etc), have different syntax. From the chapter 4 of the MikroC manual:
Accessing Individual Bits Of Variables
If you are familiar with a particular MCU, you can access bits by name:
// Clear Global Interrupt Bit (GIE)
GIE_bit = 0;
Also, you can simply use the direct member selector (.) with a variable, followed by
one of identifiers B0, B1, … , B7, or F0, F1, … F7, with F7 being the most significant
bit:
// Clear bit 0 in INTCON register
INTCON.B0 = 0;
// Set bit 5 in ADCON0 register
ADCON0.F5 = 1;

There is no need of any special declarations. This kind of selective access is an
intrinsic feature of mikroC PRO for PIC and can be used anywhere in the code. Identifiers
B0–B7 are not case sensitive and have a specific namespace. You may override
them with your own members B0–B7 within any given structure.
See Predefined Globals and Constants for more information on register/bit names.
Note: If aiming at portability, avoid this style of accessing individual bits, use the bit
fields instead.
sbit type
The mikroC PRO for PIC compiler has sbit data type which provides access to bitaddressable
SFRs. You can access them in the following manner:
sbit LEDA at PORTA.B0;
sbit bit_name at sfr-name.B<bit-position>;
sbit LEDB at PORTB.F0;
sbit bit_name at sfr-name.F<bit-position>;
// If you are familiar with a particular MCU and its ports and direction
registers (TRIS), you can access bits by their names:
sbit LEDC at RC0_bit;
sbit bit_name at R<port-letter><bit-position>_bit;
sbit TRISC0 at TRISC0_bit;
sbit bit_name at TRIS<port-letter><bit-position>_bit;
bit type
You'll have to visit all of the lines causing syntax errors and fix them up to what MikroC wants.

As always, the answers are in the MikroC manual.

Good luck.
 

Thread Starter

ali1980

Joined Nov 12, 2011
7
What @spinnaker said - just use X.
If you must use MikroC, realize that its syntax is different than XC8 in several areas.
Delete the #include <xc.h>, that's XC8-specific. MikroC includes the libraries you select when you create the project.
Bit-addressable SFRs (PORTS, INTCON etc), have different syntax. From the chapter 4 of the MikroC manual:

You'll have to visit all of the lines causing syntax errors and fix them up to what MikroC wants.

As always, the answers are in the MikroC manual.

Good luck.
Yup JohnInTX , I know what you mentioned about ,but what I mean was , the same code compilation was successfully rununder mikroC (of course as you said according to mikroC syntax ) , but after I tested the HEX file on Proteus it did not give me results.
Any way I will use MPLAB I think its better . By the way thank you for everybody.
 

JohnInTX

Joined Jun 26, 2012
4,787
A big difference between MikroC and XC8 that I recently found is that MikroC, by default, does not initialize static and global variables to 0. It looks like @ali1980 has that covered but something to know. Even though they are both 'C' compilers, there are lots of differences in the details.

MikroC has a warm fuzzy feel to it but I prefer XC8 myself.
 
Last edited:
Top