뉴티씨



  • HOME
  • 고객지원
  • 질문답변

 

 
interrupt를 사용하려 하는데 도움 부탁합니다
 글쓴이 : 정균희
작성일 : 05-09-20 06:44
조회 : 8,835  
   port_test._c (1.9K) [167] DATE : 2005-09-20 06:44:45
안녕하세요

인터럽터를 아래와 같이 사용하려하는데 안됨니다.
컴파일러는 icc AVR사용 / ina90.h있는 것임
- 아래
#include <iom128v.h>
//#include <macros.h>
#include <ina90.h>

unsigned char led;

interrupt[TIMER0_OVF_vect] void Timer0_interrupt(void) { //TIMER0 인터럽트
                  PORTC = ~led;  //변수 led를 반전해서 포트B에 출력
                  led <<= 1;    //다음번 출력데이터
                  if(!led)
                    led = 0x01; //최초의 상태에서부터 다시 시작한다
                  TCNR0 = 0x15;  //30ms초를 얻기 위한 값*0ㅌ15 = -235)dmf ektlfhem
                  printf("\n\r interrupt test %x\n\r",led);
}
-에러
C:\icc\bin\iccavr  -IC:\icc\include\ -e -DATMEGA  -l -g -Mavr_enhanced  -LC:\icc\lib\ -ucrtatmega.o -bfunc_lit:0x8c.0x20000 -dram_end:0x10ff -bdata:0x100.0x10ff -dhwstk_size:16 -beeprom:1.4096 -fihx_coff -S2 port_test.c  -lcatmega
!E port_test.c(11): undeclared identifier `TIMER0_OVF_vect'
!E port_test.c(11): integer expression must be constant
!E port_test.c(11): syntax error; found `void' expecting `;'
!W port_test.c(17):[warning] calling function without prototype may cause errors

잘못된부분 처리 방법를 알려주시면 고맙겠읍니다.
(이 프로그램은 책 "ATmega128과 그용용"240페이지)

또는 다른방법으로 일정시간마다 인터럽트가 발생되고 그때마다 일정한 일를 저리하려하는데 방법을 알려주시기 바람니다.

 - delay가 아니고 인터럽트를 원함

수고하세요


컴플라자… 05-09-22 02:45
 
  우선 인터럽트 함수는 아주 짧은 시간 동안 진행하는 거라
printf와 같은 함수를 쓰면 안됩니다. 그 동안 다른 인터럽트가 또 오게 되서...문제가 계속 생기게 되죠.
인터럽트 함수 만드는 것두 좀 문제가 있네요.
ICC AVR 안에 있는 마법사(application builder)로 만들어 보세요.
컴플라자… 05-09-22 03:12
 
  다음 두가지에 대한 예를 각각 아래에 적어두었습니다.
강좌->AVR 강좌에도 파일을 올려 놓지요.

1. 인터럽트 타이머 함수로 delay 함수 만들어 쓰기

우선 타이머 overflow를 enable 해 두면, 코드가 생성되면서 그 때마다 그 타이머 overflow 함수를 수행하게 됩니다.
거기서, us 타이머 나 ms 타이머 등 원하는 시간의 타이머 변수를 하나씩 증가시켜 갑니다.

delay 함수에서는 일단 타이머 변수들을 초기화 한 후,
타이머의 증가를 지켜 보다가 인터럽트에 의해 변한 타이머 변수 값(여기선 twenty_ustimer 또는 ten_mstimer)을 폴링으로 지켜보면서, 원하는 시간이 지날 때까지, delay 시킵니다.


2. 일정 시간마다 원하는 동작을 하게 하기

일정 시간마다 오버 플로우 함수에서 어떤 변수를 특정 값으로로 만들어 주고, 메인 루틴에서는 그 값을 원하는 폴링으로 지켜 보다가, 값에 따른 원하는 동작을 하면 된다.
컴플라자… 05-09-22 03:12
 
  1번에 대한 소스코드

//ICC-AVR application builder : 2005-09-22 오전 2:27:10
// Target : M128
// Crystal: 11.059Mhz

