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.

[SOLVED] Atmega32, int0, c, avrgcc

Status
Not open for further replies.

bitsurfer

Member level 3
Joined
Jul 19, 2012
Messages
56
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,286
Location
Croatia
Activity points
1,734
Hello,
As absolute beginner to AVR microcontrollers I try several examples from net in order to fire interrupt 0 on ATMEGA 32.
I try approach from here:
http://www.avr-tutorials.com/interrupts/avr-external-interrupt-c-programming

But as other examples this one also don't work in my case.
Here is my exact code:
Code:
#define F_CPU 7372800
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

#define DataPort PORTB
#define DataDDR	 DDRB

ISR(INT0_vect)
{
	unsigned char i;

	_delay_ms(500); // because of debouncing

	/* This for loop blink LEDs on Dataport 5 times*/
	for(i = 0; i < 5; i++)
	{
		DataPort = 0x00;
		_delay_ms(500);
		DataPort = 0xFF;
		_delay_ms(500);
	}

	DataPort = 0;


int main(void)
{
	DDRD = 1<<PD2;		// Set PD2 as input (Using for interupt INT0)
	PORTD = 1<<PD2;	// Enable PD2 pull-up resistor

	cli();
	GICR = 1<<INT0;	// Enable INT0
	MCUCR = 1<<ISC01;       // Trigger INT0 on falling edge

	sei();			// Enable Global Interrupt

	DataDDR = 0xFF;	// Configure Dataport as output
	DataPort = 0x01;	// Initialise Dataport to 1

    while(1)
    {
		if(DataPort >= 0x80)
			DataPort = 1;
		else
			DataPort = (DataPort << 1);

		_delay_ms(500);
    }
}

From all my readings that code should work but it don't do a code which is inside ISR(INT0_vect).
Since I haven't debugger I don't know if interrupt is even fired.

Chip is new so maybe something with fuses.

Any idea why this might not work?
 

In the meantime i found how my fuse bits are set:

C:\Users\User 1>cat low.bin high.bin
0xe4
0x99

If this is impotrant for interrupts problem anyway...
 

The braces for interrupt routine is not matching. Delay inside the interrupt routine is your actual problem. Don't use delay inside interrupt routine. Just set a flag inside ISR whenever there is an interrupt and then in the while(1) loop check if this flag is set and if set then execute the code that has to be executed on interrupt and then clear the flag so that the code can execute again on another interrupt.
 
Hi jayanth,
I do like you suggest and program work same as before (ISR don't work).
Sorry for braces, error while copying.

Code now:
Code:
#define F_CPU 7372800
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

#define DataPort PORTB
#define DataDDR	 DDRB
int ininterrupt;

ISR(INT0_vect)
{
    ininterrupt = 1;
}

int main(void)
{
    unsigned char i;
    ininterrupt = 0;

    DDRD = 1<<PD2;
    PORTD = 1<<PD2;

    cli();
    GICR = 1<<INT0;
    MCUCR = 1<<ISC01;

    sei();

    DataDDR = 0xFF;
    DataPort = 0x01;

    while(1)
    {
        if(DataPort >= 0x80)
            DataPort = 1;
        else
            DataPort = (DataPort << 1);

        _delay_ms(500);

        if (ininterrupt == 1)
        {
            for(i = 0; i < 5; i++)
            {
                DataPort = 0x00;
                _delay_ms(500);
                DataPort = 0xFF;
                _delay_ms(500);
            }

            DataPort = 0;
            ininterrupt = 0;
        }
    }
}
 

Crystal is 7.3728.

This is one ready maded board from ebay and may contain an error.
May I somehow test interrupt by do a shortcuircut from INT0 (pin 16) to vcc or GND?
 

If you have set interrupt on rising edge then connect INT0 pin to 5V and if you have set interrupt on falling edge then connect to gnd. Post your circuit.
 

Code:
  DDRD = 1<<PD2;
    PORTD = 1<<PD2;

Note that the ext.interrupt pin is set as output and to high logic state so it will never trigger an interrupt set on falling edge, you may even damage the pin if you apply gnd to it (you create a short).

Set it to input and retry
 

alexan,
how would I do that?
Please code example rather than I burn a chip.

jayanth,
Can't post cuircut. It is too complex. Contain many peripherials.
 

You need to set bit2 of DDRD to 0 so that PORTD.2 becomes an input

one way is
Code:
DDRD = ~(1<<PD2);   // sets pin as output

- - - Updated - - -

You may use a resistor in series with the pin while you experiment to limit the current in case of a mistake, you can use a value like 1k or more
 

Thanks for code, I replaced that line.

When I press INT0 button portB becames 11111101 every time for a short period of time.
When I connect pin 16 to vcc or gnd nothing happens, with resistor or without it.
 

Your code enables the pullup resistor so you only need to connect the interrupt pin to gnd in order to provide the falling edge.
Any change you may have already damaged the pin?

Try to use int1 or int2 and see if that works

- - - Updated - - -

I would also suggest to use

Code:
GICR|=1<<INT0;
instead of
Code:
GICR=1<<INT0;
to change only the bit you intend to
 

I read much before asking for a help here.
Now I try with totally new chip and I have same result.
Also I changed to GICR|=1<<INT0; again with same result.

I think now that most logical is that my board isn't correct or is damaged somehow.
Unfortunatelly, I haven't debugger to see where and what happens with this simple program which should work.
 

So there is no schematic of the board?

Double check the project properties, is the mcu set up correctly to mega32?
 

No, no usable schematic.
Now I create fresh project.

Here is my codeblocks project listing:
Code:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocks_project_file>
	<FileVersion major="1" minor="6" />
	<Project>
		<Option title="int0" />
		<Option pch_mode="2" />
		<Option compiler="avrgcc" />
		<Build>
			<Target title="Debug">
				<Option output="bin/Debug/int0" prefix_auto="1" extension_auto="0" />
				<Option working_dir="" />
				<Option object_output="obj/Debug/" />
				<Option type="5" />
				<Option compiler="avrgcc" />
				<Compiler>
					<Add option="-g" />
				</Compiler>
			</Target>
			<Target title="Release">
				<Option output="bin/Release/int0" prefix_auto="1" extension_auto="0" />
				<Option working_dir="" />
				<Option object_output="obj/Release/" />
				<Option type="5" />
				<Option compiler="avrgcc" />
				<Compiler>
					<Add option="-Os" />
				</Compiler>
			</Target>
			<Environment>
				<Variable name="MCU" value="atmega32" />
			</Environment>
		</Build>
		<Compiler>
			<Add option="-mmcu=atmega32" />
			<Add option="-Os" />
			<Add option="-Wall" />
			<Add option="-DF_CPU=7372800UL" />
			<Add directory="../../../WinAVR-20100110/lib/gcc/avr/4.3.3/include" />
			<Add directory="../../../WinAVR-20100110/avr/include" />
		</Compiler>
		<Linker>
			<Add option="-mmcu=atmega32" />
			<Add option="-Wl,-Map=$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).map,--cref" />
		</Linker>
		<ExtraCommands>
			<Add after='cmd /c "avr-objdump -h -S $(TARGET_OUTPUT_FILE) > $(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).lss"' />
			<Add after="avr-objcopy -R .eeprom -R .fuse -R .lock -R .signature -O ihex $(TARGET_OUTPUT_FILE) $(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).hex" />
			<Add after="avr-objcopy --no-change-warnings -j .eeprom --change-section-lma .eeprom=0 -O ihex $(TARGET_OUTPUT_FILE) $(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).eep" />
			<Add after="avr-objcopy --no-change-warnings -j .lock --change-section-lma .lock=0 -O ihex $(TARGET_OUTPUT_FILE) $(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).lock" />
			<Add after="avr-objcopy --no-change-warnings -j .signature --change-section-lma .signature=0 -O ihex $(TARGET_OUTPUT_FILE) $(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).sig" />
			<Add after="avr-objcopy --no-change-warnings -j .fuse --change-section-lma .fuse=0 -O ihex $(TARGET_OUTPUT_FILE) $(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).fuse" />
			<Add after="srec_cat $(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).fuse -Intel -crop 0x00 0x01 -offset  0x00 -O $(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).lfs -Intel" />
			<Add after="srec_cat $(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).fuse -Intel -crop 0x01 0x02 -offset -0x01 -O $(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).hfs -Intel" />
		</ExtraCommands>
		<Unit filename="fuse.c">
			<Option compilerVar="CC" />
		</Unit>
		<Unit filename="main.c">
			<Option compilerVar="CC" />
		</Unit>
		<Extensions>
			<code_completion />
			<envvars />
			<debugger />
			<lib_finder disable_auto="1" />
		</Extensions>
	</Project>
</CodeBlocks_project_file>

Here is compiling proccess report:
Code:
-------------- Clean: Release in int0 (compiler: GNU AVR GCC Compiler)---------------

Cleaned "int0 - Release"

-------------- Build: Release in int0 (compiler: GNU AVR GCC Compiler)---------------

avr-gcc.exe -mmcu=atmega32 -Os -Wall -DF_CPU=7372800UL  -Os    -I..\..\..\WinAVR-20100110\lib\gcc\avr\4.3.3\include -I..\..\..\WinAVR-20100110\avr\include -IC:\WinAVR-20100110\avr\include  -c fuse.c -o obj\Release\fuse.o
avr-gcc.exe -mmcu=atmega32 -Os -Wall -DF_CPU=7372800UL  -Os    -I..\..\..\WinAVR-20100110\lib\gcc\avr\4.3.3\include -I..\..\..\WinAVR-20100110\avr\include -IC:\WinAVR-20100110\avr\include  -c main.c -o obj\Release\main.o
avr-g++.exe -LC:\WinAVR-20100110\avr\lib  -o bin\Release\int0 obj\Release\fuse.o obj\Release\main.o   -mmcu=atmega32 -Wl,-Map=bin\Release\int0.map,--cref  
Output size is 2.38 KB
Running project post-build steps
cmd /c "avr-objdump -h -S bin\Release\int0 > bin\Release\int0.lss"
avr-objcopy -R .eeprom -R .fuse -R .lock -R .signature -O ihex bin\Release\int0 bin\Release\int0.hex
avr-objcopy --no-change-warnings -j .eeprom --change-section-lma .eeprom=0 -O ihex bin\Release\int0 bin\Release\int0.eep
avr-objcopy --no-change-warnings -j .lock --change-section-lma .lock=0 -O ihex bin\Release\int0 bin\Release\int0.lock
avr-objcopy --no-change-warnings -j .signature --change-section-lma .signature=0 -O ihex bin\Release\int0 bin\Release\int0.sig
avr-objcopy --no-change-warnings -j .fuse --change-section-lma .fuse=0 -O ihex bin\Release\int0 bin\Release\int0.fuse
srec_cat bin\Release\int0.fuse -Intel -crop 0x00 0x01 -offset  0x00 -O bin\Release\int0.lfs -Intel
srec_cat bin\Release\int0.fuse -Intel -crop 0x01 0x02 -offset -0x01 -O bin\Release\int0.hfs -Intel
Process terminated with status 0 (0 minutes, 0 seconds)
0 errors, 0 warnings (0 minutes, 0 seconds)

And here is avrdude report:
cmdwin.png

Main loop work as expected but INT dont work.
 

In the meantime i found how my fuse bits are set:

Code:
C:\Users\User 1>cat low.bin high.bin
0xe4
0x99

If this is impotrant for interrupts problem anyway...

These fuse settings are for internal RC 8MHz, your mcu is not using the crystal but this is not the cause of the interrupt malfunction, it will just give a little sorter delays.


I have not used codeblocks, I have only used AVRstudio and codevision.

Have you tried with int1 or int2 pins, maybe there is something connected to int0 on the board that doesn't allow correct operation of the interrupt
 
These fuse settings are for internal RC 8MHz, your mcu is not using the crystal but this is not the cause of the interrupt malfunction, it will just give a little sorter delays.

I noted that by comparing led switching with seconds on the wall watch!
So, this is reason for that!
I will ty later to write fuse bits properly.

As I can see, here is only INT0 and INT1 ports.
I try both.
Since chip is in ZIF socket I twist those pins to fly unconnected then try to trigger it by wire.
With same result unfortunately.

I was try to use AvrStudio 4 and 6 but I can't program a chip since my device is missing from a list of programmers.
Anyway, it seem's that all shoud work through GCC/codeblocks also.

At the moment I measure temperature with 18b20 and show results on 7-seg's with same chips which don't want to interrupt.
Here is no any caps which may be opened from switch to pin so I concludes that here must be some problem with a board.

But I will try rest of the options as soon I find few more new chips which must be somewhere in my desk :)
 

I finally find cause of those troubles.
For GCC - Integer 'ininterrupt' should be declared globally but should be declared as 'volatile' also.
That should be done so for all other interrupts in order to work.

Now (finally) my program, board and all chips work as expected from windows and linux system!

Thanks to all which tries to help.
 

For GCC - Integer 'ininterrupt' should be declared globally but should be declared as 'volatile' also.
That should be done so for all other interrupts in order to work.

What do you mean?
What do you refer to as GCC - Integer 'ininterrupt'?
 

You can see in my post from "08-07-13, 19:52".
Global variable 'int ininterrupt' should be declared as 'volatile int ininterrupt'.

Such way showed program become to behave as expected.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top