Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[AVR] external interrupts atmega32

Status
Not open for further replies.

Abdulkerim

Junior Member level 1
Joined
Jan 31, 2022
Messages
16
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Location
GB
Activity points
97
hi dears
i have a small project that use atmega32 (MICROC FOR AVR)
i need to use 3 interrupts INT0, INT1, INT2 with TIMER1
1. INT0 to detect ZERO CROSSING
2. INT1 to detect MOTOR SPEED
3. INT2 to detect some EXTERNAL FEEDBACK
note that I have no any library or headers for INTERRUPTS
MY CODE:


Code:
void Timer1Overflow_ISR() org IVT_ADDR_TIMER1_COMPA
{
 MS++;
}

ISR (INT0_VECT)
{
 return ZC_FLAG = 1;
/// have i reset INT0 flag here? ///
}
ISR (INT1_VECT)
{
 return TCHO_FLAG = 1;
/// have i reset INT1 flag here? ///
}
ISR (INT2_VECT)
{
 return FEEDBACK_FLAG = 1;
/// have i reset INT2 flag here? ///
}

void main (void)
{
/// TIMER1 ///
SREG.B7 = 1; // ENABLE GLOBAL INTERRUPT BIT
TCCR1A = 0x80;
TCCR1B = 0x0B;
OCR1AH = 0x30;
OCR1AL = 0xD3;
OCIE1A_bit = 1;



/// EXT_INTS ///
SREG.B7 = 0;
GICR.B6 = 1; // INT0 ENABLE
GICR.B7 = 1; // INT1 ENABLE
GICR.B5 = 1; // INT2 ENABLE
MCUCR.B0 = 0; MCUCR.B1 = 1; // INT0 FALLING EDGE
MCUCR.B2 = 0; MCUCR.B3 = 1; // INT1 FALLING EDGE
MCUCSR.B6 = 0; // INT2 FALLING EDGE
SREG.B7 = 1; // ENABLE GLOBAL INTERRUPTS

while (1)
{               


if (ZC_FLAG) {
                      // do somethings //
                      ZC_FLAG = 0;             
                     }
if (TACHO_FLAG) {
                            // do somethings //
                            TACHO_FLAG = 0;             
                            }
if (FEEDBACK_FLAG) {
                                  // do somethings //
                                 FEEDBACK_FLAG = 0;             
                                  }

}

}
/// END CODE //




thats my code
but it dosnt compiling

thank you for help
 

Hi,

When it does not compile, it will give an error message. Please tell us.

Klaus

Added:
Do you expect that there will be additional code in the ISRs? If not you could make it more simple.
 
Last edited:

thank you KlausST

But when I delete two of these three interrupts, it compiling
error.png
 
Last edited:

Hi,

I´m not familiar with your IDE.. thus I need to guess.

* either you defined the start of the ISR else where
* or the start of the ISR is defined by libraries or code generators
* or your syntax is wrong

Klaus

in an MicroC example it looks like this:
Code:
void Timer1Overflow_ISR() org IVT_ADDR_TIMER1_OVF {

  if (counter >= _THRESHOLD) {
    PORTB = ~PORTB;             // toggle PORTB
    counter = 0;                // reset counter
  }
  else
    counter++;                  // increment counter

}
--- Updated ---

i need to use 3 interrupts INT0, INT1, INT2 with TIMER1
maybe here is your misunderstanding.
These are 4 independent interrrupts:
* INT0
* INT1
* INT2
* TIMER1

Each of them has to be defined according the rules of your compiler/IDE

Klaus
 
Last edited:
Hi,

I´m not familiar with your IDE.. thus I need to guess.

* either you defined the start of the ISR else where
* or the start of the ISR is defined by libraries or code generators
* or your syntax is wrong

Klaus

in an MicroC example it looks like this:
Code:
void Timer1Overflow_ISR() org IVT_ADDR_TIMER1_OVF {

  if (counter >= _THRESHOLD) {
    PORTB = ~PORTB;             // toggle PORTB
    counter = 0;                // reset counter
  }
  else
    counter++;                  // increment counter

}
--- Updated ---


maybe here is your misunderstanding.
These are 4 independent interrrupts:
* INT0
* INT1
* INT2
* TIMER1

Each of them has to be defined according the rules of your compiler/IDE

Klaus
thank you

KlausST

As you can see in my code
I have defined all the external interrupts according to the datasheet of the controller
But I searched the Internet and found most of the codes use a library of external interrupts
This is the link
avr interrupt library
Of course I tried to include it in my code but it didn't build
I think it should be modified before embedding
But I don't have enough experience to do that
 

Hi,

The given link is for AVR-GCC.

But you use MikroC. Thus you need to follow MikroC rules.
I didn´t read the manual (you need to do)
But I expect something similar to

"void interrupt_ISR () org IVT_ADDR_INT0"
(seen in an MikroE description)
Note: same style than defining the timer ISR

--> You need to read the manual.

Klaus
 
In fact, I read it several times but I couldn't solve the problem
So I asked for your help here
I apologize for the inconvenience, sir KlausST
 

