본문 바로가기
[Intel] 엣지 AI SW 아카데미/펌웨어 프로그래밍 75hour

[Intel] 엣지 AI SW 아카데미 14일차 (부산상공회의소 인력개발원)

by 0x01 2023. 11. 30.

제목: [Intel] 엣지 AI SW 아카데미

부제목: 14일차

일정: 2023.11.14(화)

수업 내용: 
 

 - C언어 프로그래밍

 - Micro Processor 원리 

 - Atmel사의 8bit Micro-controller 

 - KUT0128 Evaluation Board 기능과 특징

 

 - External Interrupt 제어

 

목표: 

 

 External Interrupt 제어

 

//외부 Interrupt 4 를 이용하여 SW/INT4를 누를 때마다 (falling edge),
//맨 우측 7-Segment의 표시 값이 0  1  2  3…  9  0  1.. 이
//표시되도록 프로그램을 작성하라.

//(예제 4-4) 외부 Interrupt 4에 의한 스위치 입력 실험 (응용)

• EIMSK = 0b00010000; // Interrupt 4 enable
• EICRB = 0b00000010; // Interrupt 4 falling edge
• SREG = 0x80; // Global Interrupt bit set
: MSB=1  SREG = 0x80
#include <mega128.h>

#include <delay.h>

const char seg_pat[10]= {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f};

unsigned char N1 = 0;

void main(void)
{ 
    DDRB = 0xF0; // 포트 B 상위 4비트 출력 설정
    DDRD = 0xF0; // 포트 D 상위 4비트 출력 설정
    DDRG = 0x0F; // 포트 G 하위 4비트 출력 설정
    
    // 인터럽트 초기화
    EIMSK = 0b00010000; // 외부 인터럽트4 enable
    EICRB = 0b00000010; // 외부 인터럽트4 : falling edge
    SREG = 0x80; // 전역 인터럽트 enable-bit set
    PORTG = 0b00001000; // 맨 우측 7-Segment DIG4 ON(PG3=1)

    while(1) {
        PORTD = ((seg_pat[N1] & 0x0F) << 4) | (PORTD & 0x0F); // A, B, C, D 표시
        PORTB = (seg_pat[N1] & 0x70 ) | (PORTB & 0x0F); // E, F, G 표시
		}
}

//(예제 4-5) 2개의 외부 Interrupt 를 이용한 10진 네 자리 입력 실험
• 두 개의 스위치 SW/INT4와 SW/INT5만을 이용하여 4자리를 입력하는 프로그램을 작성하라. 
• 여기서, SW/INT5는 입력될 자리(위치)를 나타내고, 
• SW/INT4 눌려지면 현재 선택된 자리의 값을 +1하도록 한다. 
• SW/INT5가 눌려지면 입력될 위치를
1자리  10자리  100자리  1000자리  1자리  10자리..로 이동하도록 한다

 

#include <mega128.h>

#include <delay.h>

typedef unsigned char U8;

const U8 seg_pat[10]= {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07,0x7f, 0x6f};

U8 N1 = 0, N10 = 0, N100 = 0, N1000 = 0; // 0 : 1자리, 1 : 10자리 , 2 : 100자리 , 3 : 1000자리
U8 pos = 0; 

void Seg4_out(void); // 네 자리수 7-Segment 출력

void main(void)
{ 
    DDRB = 0xF0; // 포트 B 상위 4비트 출력 설정
    DDRD = 0xF0; // 포트 D 상위 4비트 출력 설정
    DDRG = 0x0F; // 포트 G 하위 4비트 출력 설정
    EIMSK = 0b00110000; // 외부 인터럽트 4,5 enable
    EICRB = 0b00001010; // 외부 인터럽트 4,5 : falling edge
    SREG = 0x80; // 전역 인터럽트 enable-bit set
    while(1) 
	{
		Seg4_out();
	}
}

void Seg4_out(void)
{
    PORTG = 0b00001000; // 7-Seg DIG4 ON(PG3=1), 1자리 표시
    PORTD = ((seg_pat[N1] & 0x0F) << 4) | (PORTD & 0x0F); // A, B, C, D 표시 
    PORTB = (seg_pat[N1] & 0x70 ) | (PORTB & 0x0F); // E, F, G 표시 PORTD 하위 4bits 변경되지 않게 OR 
    delay_ms(5);
    PORTG = 0b00000100; // 7-Seg DIG3 ON(PG2=1), 10자리 표시
    PORTD = ((seg_pat[N10] & 0x0F) << 4) | (PORTD & 0x0F); // A, B, C, D 표시
    PORTB = (seg_pat[N10] & 0x70 ) | (PORTB & 0x0F); // E, F, G 표시 PORTD 하위 4bits 변경되지 않게 OR 
    delay_ms(5); 
    PORTG = 0b00000010; // 7-Seg DIG2 ON(PG1=1), 100자리 표시
    PORTD = ((seg_pat[N100] & 0x0F) << 4) | (PORTD & 0x0F); 
    PORTB = (seg_pat[N100] & 0x70 ) | (PORTB & 0x0F); //PORTD 하위 4bits 변경되지 않게 OR 
    delay_ms(5);
    PORTG = 0b00000001; // 7-Seg DIG1 ON(PG0=1), 1000자리 표시
    PORTD = ((seg_pat[N1000] & 0x0F) << 4) | (PORTD & 0x0F); 
    PORTB = (seg_pat[N1000] & 0x70 ) | (PORTB & 0x0F); //PORTD 하위 4bits 변경되지 않게 OR 
    delay_ms(5);
}


