Delay Using Interrupt in Mikroc

Thread Starter

sonar_abhi

Joined Mar 19, 2016
22
Hello Guys,

I am trying to implement a delay using timer0 interrupt. I'll just post an abstraction of the code in mikroc

C:
void inittimer()
{
//Timer initialization for a 32ms interrupt
}

void interrupt()
{
//interrupt code;
delayvariable++;
}

void main()
{
 TRISB = 0;          //PORTB is output
 TRISC.F0 = 1;   //PORTC Pin 0 is input and connected to a switch
 if (PORTC.F0 ==0) {//check is the button is pressed

   if (delayvariable==3){   //~100ms second delay to check buttton debounce
      if (PORTC.F0==0) { //check if the button is still pressed
          PORTB = ~PORTB; //toggle PORTB
          delayvariable = 0;  //reset the delay variablE
      }
   }
 }
}
The above code does not work as I expected. Can somebody please point out the mistake I am making or suggest a better way for achieving a 100 ms delay using interrupt?
 
Last edited by a moderator:

JohnInTX

Joined Jun 26, 2012
4,787
The problem is likely because the delay variable gets incremented past 3 regardless of the button so when the button is pressed, it fails the ==3 test.

Interrupt timers are the correct way to do it but try this:

C:
void interrupt()
{
  if (TimerInterruptFlag)  // free running interrupt timer every 32ms
   if(delayvariable) delayvariable--;  // count delay variable to zero and leave it there
}
Then load the timer to your value when you detect the switch and just wait until it goes to 0 again. Since the timer runs under interrupt and stops automatically, you can go away and do other things while it is timing. That's why you do it this way.

Have fun.
 

ErnieM

Joined Apr 24, 2011
8,415
There is at problem in that you have no main loop, so your code completed the main function and resets over and over.

Put your button code inside a while(1) loop.

If you want to use delayvariable to count time you need to set out to zero as you begin to use it.
 

Thread Starter

sonar_abhi

Joined Mar 19, 2016
22
@JohnInTX, will try what you suggested.

@ ErnieM, My Bad...This is the complete code. Ideally, the PORTB should toggle if the button is pressed. But the problem lies in the button debounce part. The PORTB is toggled only if the button is pressed for more than 8 seconds. Also if the button is kept pressed, the PORTB keeps on toggling continuously every 32mS. I was expecting the button to be read and if after 32mS if the button is still pressed, the PORTB is toggled. Normally, delay is used to check the button debounce but I do not want to use the delay or the BUTTON library of mikroc. I want to do it via interrrupt

Code:
#define SW1 PORTC.RC0

char latdelay;

void InitTimer0(){
  OPTION_REG     = 0x87;
  TMR0           = 6;
  INTCON         = 0xA0;
}

void Interrupt(){
  if (TMR0IF_bit){
   TMR0IF_bit   = 0;
   TMR0         = 6;
   latdelay++;
  }
}

void main(){
InitTimer0();
TRISC.RC0 = 1;
TRISB     = 0;
PORTB     = 0x00;

while (1){
  if (SW1 == 0){
   if (latdelay == 3)
    {
     if (SW1 == 0){
     PORTB = ~PORTB;
     latdelay=0;
     }
    }
   }
}
}
 

Thread Starter

sonar_abhi

Joined Mar 19, 2016
22
Hello Guys,
Solved the problem. Thanks for the helpful advice. Here is the code in case anyone needs it

Code:
#define SW1 PORTC.RC0


char latdelay, portdelay;

void InitTimer0(){
  OPTION_REG     = 0x87;
  TMR0           = 6;
  INTCON         = 0xA0;
}

void Interrupt(){
  if (TMR0IF_bit){
   TMR0IF_bit   = 0;
   TMR0         = 6;
   latdelay++;
  if (latdelay>3){
    portdelay=1;
    latdelay=0;
   }
  }
}

void main(){
InitTimer0();
TRISC.RC0 = 1;
TRISB     = 0;
PORTB     = 0x00;
while (1){
     if (SW1==0)
     {
      latdelay=0;
     if (SW1 == 0 && portdelay ==1){
     PORTB = ~PORTB;
     portdelay=0;
     }
   }
}
}
 

Thread Starter

sonar_abhi

Joined Mar 19, 2016
22
Hello All,

I am using two 74HC595 Shift Resisters for a 4digit SSD.

The problem is that the display needs to be delayed while scanning through the digits. I do not want to use delay since while the display is on, nothing can work as the processor is busy in delay loop. So I thought I will use an interrupt based delay.