If the interrupt handler is redefined, you must search on the attached libraries where it is already defined, there is nothing else to do.
 
Hi,

no need to apologize. Everything is fine.

It´s just that you did not write what you have read. A link is always a good idea. And the information what is clear and what is unclear.

We see that you did not follow the manual. No "void", no "org" to the "IVT". We don´t know whether you tried this or not.
If you tried: no information about the result / error message.

But we see that you tried to use GCC rules .. but they don´t apply for MikroC.

*****
I guess you´ve tried a lot, you spent a lot of time, made a lot of experience, good and bad. This is a lot of background a lot of context. We don´t have this.

You need to understand that we just have this tiny bit of information that you write in the posts. Thus the more informations you provide the better we can assist you.

*****
So how does your current code look like? What is the error description? is it solved?

Klaus
 
Your ISR code as posted good example of interrupt handling, eg set a flag and exit,
process in main().

This gives you good performance, versus practice of calling other sub routines and
functions within ISR which cause a lot of stack thrashing and latency. Also use of
pointers versus globals in an ISR good practice. Lastly any variable, global, not local,
used in ISR should be declared as "volatile".



Regards, Dana.
 

Hi,

Code:
ISR (INT0_VECT)
{
 return ZC_FLAG = 1;
/// have i reset INT0 flag here? ///
}

It might be a good idea.
I see some issues and maybe some improvements.

Issues:
* the improper ISR definition
* an ISR is not meant to RETURN values.
* and as said ZC_FLAG needs to be declared as volatile.

Improvement:
* don´t enable the INT0 interrupt
* don´t define an ISR
* don´t define a ZC_FLAG variable
.. just use the INT0_flag instead of the ZC_FLAG and you are done.
--> same functionality, less code, no processing power, no latency

If the ISR does nothing but set a flag, then it does not make much sense. The idea of an ISR is that fast events/data are stored for processing later, while other (main) jobs are running.
Or to process data immediately. ... if it does not take much time. Like comparing the ADCvalue and switch ON/OFF a port pin.

Klaus
 
Good practices for ISRs -






Regards, Dana.
 
In fact, I would like to thank you all for interacting with me and helping me
This is the complete code
please help

Code:
#include "INITS.h"
#include "VARIABLES.h"
#include "LOCK.h"
#include "PUMPS.h"
#include "VALVES.h"
#include "HEATERS.h"
#include "SENSORS.h"
#include "PRESOSTAT.h"
#include "TEST_MOTOR.h"
#include "TEST_PRESOSTAT.h"
#include "TIMING.h"

void Timer1Overflow_ISR() org IVT_ADDR_TIMER1_COMPA
{
 MS++;
}

ISR (INT0_VECT)
{
 return ZC_FLAG = 1;
}

void main (void)
{
 ADC_COMP_INIT ();
 IO_INIT ();
 INIT_INTERRUPT ();


 while (1981) {
               while (WASHING_MACHINE == 1) {
                                             WM_LOCK_FUNCTION ();
                                             WM_PUMP1_FUNCTION ();
                                             WM_PUMP2_FUNCTION ();
                                             WM_PRESOSTAT_FUNCTION ();
                                             WM_VALVE1_FUNCTION ();
                                             WM_VALVE2_FUNCTION ();
                                             WM_VALVE3_FUNCTION ();
                                             WM_VALVE4_FUNCTION ();
                                             WM_HEATER1_FUNCTION ();
                                             WM_HEATER2_FUNCTION ();
                                             WM_SENS1_FUNCTION ();
                                             WM_SENS2_FUNCTION ();
                                             } // while (WASHING_MACHINE == 1)
                       
               while (DISH_WASHER == 1) {
                                       
                                         } // while (DISH_WASHER == 1)

               while (REFRIGERATOR == 1) {

                                          } // while (REFRIGERATOR == 1)

               while (TEST_MOTOR_FLAG == 1) {
                                             TEST_MOTOR_FUNCTION ();
                                            } // while (TEST_MOTOR_FLAG == 1)

               while (TEST_PRESOSTAT_FLAG == 1) {
                                                 TEST_PRESOSTAT_FUNCTION ();
                                                } // while (TEST_PRESOSTAT_FLAG == 1)
                                             
             
             
               TIMING_FUNCTION ();
               } // while (1981)


} // void main (void)

When I use only one external interrupt
The program builds well
But when I add one more interrupt shows me an error and does not build
 
Last edited by a moderator:

Hi,

I´m a bit surprised to still see this:
Code:
ISR (INT0_VECT)
{
 return ZC_FLAG = 1;
}

It seems not to be according MikoC rules.
It´s not like I told you in post#6.

Please speak with us. Tell us why. Did you try it? What was the result?

Klaus
 
Last edited:
I'm not familiar with the IDE or device but the original errors seem to suggest the ISR is being redefined. Maybe this means there should be ISR routine that checks what triggers it rather than several routines all called "ISR", even if their parameters are different.

Brian.
 
I'm not familiar with the IDE or device but the original errors seem to suggest the ISR is being redefined. Maybe this means there should be ISR routine that checks what triggers it rather than several routines all called "ISR", even if their parameters are different.