#include <iom128v.h>
#include <macros.h>

// 20us 타이머와 10ms 타이머용 변수를 만든다
int twenty_ustimer,ten_mstimer;

void port_init(void)
{
 PORTA = 0x00;
 DDRA  = 0x00;
 PORTB = 0x00;
 DDRB  = 0x00;
 PORTC = 0x00; //m103 output only
 DDRC  = 0xFF;
 PORTD = 0x00;
 DDRD  = 0x00;
 PORTE = 0x00;
 DDRE  = 0x00;
 PORTF = 0x00;
 DDRF  = 0x00;
 PORTG = 0x00;
 DDRG  = 0x00;
}

//TIMER0 initialize - prescale:1
// WGM: Normal
// desired value: 20uSec
// actual value: 19.984uSec (0.1%)
void timer0_init(void)
{
 TCCR0 = 0x00; //stop
 ASSR  = 0x00; //set async mode
 TCNT0 = 0x23; //set count
 OCR0  = 0xDD;
 TCCR0 = 0x01; //start timer
}

#pragma interrupt_handler timer0_ovf_isr:17
void timer0_ovf_isr(void)
{
 twenty_ustimer++;  // 20us마다 timer0 오버플로우 걸리면 20us 타이머를 하나씩 증가시킨다.
 if(twenty_ustimer>=500){  //20us 타이머가 500보다 크면 즉,10ms마다 10ms 타이머를 하나씩 증가시킨다.
  ten_mstimer++;
twenty_ustimer=0;  // 20us 타이머 0으로 초기화
 }
 
 TCNT0 = 0x23; //reload counter value 이 값은 실제 오실로 스코프로 찍어서, 정확한 값을 결정한다.
              //이유: 실제로는 이 값대로 되어야 하나, 인터럽트 함수에서 많은 라인들로 인하여 값이 느려진다.   
}

//UART0 initialize
// desired baud rate: 9600
// actual: baud rate:9600 (0.0%)
// char size: 5 bits
// parity: Disabled
void uart0_init(void)
{
 UCSR0B = 0x00; //disable while setting baud rate
 UCSR0A = 0x00;
 UCSR0C = 0x00;
 UBRR0L = 0x47; //set baud rate lo
 UBRR0H = 0x00; //set baud rate hi
 UCSR0B = 0xF8;
}

#pragma interrupt_handler uart0_rx_isr:19
void uart0_rx_isr(void)
{
 //uart has received a character in UDR
}

#pragma interrupt_handler uart0_udre_isr:20
void uart0_udre_isr(void)
{
 //character transferred to shift register so UDR is now empty
}

#pragma interrupt_handler uart0_tx_isr:21
void uart0_tx_isr(void)
{
 //character has been tdransmitted
}

//call this routine to initialize all peripherals
void init_devices(void)
{
 //stop errant interrupts until set up
 CLI(); //disable all interrupts
 XDIV  = 0x00; //xtal divider
 XMCRA = 0x00; //external memory
 port_init();
 timer0_init();
 uart0_init();

 MCUCR = 0x00;
 EICRA = 0x00; //extended ext ints
 EICRB = 0x00; //extended ext ints
 EIMSK = 0x00;
 TIMSK = 0x01; //timer interrupt sources
 ETIMSK = 0x00; //extended timer interrupt sources
 SEI(); //re-enable interrupts
 //all peripherals are now initialized
}

// 실제로 딜레이 할 시간 : delaytime *10 ms
void delay(int delaytime){
twenty_ustimer=ten_mstimer=0;  //타이머 함수 변수들 초기화
while(ten_mstimer < delaytime); // 10ms까지 대기
}

void main(void){
init_devices();

twenty_ustimer=ten_mstimer=0;
while(1){
delay(100); // 1초 딜레이, 아마 실제 값은 100이 아니라 40쯤 될 것임.
PORTC = 0x01;  //LED 하나 켜기
delay(100); // 1초 딜레이, 아마 실제 값은 100이 아니라 40쯤 될 것임.
PORTC = 0x02;  //LED 다른 거 하나 켜기
}
}   

