[다시 쓰는 8051 따라하기] 8051 기초 - 내부램과 SFR
+------------------------------------------------------+
게시장소 : 다음 tinyrobo
작성자 : Timy(me^^;)
작성일 : 2004.10.29
문의 : 다음카페 tinyrobo 혹은 블로그 http://electoy.cafe24.com/blog
+------------------------------------------------------+
## 8051 기초 - 내부램과 SFR
내부램은 128 byte( 0 ~ 127 , 0x00 ~ 0x7F 번지)가 있다. AT89S52 에 롬이 있고 램도 있다고 했다. 롬의 역할이 크다보니 보통 롬이 얼마나 차지하고 있는가에 관심이 집중되는 편이다. 쉽게 말해서 어떤 놈은 플래시롬이 4k 고, 어떤 놈은 플래시롬이 8k 고, 또 어떤놈은 32k 짜리도 있다. 이처럼 롬이 얼마인가에 대부분의 관심이 집중되는 편이다.
그말은 다시말해서 램의 역할은 생각보다 그렇게 크지는 않다는게다.
보통 PC를 쓸때는 롬이 아니라 램이 얼마인가에 관심의 촛점이 모여진다.
니 컴퓨터는 몇메가짜리니?
어, 800 메가...
아니 그거 말고 램말이야 램..
아, 그거... 256메가
그래 내껀 512메간데.. ^^
ㅜ.ㅜ
대충 이런 이야기가 오간다. PC에서는 램이 큰 놈이 좋은 놈이란 인식이 있다. 그런데 이 램이라는 놈이 일반적으로 마이크로프로세서에서는 그렇게 크게 중요하게 여겨지지는 않는다. (중요하게 여겨질 수도 있겠다. 그런 프로그램이 있으면..) 대부분의 프로그램은 가능하면 CPU 에서 빨리 처리하게 하고, 램에 별도로 저장하거나 하는 일은 최소화시키는 것이 8051을 비롯한 마이크로프로세서 프로그래밍의 기본적인 자세다.
말이 옆으로 많이 샜다. ^^
어쨌거나 지금은 다시 내부램 영역과 sfr 이라는 것을 살펴봐야한다.
내부 램은 그렇게 많이 필요하지 않기에 일반적으로 128 byte 가 주어져있다. 8051에서 말이다.
우리가 쓰는 AT89S52 는 8051 패밀리면서도 또 약간의 부수적인 잇점들이 있는데 그중의 하나가 램이 8051보다 두배가 많다는게다 !!!
그러니까 256 byte !!!
256 바이트중에 우선 아래쪽에 있는 절반, 그러니까 8051과 공통적으로 있는 128바이트에 대해서 먼저 살펴보자.
램 128 바이트는 가장 바닥에 있는 첫번째 그룹, 바로 그 위에 있는 두번째 그룹, 마지막으로 나머지를 차지하는 세번째 그룹으로 나눌수 있다. 위에 있는 128바이트는 세번째 그룹에 자동적으로 포함된다.
무슨 말이냐고? 이제부터 잘 읽어내려가면 된다.
사실, 똑같은 글 두번쓰고 있는게다. 이거 처음에 다 썼는데, 갑자기 정전이 되었다. 세상에... 올해 처음 맞는 정전이었다. ㅜ.ㅜ
열심히 만들어 둔 글, 아깝다.... 시간도 많이 들었는데,... 그걸 다시 써야 하다니... ㅜ.ㅜ
그래서 이번에 계속 저장해가며 글쓴다. ㅜ.ㅜ 소잃고 외양간 고치는 격이지 뭐... ㅜ.ㅜ
자, 다시 램 으로 돌아가자.
1.######## 레지스트리 뱅크, 0x00 - 0x1F, 총 32 바이트
첫번째 그룹은 맨 아래쪽 8바이트 짜리 4개로 구성된다. 그러니까 1바이트가 8비트다. 1바이트짜리 8개가 모여서 하나의 단위를 형성하고, 그것이 4개 모인 것이 첫번째 그룹이다.
그림을 잘 보면 맨 아래쪽에 0x00 부터 0x1F 까지 32바이트의 공간이 있는 것을 볼수 있다. 32바이트는 4개의 8비트짜리 뱅크가 모인 것이다. 8비트짜리 뱅크는 각각 Bank0, Bank1, Bank2, Bank3 라는 이름을 가진다. 내부에는 R0 부터 R7 까지 8개의 레지스트가 있다. 이름은 4개 모두 같다. 그러니까 Bank0 에도 R0가 있고, Bank1, Bank2, Bnak3 에도 모두 R0 가 있다는게다. 이건 어떻게 쓰느냐면 ... 알아서 쓰면 된다... ^^;
지금은 설명하기 좀 그런데, 대충 레지스터중에 PSW 라는게 있다. 이것이 있는 위치가 0xD0 이다. 그러니까 0x7F 보다 위쪽에 있는게다. 램이 0x00 부터 0x7F 까지 128 바이트를 가진다고 했다. 그 위에 레지스트가 있다. 이 레지스트는 램과는 조금 다르다. 그러니까 램은 사용자 마음대로 읽고, 쓰고, 지지고 볶고 마음대로 할수 있는 영역이지만, 레지스트는 그렇지 않다. 조작할 수 있는 부분과 조작해서는 안되는 부분이 있다. 저절로 바뀌는 부분도 있다. PSW 는 0xD0 에 있는 레지스트인데, 이걸 건드리면 R0 를 선택할 때 Bank 의 선택을 가능하게 할수 있다. 그러니까, R0 에다가 0이라는 값을 넣고 싶다면,
MOVE R0 ,#0
이렇게 명령을 주면 된다. 그런데 이때 R0 가 대체 뭔가? 어디있는것인가? Bank0 인가? Bank1? 아니면? ??
이때 R0 가 어디 있는 것인지는 PSW(Program Status Word) 의 8비트중에 두개의 비트인 RS1, RS0(Register Select bit 1, Register Select bit 0)을 보면 된다.
RS1, RS0 = 0,0 ( Bank 0 선택, default Bank)
RS1, RS0 = 0,1 ( Bank 1 선택 )
RS1, RS0 = 1,0 ( Bank 2 선택 )
RS1, RS0 = 1,1 ( Bank 3 선택 )
비트를 바꾸는 방법은 CLR, SETB 명령을 쓰면 된다.
CLR RS1 ( => RS1 비트는 0이 됨)
SETB RS0 ( => RS0 비트는 1이 됨)
그럼 이제 두번째 집합을 보자..
2.######## 비트 단위 억세스 가능 영역(Bit Addressable space), 0x20 - 0x2F, 총 16 바이트, 개별적인 번지(0x00 - 0x7F)를 가진다.
레지스트리 뱅크 바로 위에 비트단위로 조작이 가능한 램의 영역이 있다. 이걸 어디에 쓸까? 이건 대체로 비트별로 조작을 해야 할 때, 그러니까 굳이 바이트단위로 조작하지 않아도 될때 사용한다. 그만큼 자원의 리소스를 적게 소모하므로 프로그램이 효율적으로 되는 것이다.
이 영역에 있는 것들은 개별적인 번지수를 가진다. 조금 이 부분이 특별하다. 그러니까 일반적인 번지수는 당연히 바이트단위로 되어 붙여진다. 0x01 그러면 당연히 1번지에 가서 거기 있는 녀석을 끄집어온다.(아니면 집어 넣는다) 그런데, 이때 명령어가 바이트단위로 처리하는 내용을 가진 명령어라면 당연히 집합1의 0x01 이라는 곳으로 가서 거기서 논다. 반면 명령어가 비트를 처리하는 녀석이라면, 그때 이 0x01 이라는 번지는 0x20 이라는 번지로 와서 거기서 두번째(첫번째는 0x00 이니까) 비트를 가지고 조작을 하는 것이다.
그러니까 대충 감을 잡았겠지.... 비트단위로 처리하는 명령어를 동반하는 어드레스는 다른 곳으로 가는게 아니라 0x20 에서 0x2F 사이에 있는 비트를 처리하는 것인게다. 그러니까 0x20 을 0x00 으로 하고, 0x2F 를 0x7F 로 하게 된다. 계산해보면 대충 알게다. 한바이트는 8개의 비트로 구성되는 것이니까, 16개의 바이트는 총 16*8 해서 128 비트로 구성되는 것이다. 128 이라는 수치는 램의 기본수치와 동일하다는 것도 알고 있겠지? ^^
SETB 0H
이 명령은 0번지에 1을 넣으라는 명령이다. 그런데 SETB 는 비트단위로 처리하는 명령이다. 다시말해서 CLR 은 0으로, SETB 는 1로 만들라는 소리다. 비트로 처리하는명령, 그러니까 여기서 0번지는 0x00 즉, Bank0 의 R0 가 있는 곳의 주소가 아니라, 0x20 의 첫번째 비트를 의미하는 것이다.
SETB 20H.0
마찬가지로 위와 같이 써도 된다.
그다음은
3.######## 일반 램 영역, 0x30 - 0x7F, 총 80바이트
일반 램 영역은 보통 스택영역으로 사용된다. 사실상 맨 아래쪽과 그 윗부분이 중요하고 이 나머지 부분은 그렇게까지 크게 소용이 되는 부분은 아니다. 물론 그렇다고 이게 없어도 된다는 것은 아니다. 별로 프로그램시에 크게 신경쓸 부분은 없다는 정도다. ^^
조금 신경쓸 부분은 스택영역을 정할때 앞에 언급했던 집합1, 2의 영역까지도 스택영역속에 집어 넣을 수 있다는 정도, 그리고 SP 레지스터가 관리하고, 만약 스택영역의 범위를 넘어서게 되면 곤란한 일이 발생할수 있다는 것 정도다.
SP 레지스터는 처음의 값부터 시작해서 스택이 하나씩 쌓여갈 때마다 1씩 증가한다. 스택이 하나씩 소거되면 역시 1씩 감소한다.
SFR (Special Function Register)
SFR 이란 것은 조금 특별한 레지스터라고 불리는 것들이다. 뭐가 특별한지는 잘 모르겠는데, 어쨌든 특별하다니까 특별대우를 해 주자. ^^
우선 이 녀석들이 사는 곳을 공개한다. ^^ 내부 램이 0x00 부터 0x7F 까지 128바이트가 걸쳐서 있었다. 바로 그 뒤에 이 SFR 이라는 녀석들이 살고 있다. 그러니까 0x80 부터 0xFF 까지 128 바이트에 걸쳐서 SFR 이 늘어져있다.
그러면 또 한가지 의문이 생긴다. 그러면 8052의 또 다른 램 영역, 0x80부터 0xFF 까지 128 바이트는 어디 간것인가?
그건 나도 잘 모르겠다. ^^
어쨌거나 대충 알수 있는 것은 SFR 이라는 녀석들과 램의 하위 부분이 동일한 주소번지를 가지고 있다는 것이다.
그러면 어떻게 램과 SFR 을 별도로 불러다 쓸수 있을까? ... 잘 하면 된다.. ^^
우선 8051 기본을 보자. 8051을 처음 만들었을때 아마도 8052 까지 염두에 두지는 않았을게다. 그래서 128 바이트의 램 영역 바로 위에 128 바이트의 SFR 영역을 두었다. 그런데 조금 시간이 지나서 램을 조금 더 늘리고 싶어졌다. 그래서 128 바이트의 램을 더 추가로집어 넣었다. 그런데, 이게 들어갈 자리를 못찾은게다. ㅜ.ㅜ
그래서 억지로집어 넣었다. 무슨 꽁수를 썼는가하면, SFR 과 똑같은 번지수를 가지되, 단 접근할때는 간접주소지정방식을 쓰도록 한다는 조건이었다.
그러니까 이제부터 0x80 부터 0xFF 까지 걸쳐있는 램도 쓸수있다. 어떻게? 간접주소지정방식을 사용해서 말이다.
간접주소지정방식이란 것은 혹시 C 를 했다면 포인터와 비슷한 개념이라고 보면 되겠다.
우선 직접주소지정방식은 이런 것이다.
mov 주소번지 or 레지스터 , #3<- 여기다 3을 넣어라.
mov B, #3
이러면 B 라는 레지스터 (주소번지는 0xF0 이다)에 3이라는 값이 저장된다.
간접주소지정방식은 이런 것이다.
mov 레지스터, 주소번지
mov @레지스터, 값
mov R0, #0F0H
mov @R0, #3
그러니까 R0 에다가 0xF0 를 넣는다. 0xF0 는 B레지스터의 주소번지다. 그 다음 줄의 @R0 는 R0에 담겨진 번지수를 찾아가서 거기에다가 3을 넣으라는 뜻이다. 그러면 당연히 R0 가 가지고 있는 값, 바로 0xF0 라는 값을 가진 주소번지를 찾아가서 거기에 3을 집어넣는 것이다. 이것이 바로 간접주소지정방식이다. 직접주소지정방식이나 간접주소지정방식이나 별 차이가 없어보이긴 한다. 하지만 여기서 SFR 은 원래 있던 것이니까 직접주소지정방식으로만 사용이 가능하고, 이런 식으로 간접주소지정방식을 쓰면 바로 램영역의 주소로 찾아가게 되는 것이다.
자, 그러면 어떻게 AT89S52 내부의 256 바이트의 램을 모두 쓸수 있는지, 또 번지수가 겹쳐진 SFR 영역도 어떻게 접근해서 쓸수 있는지 개략적으로 설명해 보았다.
나머지는 여기 있는 도표의 SFR 들을 살펴보는 것인데 ....
몇가지만 살펴보자. 나머지는 프로그램을 하면서 살펴보기로 하자.
Acc : 어큐물레이터, 아주 자주 쓰는 레지스터
B : B레지스터
SP : Stack Pointer
DPH,DPL : 마음데로 쓸 수있는 유일한 16bit 레지스터 DPTR의 상위 바이트(Data Pointer High)와 하위 바이트(Data Pointer Low)
P0,P1,P2,P3 : Port latch, 값을 쓰면 그 값이 각 포트의 출력 핀으로 나가고, 읽으면 핀으로 입력을 읽는 것이 되는 것
PSW : Program Status Word, C(carry) 비트와 레지스터 뱅크를 바꾸는데 사용하는 RS1,RS0 들어 있음
------ ------ ------ ------ ------ ------ ------ ------ F8H | | | | | | | | |FFH ------ ------ ------ ------ ------ ------ ------ ------ F0H | B | | | | | | | |F7H ------ ------ ------ ------ ------ ------ ------ ------ E8H | | | | | | | | |EFH ------ ------ ------ ------ ------ ------ ------ ------ E0H | ACC | | | | | | | |E7H ------ ------ ------ ------ ------ ------ ------ ------ D8H | | | | | | | | |DFH ------ ------ ------ ------ ------ ------ ------ ------ D0H | PSW | | | | | | | |D7H ------ ------ ------ ------ ------ ------ ------ ------ C8H | | | | | | | | |CFH ------ ------ ------ ------ ------ ------ ------ ------ C0H | | | | | | | | |C7H ------ ------ ------ ------ ------ ------ ------ ------ B8H | IP | | | | | | | |BFH ------ ------ ------ ------ ------ ------ ------ ------ B0H | P3 | | | | | | | |B7H ------ ------ ------ ------ ------ ------ ------ ------ A8H | IE | | | | | | | |AFH ------ ------ ------ ------ ------ ------ ------ ------ A0H | P2 | | | | | | | |A7H ------ ------ ------ ------ ------ ------ ------ ------ 98H | SCON | SBUF | | | | | | |9FH ------ ------ ------ ------ ------ ------ ------ ------ 90H | P1 | | | | | | | |97H ------ ------ ------ ------ ------ ------ ------ ------ 88H | TCON | TMOD | TL0 | TL1 | TH0 | TH1 | | |8FH ------ ------ ------ ------ ------ ------ ------ ------ 80H | P0 | SP | DPL | DPH | | | | PCON |87H ------ ------ ------ ------ ------ ------ ------ ------ . /| ( SFR map ) | |____ 이 칼럼이 0H 또는 8H로 끝나니까 bit accessable SFR
위에 있는 그림과 아래에 있는 것을 한번 잘 살펴봐라. 아래에 있는 것이 기본 8051 의 SFR 이고, 위에 있는 것은 AT89S52 의 SFR 이다. 약간 추가된 것들이 보인다. 추가된 기능을 한번 써보는 것도 괜찮을 게다. ^^
많이 피곤하다. 오늘 여기까지 하자..
가능하면 조금 빨리 설명같은 것을 끝내고 실제적인 프로그램을 하면서 하나씩 해나갔으면 하는 바램... ^^