336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.
tapito의 AVR 정복기
4부. RAM을 이용한 스택 구현
(c) tapitolife
-
스택?
스택(Stack)은 컴퓨터에서 후입선출의 방식으로 데이터를 저장하는 자료 구조를 말합니다. 후입선출(Last-In First-Out, LIFO)은 말 그대로 가장 나중에 저장된 데이터가 출력될 때는 가장 먼저 출력된다는 의미로서 주로 함수를 실행할 때 적용되는 개념입니다. 문자열로 이루어진 수식을 첫 글자부터 하나씩 읽어 들이면서 함수가 보이면 일단 연산 버퍼에 기억해 두었다가 버퍼에서 함수를 하나씩 꺼내 쓸 때 스택의 구조를 이용하는데, 이를 그림으로 표현하면 아래와 같습니다.
그림 1. Stack 자료 구조 -
스택의 작동 과정
-
push
push은 스택의 끝에 데이터를 추가하는 동작입니다.
-
pop
pop은 스택을 이루는 데이터 중 가장 마지막 원소를 떼어 가져오는 동작입니다. pop 동작을 수행하면 스택에는 더이상 그 데이터는 존재하지 않게 됩니다.
결국 pop과 push는 아래와 같은 그림으로 표현할 수 있습니다.
그림 2. stack과 pop -
-
Stack의 구현
아래 회로는 3부에서 설명했던 RAM의 작동 방식을 토대로 간단하게 구현해 본 스택입니다. 실제 RAM이 작동되는 속도는 빠르지만, 여기서는 _delay_ms 함수를 사용해서 각 단계별로 지연시켜가면서 RAM의 작동을 확인해보도록 합니다.
그림 3. stack의 구현 (클릭하면 크게 보입니다.) 기호 품목 규격 SW1~SW8 DIP 스위치 8비트 1개 LED LED 아무거나 (저항) 저항 4.7k 1/8W로 통일 POP, PUSH Tact 스위치(누름 스위치) 아무거나 (RAM) RAM SRAM (A625308A-70SF) (ATmega) AVR ATmega8535 DIP 타입 펌웨어 소스
/************************************************************* * (c) tapito http://tapito.tistory.com/ * * * * main.c : stack test circuit * *************************************************************/ #define F_CPU 16000000 #define DELAY_TIME 20 // 스택이 최대로 가질 수 있는 원소 수. // 회로상 RAM의 주소 중 A0~A7만을 사용하고 있으므로 // 여기에서는 최대 256개 #define MAX_STACK 0xFF #include <avr/io.h> #include <avr/delay.h> int main() { int memAddr = 0x00; // 가장 끝 원소가 있는 주소 int esp = -1;// 가장 끝 원소가 몇 번째 원소인지 기억할 변수 while(1) { switch(PINB & 0b11110000) { case 0b00100000 : // Push 버튼을 눌렀을 때 처리 // 스택이 이미 가득 찼다면, Push 명령 무시 if(esp >= 0xFF) { esp = 0xFF; break; } DDRA = 0b11111111; DDRB = 0b00001111; DDRC = 0b11111111; DDRD = 0b00000000; PORTB = 0b00001111; _delay_ms(DELAY_TIME * 5); // 주소 버스로 주소를 출력한 다음... (이와 동시에 esp도 1 증가함) PORTC = (memAddr + (++esp)) & 0xFF; _delay_ms(DELAY_TIME * 5); // 데이터 버스로 D에서 입력받은 값을 출력 PORTA = PIND; _delay_ms(DELAY_TIME * 5); // 1. /CE를 LOW(=0V)로 만들어 칩 활성화 PORTB = 0b00000011; _delay_ms(DELAY_TIME * 5); // 2. /WE를 LOW(=0V)로 만들어 데이터 버스에 있는 데이터를 // RAM이 받아들이도록 함. PORTB = 0b00000010; _delay_ms(DELAY_TIME * 5); // 3. 마무리 PORTB = 0b00000111; _delay_ms(DELAY_TIME * 5); PORTC = 0b00000000; _delay_ms(DELAY_TIME * 5); PORTB = 0b00000000; _delay_ms(DELAY_TIME); break; case 0b00010000 : // Pop 명령이 들어올 경우 // 스택이 비었다면 무시 if(esp <= -1) { esp = -1; PORTD = 0b00000000; break; } DDRA = 0b00000000; DDRB = 0b00001111; DDRC = 0b11111111; DDRD = 0b11111111; PORTB = 0b00001111; _delay_ms(DELAY_TIME * 5); // memory 주소 설정 PORTC = (memAddr + esp) & 0xFF; _delay_ms(DELAY_TIME * 5); // /CE를 LOW로 만들어 칩 선택 PORTB = 0b00000011; _delay_ms(DELAY_TIME * 5); // /OE를 LOW로 만들어 RAM이 해당 주소의 데이터를 보이도록 지시 PORTB = 0b00000001; _delay_ms(DELAY_TIME * 5); // ATmega에서는 RAM으로부터 나오는 데이터를 받아들여서 PORTD로 전송 PORTD = PINA; _delay_ms(DELAY_TIME * 5); // 마무리 PORTB = 0b00000111; _delay_ms(DELAY_TIME * 5); PORTC = 0b00000000; _delay_ms(DELAY_TIME * 5); PORTB = 0b00000000; // 끝 원소는 이제 삭제되었음 esp--; _delay_ms(DELAY_TIME); break; } } return 0; }
브레드보드로 만들어 본 스택 회로입니다.
협찬: 땅콩캬라멜(?)3부에서 손으로 직접 RAM을 제어하던 것을 이제 ATmega에 작성된 프로그램이 대신 제어합니다.
데이터 모니터입니다. 어떤 데이터가 입력되고 있고 어떤 데이터를 출력하고 있는지 LED로 보여줍니다.
RAM을 제어하는 3가지 신호:CE, OE, WE입니다.
주소 버스입니다. LED를 통해 RAM에 접근하고 있는 주소를 보여줍니다.영상 1. stack과 pop 작동 영상
'Embeded Programming > AVR' 카테고리의 다른 글
Tapito의 AVR 정복기 – 6부. 비안정 멀티바이브레이터 (14) | 2012.03.04 |
---|---|
tapito의 AVR 정복기 - 5부. FND (0) | 2012.01.29 |
tapito의 AVR 정복기 - 3부. RAM (4) | 2012.01.09 |
CodeVision과 AVR Studio간의 인터럽트 비교 (0) | 2011.12.18 |
소스로 보는 ATmega8535 – 2부. I/O Port (4) | 2011.12.18 |