출처:
http://cpu.kongju.ac.kr/ezboard/ezboard.cgi?db=qa_avr&action=read&dbf=200903120001
----------------------------------------------------------------------------------------------------------------------------------------------------
교수님 안녕하십니까?
저는 강원도 태백에서 농사를 짖고 있는 40대 중반의 농사꾼입니다.
사람이 살다보면 때로는 본인의 분수에 넘치는 능력이 필요할 때가 있는것 같습니다. 제가 지금 바로 그런 상황에
놓 여 있어 교수님께 실례를 무릅쓰고 질문 드리오니 소중한 가르침을 부탁드립니다.
제가 ATmega128L을 이용하여 온도 및 습도를 체크하여 저장하였다가 몇일단위로 PC에 연결하여 전송하는 장비를
만들어보려 하고 있습니다. 장비가 장착될 곳의 환경이 전력선을 이용한 전력의 공급이 어려운 상황인지라
배 터리를 이용하려 하는데 상기 표제의 Sleep모드에서 어려움을 겪고 있습니다.
질문을 요약하면 이렇습니다.
* External Interrupt 0을 이용해서 Sleep모드에 들어가고 External Interrupt 4에 의해서 Wake up되도록 하려는데
(사실은 INT0에서 토글이 되도록 했으나(Sleep<-->Wake up), 잘되지 않아 프로그램의 흐름을 확인해 보고자
이렇게 해 본 것입니다.)
일단 INT0에 의해서 Sleep모드에 진입은 잘 됩니다.(확인은 멀티테스트의 전류계를 이용했습니다.)
진입 후 INT4에 의해서 Wake up이 되지 않아 확인해본 바 재귀호출에 빠지는 것 같습니다.
궁금한 것은 Sleep모드에 진입 후 INT4에 의해서 Wakeup 되는 과정과 이후 프로그램 흐름에 대하여 알고 싶습니다.
제가 지금까지 보아온 바로는 INT0에 의해서 Sleep모드에 진입 후 INT4가 발생하면 INT4서비스 루틴을 실행하기 전
INT0 서비스루틴의 Sleep모드 이후 step을 진행하는 것 같습니다. 그래서 재귀호출이라는 표현을 위에서 한 것인데
이것이 맞는지 궁금하고, 맞다면 해결책이 있는지도 궁금합니다.
해결방법이 Assembly 프로그램으로 가능하다면 이부분만 Assembly로 코딩하고 나머지는 C로 코딩 후 어셈블 및 컴파일
후 각각의 오브젝트 파일로 Linking이 가능한지도 궁금합니다.
아래는 이 문제와 관련한 소트코드 입니다.
감사합니다.
/*****************************************************************************
File Name : 'main.c'
Title : AVR project ATmega128로 PowerDown Mode 진입하고 빠지기
Author : Lee JeongHoon
Created : 2/22/2009
Revised :
Version : 1.0
Target MCU : Atmel AVR series
Description : set_bit(PORTC, PC1);--> PORTC의 PC1을 High로 설정
clear_bit(PORTC, PC1); --> PORTC의 PC1을 Low로 설정
*****************************************************************************/
#include <avr/io.h>
#include <avr/interrupt.h>
#include "macro.h"
#include "delay.h"
void Set_ExtInt();
void Init_Port(void);
void POWER_SAVE(void);
/*--------------------------------------------------------------------
외 부인터럽트 서비스 루틴
--------------------------------------------------------------------*/
ISR(INT0_vect)
{
if(((~PORTC) & 0x02)){
set_bit(PORTC, PC1);
asm("sleep");
}
else
clear_bit(PORTC, PC1);
Loop:
while(!(PIND & 0x01));
Delay_ms(50);
if(!(PIND & 0x01)) goto Loop;
EIFR |= 0x01;
}
ISR(INT4_vect)
{
if(((~PORTC) & 0x02))
set_bit(PORTC, PC1);
else
clear_bit(PORTC, PC1);
Loop:
while(!(PINE & 0x10));
Delay_ms(50);
if(!(PINE & 0x10)) goto Loop;
EIFR |= 0x01;
}
/*--------------------------------------------------------------------
파 워다운모드 설정
--------------------------------------------------------------------*/
void POWER_SAVE(void)
{
//PWRDN_MODE_1;
set_bit(MCUCR, SE);
clear_bit(MCUCR, SM2);
set_bit(MCUCR, SM1);
clear_bit(MCUCR, SM0);
}
/*--------------------------------------------------------------------
External Interrupt Setting
--------------------------------------------------------------------*/
void Set_ExtInt()
{
//The low level of INTn generates an interrupt request.
clear_bit(EICRA, ISC01); //Ext INT0
clear_bit(EICRA, ISC00);
clear_bit(EICRB, ISC41); //Ext INT4
clear_bit(EICRB, ISC40);
set_bit(EIMSK, INT0);
set_bit(EIMSK, INT4);
SREG = 0x80;
}
/*--------------------------------------------------------------------
Port 초기화
--------------------------------------------------------------------*/
void Init_Port(void)
{
DDRA = 0xFF;
PORTA = 0x00;
DDRB = 0xFF;
PORTB = 0x00;
DDRC = 0xFF;
set_bit(DDRC, PC1); //출력으로 설정
PORTC = 0x00;
DDRD = 0xFF;
clear_bit(DDRD, PD0); //Interrupt PE4 입력
PORTD = 0x00;
DDRE = 0xFF;
clear_bit(DDRE, PE4); //Int4
PORTE = 0x00;
DDRG = 0xFF;
PORTG = 0x00;
}
/*--------------------------------------------------------------------
Main Program
--------------------------------------------------------------------*/
int main(void)
{
//PORT 초기화
Init_Port();
POWER_SAVE();
Set_ExtInt();
while(1);
return 1;
}