Code:
void InitTimer0(){
  OPTION_REG     = 0x87;
  TMR0           = 6;
  INTCON         = 0xA0;
}

void Interrupt(){
  if (TMR0IF_bit){
    TMR0IF_bit   = 0;
    TMR0         = 6;
    latdelay++;
    if (latdelay>3){
    portdelay=1;
    latdelay=0;
   }
  }
  }
and the function that shifts the digits is as follows

Code:
void shiftdata(char _shiftdata)
{
char i;
char temp;
int m,n;
temp = _shiftdata;
i=8;
while (i>0)
{
  if (temp.F7==0)
   {
    SHIFT_DATA1 = 0;
   }
   else
   {
    SHIFT_DATA1 = 1;
   }

   temp = temp<<1;
   SHIFT_CLOCK1 = 1;
   if (latdelay>3 && portdelay==1){    //If I comment out this loop and add the Delay_ms(100) the system works fine displaying digits one by one
   //Delay_ms(100);                          // else, all the digits are displayed simultaneously 
    SHIFT_CLOCK1 = 0;  
    i--;
    portdelay = 0;
   }
}
}
 

MrChips

Joined Oct 2, 2009
34,807
There are a number of issues with your approach to the problem.

Firstly, there are hundreds of thousands of different microcontrollers. How are we to know which microcontroller you are using?
Also, which software development platform are you using?

Writing code to use interrupts have to follow a certain recipe.

1. Write the interrupt service routine.
2. Tell the MCU which interrupt service routine is to be used for each specific interrupt.
3. Enable interrupts for the specific interrupting hardware.
4. Enable master interrupt.

void Interrupt( ) is just another function and is not the ISR (interrupt service routine). You need something else to tell the compiler that this is the ISR.

More importantly, you need a strategy or algorithm on how you are going to use the interrupt capability. You just cannot simply replace the Delay_ms(100) statement.

What do you want the program to do while waiting for interrupts?
When a timer interrupt is detected, send one clock pulse. Then what do you do next?
 

MrChips

Joined Oct 2, 2009
34,807
Sorry, I just noticed you had already started a similar thread on the same topic.
Keep the discussion in the same thread unless the topic has changed.

btw, I don't do Mikroc or PICs.
 

Thread Starter

sonar_abhi

Joined Mar 19, 2016
22
I am using PIC16F877A and mikroC for PIC

In mikroC, as I understand, this is a perfectly valid way of interrupt (Or ISR if we may call it) declaration. Shown below is the code snippet from mikroC website.

Interrupt Examples
Here is a simple example of handling the interrupts from TMR0 (if no other interrupts are allowed):

void interrupt() {
counter++;
TMR0 = 96;
INTCON = 0x20;
}
As you said, I need a strategy. I am just starting serious programming. If you can point me a direction as to what am I doing wrong and what should I do to correct it, it would be helpful.
 

MrChips

Joined Oct 2, 2009
34,807
Sorry, I am not familiar with MikroC.
I am more accustomed to seeing something like:
void interrupt ISR(void)

As I said before, what do you want the program to do while waiting for a timer interrupt?
 

Thread Starter

sonar_abhi

Joined Mar 19, 2016
22
The oscillator frequency is 8Mhz.
I'll just briefly illustrate the system and the problem I am facing.
The system consists of 6 switches which control 6 different applications. When I am displaying the current information on the SSD, the system doesn't recognize any of the switch being pressed. Once the SSD is switched off, the system recognizes the switch press normally. Hence I thought of shifting from a delay based SSD display function.
As I had included the code snippet earlier, if I keep the delay loop in the second shift resister, the system works displaying each digit, if delay is not used, the system displays the same data in all 4 digits of the 4 digit SSD.
Maybe my approach to this problem itself is fundamentally wrong, will work on it for a couple of days.
 

MrChips

Joined Oct 2, 2009
34,807
The oscillator frequency is 8Mhz.
I'll just briefly illustrate the system and the problem I am facing.
The system consists of 6 switches which control 6 different applications. When I am displaying the current information on the SSD, the system doesn't recognize any of the switch being pressed. Once the SSD is switched off, the system recognizes the switch press normally. Hence I thought of shifting from a delay based SSD display function.
As I had included the code snippet earlier, if I keep the delay loop in the second shift resister, the system works displaying each digit, if delay is not used, the system displays the same data in all 4 digits of the 4 digit SSD.
Maybe my approach to this problem itself is fundamentally wrong, will work on it for a couple of days.
So service the timer and switches using interrupts.
 
Top