(Universal Asynchronous Receiver/Transmitter) | |||||||||||||||||||||||||||||
병렬 제어기 또는 데이타 단말기의 단어를 순서적인 비트 통신망에 접속시키는 장치. 수신기는 송신된 단어의 시작에 원하는 수의 개시 비트를 넣고 끝에 종료 비트를 넣어 입력된 직렬 데이타를 병렬 데이터로 출력시킨다. 패리티 비트도 삽입될 수 있다. 데이타는 전송 데이타 클록에 의하여 정해진 보율 (baud rate) 로 전송된다. 수신기 부분은 순서적인 데이타의 개시 비트의 정당성을 체크하고 입력 데이타를 병렬 단어로 출력시킨다. 수신기는 패리티와 오버런 오류를 체크한다. | |||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||
Register | |||||||||||||||||||||||||||||
레지스터 0 - 수신 버퍼 레지스터(RHR:Receiver Holding Register) | |||||||||||||||||||||||||||||
한 문자의 데이터가 16550 UART의 수신 버퍼 레지스터(RBR)에서 조합이 된다. 수신 버퍼 레지스터는 이 UART의 첫 번째 레지스터로서, 직렬 포트의 기본 레지스터 포트를 읽어서 주소가 지정된다. 수신 버퍼 레지스터는 항상 8비트 값이 들어 있지만 한 문자당 8비트 미만을 사용하는 데이터 링크에서는 사용되지 않는 비트가 나타나지 않도록 주의해야 한다. | |||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||
레지스터 0 - 전송 대기 레지스터(THR:Transmitter Holding Register) | |||||||||||||||||||||||||||||
이 UART의 전송 대기 레지스터(THR)는 직렬 인터페이스를 통해 한 문자의 데이터를 전송하는 데 사용된다. 이것은 이 UART의 첫 번째 레지스터를 수신 버퍼 레지스터(RBR)와 함께 사용하며, 해당 직렬 포트의 기본 레지스터 포트에 기록함으로써 주소가 지정된다. | |||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||
레지스터 1 - 인터럽트 가능 레지스터(IER:Interrupt Enable Register) | |||||||||||||||||||||||||||||
이 UART의 인터럽트 가능 레지스터(IER)는 인터럽트를 가능하게 하는 데 사용된다. 이 것은 직렬 포트의 기본 레지스터 포트 + 1번지에서 읽거나 씀으로써 주소가 지정된다. | |||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||
레지스터 2 - 인터럽트 인식 레지스터(IIR:Interrupt Identification Register) | |||||||||||||||||||||||||||||
이 UART의 인터럽트 인식 레지스터(IIR)는 인터럽트가 발생했는지의 여부와 FIFO 버퍼가 사용 가능한지의 여부를 판단하는 데 사용된다. 이것은 직렬 포트의 기본 레지스터 포트 + 2번지부터 읽어서 주소가 지정된다. | |||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||
레지스터 2 - FIFO 제어 레지스터(FCR:FIFO Control Register) | |||||||||||||||||||||||||||||
이 UART의 FIFO 제어 레지스터(FCR)는 FIFO 버퍼를 제어하는 데 사용된다. 이것은 직렬 포트의 기본 레지스터 포트 + 2번지에 기록함으로써 주소가 지정된다. | |||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||
레지스터 3 - 라인 제어 레지스터(LCR:Line Status Register) | |||||||||||||||||||||||||||||
이 UART의 라인 제어 레지스터(LCR)는 데이터 비트의 수, 정지 비트의 수, 패리티 세팅 등을 지정하는 데 사용된다. 이것은 직렬 포트의 기본 레지스터 + 3번지부터 읽거나 씀으로써 주소가 지정된다. | |||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||
레지스터 4 - 모뎀 제어 레지스터(MCR:Modem Control Register) | |||||||||||||||||||||||||||||
이 UART의 모뎀 제어 레지스터(MCR)는 RTS(Request To Send) 라인이나 DTR(Data Terminal Ready) 라인을 세트하거나 이 UART를 인터럽트 가능으로 세트하는 등에 사용된다. 이것은 직렬 포트의 기본 레지스터 + 4번지부터 읽거나 씀으로써 주소가 지정된다. | |||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||
라인 상태 레지스터(LSR:Line Status Register) | |||||||||||||||||||||||||||||
이 UART의 라인 상태 레지스터(LSR)는 수신된 데이터의 유효성, 에러, 그리고 데이터 전송 완료 등을 보고하는 데 사용된다. 이것은 직렬 포트의 기본 레지스터 + 5번지부터 읽음으로써 주소가 지정된다. | |||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||
모뎀 상태 레지스터(MSR:Modem Status Register) | |||||||||||||||||||||||||||||
이 UART의 모뎀 상태 레지스터(MSR)는 전화 신호가 들어오거나 캐리어가 있을 때 CTS(전송 해제)와 DSR(데이터 세트 준비 완료) 라인의 현재 상태 등을 보고하는 데 사용된다. 이것은 직렬 포트의 기본 레지스터 + 6번지부터 읽음으로써 주소가 지정된다. | |||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||
레지스터 7 - 스크래치 패드(Scratch Register) | |||||||||||||||||||||||||||||
이 레지스터는 16550 UART에서는 사용되지 않으며 8250 UART의 전체 버전에 존재하지도 않는다. 따라서 무시하는 것이 좋다. | |||||||||||||||||||||||||||||
레지스터 8 - DLL:Divisor Latch(보드율 제수 하위 래치 레지스터) | |||||||||||||||||||||||||||||
이 UART의 DLL(보드율 제수 하위 래치 레지스터)은 이 UART 보드율 제수의 하위 바이트를 세트하는 데 사용된다. 이 레지스터에서 읽고 쓰려면 우선 라인 제어 레지스터(LCR)의 DLAB(Divisor Latch Access Bit) 비트를 1로 세트해 두어야 한다. 즉, DLAB 비트를 1로 세트하면 DLL은 그 직렬 포트의 기본 레지스터에서 읽고 씀으로써 주소가 지정된다. 이 UART의 보드율 제수는 단순히 115,200을 원하는 보드율을 나눔으로써 계산된다. 그리고 그 결과의 하위 8비트가 DLL에 놓이게 된다. | |||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||
레지스터 9 - 보드율 제수 상위 래치 레지스터(DLM) | |||||||||||||||||||||||||||||
이 UART의 DLM(보드율 제수 상위 래치 레지스터)은 이 UART 보드율 제수의 상위 바이트를 세트하는 데 사용된다. 이 레지스터에서 읽고 쓰려면 우선 라인 제어 레지스터(LCR)의 DLAB(Divisor Latch Access Bit) 비트를 1로 세트해 두어야 한다. 즉 DLAB 비트를 1로 세트하면 DLM은 그 직렬 포트의 기본 레지스터 + 1번지에서 읽고 씀으로써 주소가 지정된다. 이 UART의 보드율 제수는 단순히 115,200을 원하는 보드율로 나눔으로써 계산된다. 그리고 그 결과의 상위 8비트가 DLM에 놓이게 된다. | |||||||||||||||||||||||||||||
|
(Universal Asynchronous Receiver/Transmitter) |
FIFO(First In First Out) |
UART의 속도와 CPU 속도는 큰 차이를 내기 때문에 UART쪽에 FIFO라는 buffer을 내장해서 CPU의 부담을 덜도록 설계했다. 16450은 FIFO가 없고, 16550은 FIFO가 있다. 총 16 바이트의 버퍼가 있으나, 2개는 예비 버퍼로 활용하고 있고, FIFO의 총 가능 버퍼는 14byte 이다. FIFO Control Register 에서 제어한다. |
16550 초기화(Initialization) |
1. Line Control Register(LCR)의 7비트(DLAB)를 1로 세트 |
16C550 UART Register 요약본 |
1. Line Status Register (0. 수신 1. over run 2. parity error 3. framing error. 4. break 5. THR->shifr 6. THR, FIFO empty 7. FIFO error ) 2. Line Control Register (0-1. 비트 데이터 1. 정비 비트 3-5. parity 비트 지정 6. break 7. DLAB = 1(분주율)) 3. Modem Status Register (델타 0. CTS 1. DSR 2. RI 3. DCD 보통 4. CTS 5. DSR 6. RI 7. DCD ) 4. Modem Control Register (0. DTR 1. RTS 2. GP01(모뎀 리셋) 3. GP02(인터럽트) 4. loopback 5-7. 0 ) 5. Interrupt Identification Register (0. 인터럽트0 1-3. MSR, THR empty, Trigger lovel 도달, over run외3 4-5. 0 6-7. 1 1 FIFO ) 6. Interrupt Enable Register (0. Trigger level 1. THE->shift 2. over run외3 3. MSR 4-7. 0) 7. FIFO Control Register (0. FIFO 1 1. 수신 FIFO 0 2. 송신 FIFO 0 3. DMA 0 4-5. 예약 6-7. FIFO 수신 경계) |
프로그램 소스 |
UART와 RS232C 통신하는 프로그램 소스를 여기에 싫도록 하겠다. Interrupt 방식이 아닌, polling 방식이다. 컴파일러는 볼랜드 C++ 3.1 이다. 도스용이다. // programming by Oh, Seong-Min. #include "stdio.h" #include "conio.h" #define COM1_BASE 0x03F8 #define DLAB 0x00 #define LCR 0x03 #defineLCR_8_DB 0x03 #define LCR_NO_PARITY 0x00 #define LCR_1_STOP 0x00 #define LSR 0x05 #define LSR_0_MASK 0x01 //LSR 0's bit Masking int rl, tl, rt, tt; // rt=receive top, tt=transmitte top char port_read, port_write; void receive_port(); void transmitte_port(); void clear_screen(); void main() { outportb( (COM1_BASE + LCR), 0x80); //set DLAB=1 outport( (COM1_BASE + DLAB), 12); //set 9600 baud // set none, 8, 1 outportb((COM1_BASE + LCR),(LCR_8_DB|LCR_NO_PARITY|LCR_1_STOP)); inport(COM1_BASE + LSR); clrscr(); printf("\n\t========================================================"); printf("\n\t This is a receiver & transmitter Test program for UART."); printf("\n\t=========================================================\n"); gotoxy(1,7); printf("\n<- Transmitte start!!\n"); gotoxy(1,16); printf("\n<- Receive start!!\n"); rl = tl = 1; rt = 18; tt = 9; while(1) { receive_port(); transmitte_port(); // ESC - halt program if (port_write == 27) { printf("\n\n=== Thank you for test. Good bye!! ==="); break; } } } void receive_port() { while((inport(COM1_BASE + LSR) & LSR_0_MASK) == 1) { port_read=inport(COM1_BASE); gotoxy(rl,rt); if (port_read == 13) { clear_screen(); rl=0; rt=18; } putch(port_read); rl++; if (rl > 80) { rl=1; rt++; } if (rt > 21) { rl=1; rt=18; } } } void transmitte_port() { if (kbhit()) { port_write = getche(); if (port_write == 13) { clear_screen(); tl=0; tt=9; } outportb( (COM1_BASE), port_write ); tl++; if (tl>80) { tl=1; tt++; } if (tt>12) { tl=1; tt=9; } } } void clear_screen() { clrscr(); gotoxy(1,1); printf("\n\t\t------------------------------------------"); printf("\n\t\t\tPress ""ESC"" for halt program."); printf("\n\t\t------------------------------------------"); gotoxy(1,7); printf("\n<- Transmitte start!!\n"); gotoxy(1,16); printf("\n<- Receive start!!\n"); }
// End the source program. |
[출처:http://blog.naver.com/woosung807/10133730]