I am currently using Arduino Uno a smy developement board which has ATmega328P microcontroler on it with 16 MHz oscillator.
When I try to use any of interrupt methods the microcontroler restarts for no good reason (this even happen in simulation - I am currently running Atmel studio 7.0).
This is my code:
#define F_CPU 16000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <inttypes.h>
#include <util/delay.h>
uint32_t time_ms;
ISR(TIMER0_COMPA_vect){
static uint32_t time_old = 0;
static uint8_t count = 0;
if(time_ms - time_old > 750){
time_old = time_ms;
count++;
}
if(count > 100){
count -= 100;
PORTB ^= PORTB;
}
time_ms++;
}
int main(void)
{
time_ms = 0;
DDRB = 0xFF; //set PORTB as output
PORTB = 0xFF; //turn all leds on PORTB on
TCCR0A = 1<<WGM01;
TCCR0B = (1<<CS00); // set timer to CTC mode and prescaler to 1 (no prescaler)
TCNT0 = 0; //reset timer
OCR0A = 160; //set TOP value for timer
// TIMSK0 = (1<<OCIE0A); //enable interrupt when timer reaches TOP value
sei(); //enable interrupts
while (1)
{
PORTB ^= 0b01010101; //toggle some leds on PORTB
_delay_ms(500);
PORTB ^= 0b10101010; //toggle some leds on PORTB
_delay_ms(500);
}
}
My question is. Why doesn't interrupt work if I uncomment TIMSK0? Before I uncomment it, everything works as predicted, but when I when I do uncomment it, not even a while loop works. (This is both for simulation and when I program the chip)
Moderator edit: </mark> <mark>[code]</mark> <mark>
jernejperko:
I am currently running Atmel studio 7.0).
This is a Forum for Arduino programming with the Arduini IDE.
What is your program supposed to do? Don't expect people to see stuff like TCCR0A = 1<<WGM01; and know what it is for without referring to the Atmega 328 datasheet.
Is there any reason why you can't achieve the results you want with the Arduino system?
TCCR0A = 1<<WGM01;
TCCR0B = (1<<CS00); // set timer to CTC mode and prescaler to 1 (no prescaler)
TCNT0 = 0; //reset timer
OCR0A = 160; //set TOP value for timer
Why are you setting TCNT0 and OCR0A after starting the timer?
My question is. Why doesn't interrupt work if I uncomment TIMSK0? Before I uncomment it, everything works as predicted, but when I when I do uncomment it, not even a while loop works.
I can not confirm your findings.
I ran your code, with no changes, on a UNO. I have an external led on pin 12 and the internal led on pin 13.
The led's are blinking with the interrupt commented in or out. The pattern of blinks is not the same because of the additional toggling of the port within the interrupt. PORTB ^= PORTB
The blinks still alternate on the two leds, but the rhythm is different when the interrupt is enabled or not.
Not necessary. main accesses it before the timer is started and the access is redundant (it is already zero). Only data accessed by both an ISR and main (setup / loop) has to be volatile.
Surely any global variable is accessed from the main program, it is initialized to zero. Thus it needs to be
volatile or the initialization can be optimized away, leaving it undefined (crashing the ISR)?
Also if a variable is both read and written by an ISR you need to declare it volatile, so you have to anyway.
No, you forget that ISRs break the dataflow optimization of the compiler, so the compiler can gaily assume
the ISR is never called (although declaring an ISR prevents it being optimized away completely).
When compiling the body of the ISR is can assume the ISR is never called again, and optimize away
any DEFs that would be USEd by itself later.
volatile prevents any dataflow optimization of duplicate DEFs and unDEF'd USEs.
MarkT:
Surely any global variable is accessed from the main program, it is initialized to zero. Thus it needs to be volatile or the initialization can be optimized away, leaving it undefined (crashing the ISR)?
I don't understand that or any of the rest of what you wrote.
In any case, there may be a single potential race condition that is easily eliminated by removing the explicit unnecessary initialization...
int main(void)
{
// time_ms = 0;
DDRB = 0xFF; //set PORTB as output