컴플라자… 05-09-22 03:13
 
  2번에 대한 소스코드

//ICC-AVR application builder : 2005-09-22 오전 2:27:10
// Target : M128
// Crystal: 11.059Mhz

#include <iom128v.h>
#include <macros.h>

#define SETCANCLE  0
#define SETOK   1
#define SETSUSPEND 2

// 20us 타이머와 10ms 타이머용 변수를 만든다
int twenty_ustimer,Half_sectimer;

void port_init(void)
{
 PORTA = 0x00;
 DDRA  = 0x00;
 PORTB = 0x00;
 DDRB  = 0x00;
 PORTC = 0x00; //m103 output only
 DDRC  = 0xFF;
 PORTD = 0x00;
 DDRD  = 0x00;
 PORTE = 0x00;
 DDRE  = 0x00;
 PORTF = 0x00;
 DDRF  = 0x00;
 PORTG = 0x00;
 DDRG  = 0x00;
}

//TIMER0 initialize - prescale:1
// WGM: Normal
// desired value: 20uSec
// actual value: 19.984uSec (0.1%)
void timer0_init(void)
{
 TCCR0 = 0x00; //stop
 ASSR  = 0x00; //set async mode
 TCNT0 = 0x23; //set count
 OCR0  = 0xDD;
 TCCR0 = 0x01; //start timer
}

#pragma interrupt_handler timer0_ovf_isr:17
void timer0_ovf_isr(void)
{
 twenty_ustimer++;  // 20us마다 timer0 오버플로우 걸리면 20us 타이머를 하나씩 증가시킨다.
 if(twenty_ustimer>=25000){  //20us 타이머가 25000보다 크면 즉,0.5초마다 1초 타이머를 하나씩 증가시킨다.
  if(Half_sectimer==SETOK)
Half_sectimer = SETCANCLE;
else
Half_sectimer = SETOK;
twenty_ustimer=0;  // 20us 타이머 0으로 초기화
 }
 
 TCNT0 = 0x23; //reload counter value 이 값은 실제 오실로 스코프로 찍어서, 정확한 값을 결정한다.
              //이유: 실제로는 이 값대로 되어야 하나, 인터럽트 함수에서 많은 라인들로 인하여 값이 느려진다.   
}

//UART0 initialize
// desired baud rate: 9600
// actual: baud rate:9600 (0.0%)
// char size: 5 bits
// parity: Disabled
void uart0_init(void)
{
 UCSR0B = 0x00; //disable while setting baud rate
 UCSR0A = 0x00;
 UCSR0C = 0x00;
 UBRR0L = 0x47; //set baud rate lo
 UBRR0H = 0x00; //set baud rate hi
 UCSR0B = 0xF8;
}

#pragma interrupt_handler uart0_rx_isr:19
void uart0_rx_isr(void)
{
 //uart has received a character in UDR
}

#pragma interrupt_handler uart0_udre_isr:20
void uart0_udre_isr(void)
{
 //character transferred to shift register so UDR is now empty
}

#pragma interrupt_handler uart0_tx_isr:21
void uart0_tx_isr(void)
{
 //character has been tdransmitted
}

//call this routine to initialize all peripherals
void init_devices(void)
{
 //stop errant interrupts until set up
 CLI(); //disable all interrupts
 XDIV  = 0x00; //xtal divider
 XMCRA = 0x00; //external memory
 port_init();
 timer0_init();
 uart0_init();

 MCUCR = 0x00;
 EICRA = 0x00; //extended ext ints
 EICRB = 0x00; //extended ext ints
 EIMSK = 0x00;
 TIMSK = 0x01; //timer interrupt sources
 ETIMSK = 0x00; //extended timer interrupt sources
 SEI(); //re-enable interrupts
 //all peripherals are now initialized
}

void main(void){
init_devices();

twenty_ustimer=Half_sectimer=0;
while(1){
if(Half_sectimer==SETOK){
PORTC=0x01;
Half_sectimer=SETSUSPEND;
}else{
PORTC=0x02;
Half_sectimer=SETSUSPEND;
}
}
}   
 
   
 

 


1