// 외부 인터럽트4 서비스 루틴
interrupt [EXT_INT4] void external_int4(void) 
{ 
    if(pos == 0) N1 = (N1 + 1) % 10; // 1자리 +1 
    else if(pos == 1) N10 = (N10 + 1) % 10; // 10자리 +1 
    else if(pos == 2) N100 = (N100 + 1) % 10; // 100자리 +1 
    else N1000 = (N1000 + 1) % 10; // 1000자리 +1 
} 

// 외부 인터럽트5 서비스 루틴
interrupt [EXT_INT5] void external_int5(void) 
{ 
	pos = (pos + 1) % 4; // 입력 자리 이동
}

 

(예제 4-6) 외부 Interrupt 를 이용한 간이 시계 실험

 

 

 

#include <mega128.h>

#include <delay.h>

typedef unsigned char U8;

const U8 seg_pat[10]= {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f};

U8 N1, N10, N100, N1000; 
U8 pos = 0; 
U8 hour = 12, min = 0, sec = 0;

void Time_out(void); // 시간 표시 함수

void main(void) { 
    unsigned char i;
    
    DDRB = 0xF0; 
    DDRD = 0xF0; 
    DDRG = 0x0F; 

	EIMSK = 0b00110000; // 외부 인터럽트 4,5 enable
    EICRB = 0b00001010; // 외부 인터럽트 4,5 falling edge
    SREG = 0x80; // 전역 인터럽트 enable-bit set

	while(1) { 
        for(i = 0;i < 49;i++) {
        	Time_out(); // 약 1초간 반복 표시
        } // end of for
        sec = sec + 1; // 초값 +1
        if(sec == 60) { 
            sec = 0;
            min = min + 1; // 분값 +1
            if(min == 60) {
                min = 0;
                hour = (hour + 1) % 24; // 시간 +1
            } // end of min
        } // end of sec 
    } //end of while
} //end of main

void Time_out(void) // display
{
    PORTG = 0b00001000; // 7-Seg DIG4 ON(PG3=1), 분 1자리 표시
    PORTD = ((seg_pat[min % 10] & 0x0F) << 4) | (PORTD & 0x0F);
    PORTB = (seg_pat[min % 10] & 0x70 ) | (PORTB & 0x0F);
    delay_ms(5);
    PORTG = 0b00000100; // 7-Seg DIG3 ON(PG2=1), 분 10자리 표시
    PORTD = ((seg_pat[min / 10] & 0x0F) << 4) | (PORTD & 0x0F);
    PORTB = (seg_pat[min / 10] & 0x70 ) | (PORTB & 0x0F); 
    delay_ms(5); 
    PORTG = 0b00000010; // 7-Seg DIG2 ON(PG1=1), 시간 1자리 표시
    PORTD = ((seg_pat[hour % 10] & 0x0F) << 4) | (PORTD & 0x0F);
    PORTB = (seg_pat[hour % 10] & 0x70 ) | (PORTB & 0x0F); 
    delay_ms(5);
    PORTG = 0b00000001; // 7-Seg DIG1 ON(PG0=1), 시간 10자리 표시
    PORTD = ((seg_pat[hour / 10] & 0x0F) << 4) | (PORTD & 0x0F);
    PORTB = (seg_pat[hour / 10] & 0x70 ) | (PORTB & 0x0F); 
    delay_ms(5); 
}

interrupt [EXT_INT4] void external_int4(void) 
{ 
    N1 = min % 10; // 현재 분 1자리 추출
    N10 = min / 10; // 현재 분 10자리 추출
    N100 = hour % 10; // 현재 시간 1자리 추출
    N1000 = hour / 10; // 현재 시간 10자리 추출
    
    if(pos == 0) N1 = (N1 + 1) % 10; // 현재 분 1단위 표시 +1 값
    else if(pos == 1) N10 = (N10 + 1) % 6; // 현재 분 10단위 표시 +1 값 (60분)
    else if(pos == 2) { // 시간 1단위 +1
        if(N1000 == 2) N100 = (N100 + 1) % 4; // 24시간의 앞자리 2이므로 20,21,22,23,24
        else N100 = (N100 + 1) % 10; // 0,1,2,3,-9,10 ,11,12,-,18, 19
	}

	else { // pos=3 (세 번 눌러짐)
        if(N100 < 4) N1000 = (N1000 + 1) % 3; // N100<4은 04 (00,01,02,03), (10,11,12,13), 
    // else if(N1000 != 1) N1000 = (N1000 + 1) % 3; 
    	else N1000 = (N1000 + 1) % 2;
	}
    
    hour = N1000 * 10 + N100; // 시간 계산 (시간 세팅 값을 void Time_out(void) 로,
    min = N10 * 10 + N1; // 분 계산
} 

interrupt [EXT_INT5] void external_int5(void) 
{ 
	pos = (pos + 1) % 4; // 입력 자리 이동
}