Brian.
Thank you MR.

betwixt

In fact, I deal with all the interrupts inside the main function
I don't put any time delays in the external interrupts
As well as the definition of the pin of the interrupts as inputs with high value


Code:
void  IO_INIT (void)
{
DDRA = 0x00; // PORTA INPUTS
DDRB = 0xFB; // 0B11111011 // PB2 INPUT // INT2
DDRC = 0xFF; // PORTC OUTPUTS
DDRD = 0xF3; // 0B11110011 // PD2, PD3 INPUTS // INT0, INT1


PORTA = 0xFF; // PORTA HIGH
PORTB = 0x04; // 0B00000100 // PB2 HIGH // INT2
PORTC = 0x00; // PORTC LOW
PORTD = 0x0C; // 0B00001100 // PD2, PD3 HIGH // INT0, INT1
}
--- Updated ---

But as for routine ISR
I never dealt with him
I don't have any libraries or files for it
--- Updated ---

Thank you MR.

betwixt

In fact, I deal with all the interrupts inside the main function
I don't put any time delays in the external interrupts
As well as the definition of the pin of the interrupts as inputs with high value


Code:
void  IO_INIT (void)
{
DDRA = 0x00; // PORTA INPUTS
DDRB = 0xFB; // 0B11111011 // PB2 INPUT // INT2
DDRC = 0xFF; // PORTC OUTPUTS
DDRD = 0xF3; // 0B11110011 // PD2, PD3 INPUTS // INT0, INT1


PORTA = 0xFF; // PORTA HIGH
PORTB = 0x04; // 0B00000100 // PB2 HIGH // INT2
PORTC = 0x00; // PORTC LOW
PORTD = 0x0C; // 0B00001100 // PD2, PD3 HIGH // INT0, INT1
}
--- Updated ---

But as for routine ISR
I never dealt with him
I don't have any libraries or files for it
But as for routine ISR
I never dealt with him
I don't have any libraries or files for it
 

KlausST

betwixt

danadakk

andre_luis


Thank you all for your attention and help
The problem has been resolved
It was all because of the wrong definition


Code:
void EXT_INT0_ISR ()
{
ZC_FLAG = 1;
}

void EXT_INT1_ISR ()
{
TACHO_COUNTER++;
}

In this way, it was built without errors


But I still need help with something else
 

Hi,

I'm surprised.
Are you sure it does work? Or does it just compile?

Does TACHO_COUNTER really count? How did you test it?

Klaus
 

KlausST

I can't test it right now because I don't have controllers yet
ıt ıs just compiling and building
But when I receive the controllers, I will test it and let you know the result
Or if someone can test it right away

I think this code is compatible with a lot of controllers
But what do you think of it?
Give me your tips for driving a triac



C:
bit ZC_FLAG;
sbit TR_GATE at PORTB.B0;


void EXT_INT0_ISR ()
{
ZC_FLAG = 1;
}


void main (void)
{
SREG.B7  = 1; // GLOBAL INERRUPT
MCUCR.B3 = 1; MCUCR.B2 = 0;  //  INT1 FALLING EDGE
MCUCR.B1 = 1; MCUCR.B0 = 0;  //  INT0 FALLING EDGE
    
GICR.B7  = 1; // INT1 ENABLE
GICR.B6  = 1; // INT0 ENABLE   

DDAB.B0 = 0x01; // B7 OUTPUT
PORTB.B0 = 0; // 0 LOGIC AT OUTPUT
    
while (1) {
           if (ZC_FLAG) {
                         delay_us (100);
                         TR_GATE = 1;
                         for (i = 0; i < TR_G_H; i++) delay_ms (1); // variable delaying betweEn 0 to 10 mS
                         // it can be inc or dec by pushbutton
                         TR_GATE = 0;
                         ZC_FLAG = 0;
                        }
          }
    
    
}
 

Hi,

my tips:

* I expect it to get compiled, but I expect it not to work.
* don´t do the triac timing in main(), do it in the ISR. But don´t use busy wait like delay_us().

The general rule "don´t use delay in an ISR" or "keep the ISR as short as possible" does not mean it just should set a flag. Otherwise you´ve nothing won.

How I´d do it:
* in the ISR: CLEAR the output (for triac gate trigger)
* use the PWM hardware to automatically SET the gate trigger output.
(this just needs a couple of microseconds in the ISR)
This is the most precise solution. It just uses the ZeroCrossISR.

Another way is to use the ZeroCrossISR and a timerISR:
* in the ZeroCrossISR: CLEAR the output (for triac gate trigger)
* set the timer timeout, then leave this ISR

* in the timerISR just SET the gate trigger output. and leave.

*****
Avoid doing precise timing in main(). Do it in the ISR. This is how it´s meant to work.

*****
I know it´s hard time to go through this the first time. We all have this behind us. (not only behind)
I know it´s a lot to read ... and it needs time to understand.
But you should know: This will go on as long as you are doing electronics/software design.
All professionals read more papers every day than you may expect. It´s unavoidable in my eys, but one get´s used to it. It´s our daily job.


Klaus
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top