简体   繁体   中英

Why is a while loop needed in main for calling ISR in arduino UNO?

I am writing C code that gets uploaded to arduino uno. It was a simple exercise in learning how to call the ISR in C. Here is the code:

#include<stdio.h>
#include<stdlib.h>
#include<avr/interrupt.h>
#include<avr/io.h>


int main(){

 DDRB        = 0;
 PORTB       = 0;
 DDRB        = (1<<5);
 PORTB       = (0<<5);

 //resetting the Timer/Counter1
 TCNT1H         = 0;
 TCNT1L         = 0;  

 //disabling all global interrupts
 SREG         = 0;

 //defining prescalar

 //TCCR1B: ICNC1 ICES1 – WGM13 WGM12 CS12 CS11 CS10
 TCCR1B = 0;
 //TCCR1B_reg = CS11_val; WORKING SETTINGS
 TCCR1B = 0b00000101;//(1<<CS10_val)|(1<<CS12_val);

 //setting up PWM mode

 //TCCR1A: COM1A1 COM1A0 COM1B1 COM1B0 COM1C1 COM1C0 WGM11 WGM10
 TCCR1A      = 0; //this is for waveform generation and CTC setting up mode;
 //TCCR1A      = 0b10000000;//(1<<COM1A1_val);
 TCCR1A      = COM1A1;

 OCR1AH      = 0b10011100;//0b00000000;
 OCR1AL      = 0b01000000;//0b01000000;

 TIMSK1      = 0b00100010;//(1<<ICIE1_val)|(1<<OCIE1A_val);//0b00100010;//writing so that output compare A is set up

 //enable global interrupts
 SREG         = (1<<7);
 while(1){}

 return 0;

}

ISR(TIMER1_COMPA_vect){
  PORTB = PORTB^(1<<5);
}

The interesting part is when I get rid of the "while(1){}" the code doesn't seem to work to toggle PinB5 (builtin led on arduino uno). As soon as I added in the while loop I saw PinB5 toggling. The weird part is that when I want to use the timer to make a PWM that outputs directly to a Pin I don't need to use the while loop.

Just in case you guys are curious, here is how I upload to arudino-uno:

avr-gcc -Os -DF_CPU=16000000UL -mmcu=atmega328p -c -o ISR_example.o ISR_example.c
avr-gcc -mmcu=atmega328p ISR_example.o -o ISR_example
avr-objcopy -O ihex -R .eeprom ISR_example ISR_example.hex

read -p "Get ready to flash!"
#flashing the Arduino:
avrdude -C/home/ashwini/Downloads/arduino-1.8.3/hardware/tools/avr/etc/avrdude.conf -v -patmega328p -carduino -P/dev/ttyACM0 -b115200 -D -Uflash:w:ISR_example.hex:i

Very simple answer. When main returns on most AVR toolchains it evecutes cli instruction disabling the interrupts and then ends in the infinitive loop. This is the most common epilogue routine in the AVR bare metal toolchains.

This is what is happening when you exit from the main

00000078 <_exit>:
  78:   f8 94           cli

0000007a <__stop_program>:
  7a:   ff cf           rjmp    .-2         ; 0x7a <__stop_program>

You can change it by amending the startup assembly file (it contains the epilogue as well).

Without the busy-loop, the program will immediately return 0, and end. While it is in the loop, doing nothing, it can be interrupted by an Interrupt Service Routine.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM