BASIC4MCU | 질문게시판 | atmega128 인터럽트 질문
페이지 정보
작성자 초코우유먹자 작성일2018-06-11 15:57 조회10,301회 댓글1건본문
// 헤더
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "avr/io.h"
#include "avr/interrupt.h"// [variables]
volatile int Level = 1; // 게임 레벨(속도)
volatile int Score = 0; // 점수
volatile enum { Direction_L, Direction_R}Direction = Direction_R; // 게임 방향volatile int T_cnt = 0; // m초[ms] 단위 Count를 위한 변수
volatile int t_cnt = 0; // Star 지나가는 Count를 위한 변수
volatile int Time_ms = 0; // [전역변수] 시간int Time_area = 0; // Main함수에서 순간 현재시간을 저장하기 위한 변수
volatile int Key_input =0; // 'my_getchar' 입력시 전역변수로써 입력 key 저장volatile enum { Star_L2, Star_L1, Star_C0, Star_R1, Star_R2 } Star = Star_L2; // '상태' 정의 // [전역변수]'클레이위치'를 열거형 변수로 선언
volatile enum { State_Display, State_Success, State_Failure, State_Finish } State = State_Display; // [전역변수]'상태'를 열거형 변수로 선언
// [initialization]
void cpu_init(void); // MCU 초기화 function
void usart01_setup(void); // Usart0,1(1use) 초기화 function
void TimerCounter0_setup(void); // TimerCounter 초기화 function
void Timer_Reset(void); // 임의 Timer/Counter '변수' 초기화
// [Usart]
char ASC_Number[] = { 48, 49, 50, 51, 52, 53, 54, 55, 56, 57 }; // tx시 편리성을 위함
int my_putchar(char data); // COM1 송신 (Usart1:use)
int my_getchar(void); // COM1 수신 (Usart1:use)
void tx_string(unsigned char *string); // string 송신
// ================================ 메인 프로그램 ========================================
// ---------------------------------------------------------------------------------------int main(void)
{
cpu_init(); // MCU 초기화 function
usart01_setup(); // Usart0,1(1use) 초기화 function
TimerCounter0_setup(); // TimerCounter 초기화 function
tx_string("\n강화를 시작합니다\n");tx_string("강화 시작!!\n");
Timer_Reset();
while(0){
my_putchar(48);
my_putchar('\n');
}
while (1)
{
switch (State){
case State_Display:
switch (Star){
case Star_L2:
tx_string("\n★□□□□ ");
Time_area = Time_ms;
my_putchar(ASC_Number[Time_area / 100]);
my_putchar(ASC_Number[(Time_area%100)/ 10]);
my_putchar(ASC_Number[(Time_area%100)% 10]);
break;case Star_L1:
tx_string("\n□★□□□ ");
Time_area = Time_ms;
my_putchar(ASC_Number[Time_area / 100]);
my_putchar(ASC_Number[(Time_area%100)/ 10]);
my_putchar(ASC_Number[(Time_area%100)% 10]);
break;case Star_C0:
tx_string("\n□□★□□ ");
Time_area = Time_ms;
my_putchar(ASC_Number[Time_area / 100]);
my_putchar(ASC_Number[(Time_area%100)/ 10]);
my_putchar(ASC_Number[(Time_area%100)% 10]);
break;case Star_R1:
tx_string("\n□□□★□ ");
Time_area = Time_ms;
my_putchar(ASC_Number[Time_area / 100]);
my_putchar(ASC_Number[(Time_area%100)/ 10]);
my_putchar(ASC_Number[(Time_area%100)% 10]);
break;case Star_R2:
tx_string("\n□□□□★ ");
Time_area = Time_ms;
my_putchar(ASC_Number[Time_area / 100]);
my_putchar(ASC_Number[(Time_area%100)/ 10]);
my_putchar(ASC_Number[(Time_area%100)% 10]);
break;
}
break;case State_Success:
++Score;
tx_string("\n\nSUCCESS\n");
tx_string("SCORE:");
my_putchar(ASC_Number[Score/10]);
my_putchar(ASC_Number[Score%10]);
my_putchar('\n');
if (Level < 5){
Level++;
}
Direction = Direction_R;
Star = Star_L2;
Timer_Reset();
State = State_Display;
break;case State_Failure:
tx_string("\n\nFailure\n");
tx_string("SCORE:");
my_putchar(ASC_Number[Score % 10]);
my_putchar('\n');
Direction = Direction_R;
Star = Star_L2;
Timer_Reset();
State = State_Display;
break;case State_Finish:
tx_string("\n\nFinish\n");
tx_string("Final score:");
my_putchar(ASC_Number[Score % 10]);
my_putchar('\n');
tx_string("RE START:");
tx_string("Go!");
Level = 0;
Score = 0;
Direction = Direction_R;
Star = Star_L2;
Timer_Reset();
Time_ms = 0;
State = State_Display;
break;
}
}
return 0;
}// ================================ 초기화 ==================================
// --------------------------------------------------------------------------void cpu_init(void)
{
// =================================================================================
// 불 필요한 Interrupt, 외부 메모리, 포트 입출력 등 이상 동작을 방지하기 위해 초기화
// =================================================================================// Interrupt 초기화 -----------------------
EICRA = 0x00; // External(외부)interrupt 0~7 발생하지 않도록 (disable) (datasheet P.90~92)
EICRB = 0x00;
EIMSK = 0x00;
EECR = 0x00; // EEPROM interrupt (disable) (datasheet P.22)
TIMSK = 0x00; // Timer(s)/Counter(s) interrupt(s) (disable)
ETIMSK = 0x00;
UCSR0B = 0x00; // USART 0의 interrupt (disable) datasheet P.190
UCSR1B = 0x00; // USART 1의 interrupt (disable) datasheet P.190
SPCR = 0x00; // SPI interrupt (disable) datasheet P.167
TWCR = 0x00; //TWI의 interrupt (disable) datasheet P.206
ADCSRA = 0x00; // Analog-to-Digital converter의 interrupt (disable) datasheet P.244
ACSR = 0x00; // Analog comparator의 interrupt (disable) datasheet P.227
sei();
// ----------------------------------------// PORTn 초기화 ---------------------------
PORTA = 0x00; //포트출력 reg
DDRA = 0x00; //포트 방향 reg(0입력, 1출력)
PORTB = 0x00; //포트출력 reg
DDRB = 0x00; //포트 방향 reg(0입력, 1출력)
PORTC = 0x00; //포트출력 reg
DDRC = 0x00; //포트 방향 reg(0입력, 1출력)
PORTD = 0x00; //포트출력 reg
DDRD = 0x00; //포트 방향 reg(0입력, 1출력)
PORTE = 0x00; //포트출력 reg
DDRE = 0x00; //포트 방향 reg(0입력, 1출력)
PORTF = 0x00; //포트출력 reg
DDRF = 0x00; //포트 방향 reg(0입력, 1출력)
PORTG = 0xFF; //포트출력 reg
DDRG = 0xFF; //포트 방향 reg(0입력, 1출력)
// ----------------------------------------// External SRAM/XMEM 초기화 --------------
MCUCR = 0x00;
XMCRA = 0x00;
XMCRB = 0x00;
// ----------------------------------------
}void usart01_setup(void)
{
UCSR0A = 0x00;
UCSR0B = 0x98;
UCSR0C = 0x06;
UBRR0H = 0x00;
UBRR0L = 0x33;UCSR1A = 0x00; // U2X(Double speed): [X]
UCSR1B = 0x98; // rx,tx enable & Rx Interrupt enable
UCSR1C = 0x06; // Asynchronous, No parity, 1 stop bit, (UCSZn[2:0]:011) 8 data bits
UBRR1H = 0x00; //
UBRR1L = 0x33; // Baud Rate: 19200// stdio.h의 413line 근처에 있는 함수로서,
// winavr이 제공하는 함수이다.
// 이 함수는 널리 사용하는 printf함수를 이용하여 USART를 통해서 message를 송신 (예, PC hyp
// ---------------------------------------------------------------------------------------
}void TimerCounter0_setup(void)
{
cli();
TCNT0 = 0x00; // Timer/Counter Register 초기화
TCCR0 = 0x0E; // WGM[1:0]=10 :CTC모드 , CS[2:0]=110 :clk/256 = 16us
TIMSK = 0x02; // T/C0 Output Compare Match interrupt: Enable
OCR0 = 249; // 0CR0 = 249로써 0~249
sei(); // CTC, clk/256=16us, 0CR0:250 임으로... CompareMatchInterrupt주기:(16u*250= 4m[sec]
}int my_putchar(char data)
{
if (data == '\n'){
while((UCSR0A & 0x20) == 0);
UDR0 = '\r';
}
while ((UCSR0A & 0x20) == 0);
UDR0 = data;
return(0);
}int my_getchar(void)
{
while((UCSR0A & 0x80) == 0);
return(UDR0);
}void tx_string(unsigned char *string)
{
while (*string != '\0')
{
my_putchar(*string);
string++;
}
}void Timer_Reset(void)
{
T_cnt = 0;
t_cnt = 0;
}// ================================ Interrupt ===============================
// --------------------------------------------------------------------------
SIGNAL(SIG_OUTPUT_COMPARE0) // CTC, clk/256=16us, 0CR0:250 임으로... CompareMatchInterrupt주기:16u*250= 4m[sec]
{
T_cnt++;
t_cnt++;if (T_cnt == 25) // TIMER0_COMP_vect 발생주기[4m] X Count[250] = 1s
{
if(Time_ms < 200) ++Time_ms;
else State = State_Finish;
T_cnt = 0;
}if (State == State_Display)
{
if (t_cnt == (250 - 50 * (Level - 1))) // Level1: 1.0초마다 ...Level5: 0.2초마다 상태 변환
{
if(Direction == Direction_R){ // 방향이 좌에서 우라면...
switch (Star){
case Star_L2:
Star = Star_L1;
break;case Star_L1:
Star = Star_C0;
break;case Star_C0:
Star = Star_R1;
break;case Star_R1:
Star = Star_R2;
break;case Star_R2:
Star = Star_R1;
Direction = Direction_L;
break;
}
}
else{ // 방향이 우에서 좌라면...
switch (Star){
case Star_R1:
Star = Star_C0;
break;case Star_C0:
Star = Star_L1;
break;case Star_L1:
Star = Star_L2;
break;case Star_L2:
Star = Star_L1;
Direction = Direction_R;
break;
}
}
t_cnt = 0;
}
}
else t_cnt = 0;
}SIGNAL(SIG_UART0_RECV) // Rx Interrupt
{
Key_input = my_getchar(); //key_com undeclared
if (State == State_Display)
{
if (Star == Star_C0)
{
State = State_Success;
}
else
{
State = State_Failure;
}
}
//if (Key_input_ == 82 || Key_input_ == 114)
// State = State_Finish;
}
poling의 무한 while문을 사용하여 간단히설명하여 20초동안
x0000 -> 0x000 -> 00x00 이런식으로 출력되도록 하였는데
tx interrupt를 사용하고 싶은데 어떻게 변경해야하나요?
while문을 사용하지않고 반복적인것을 출력하는것을 모르겟어요
댓글 1
조회수 10,301master님의 댓글
master 작성일tx interrupt가 아니고 타이머 인터럽트 아닌가요?