Universal asynchronous receiver-transmitter
UART(범용 비동기화 송수신기: Universal asynchronous receiver/transmitter)는 병렬 데이터의 형태를 직렬 방식으로 전환하여 데이터를 전송하는 컴퓨터 하드웨어의 일종이다. UART는 일반적으로 EIA RS-232, RS-422, RS-485와 같은 통신 표준과 함께 사용한다. UART의 U는 범용을 가리키는데 이는 자료 형태나 전송 속도를 직접 구성할 수 있고 실제 전기 신호 수준과 방식(이를테면 차분 신호)이 일반적으로 UART 바깥의 특정한 드라이버 회로를 통해 관리를 받는다는 뜻이다.
통신 데이터는 메모리 또는 레지스터에 들어 있어 이것을 차례대로 읽어 직렬화 하여 통신한다. 최대 8비트가 기본 단위이다.
UART는 일반적으로 컴퓨터나 주변 기기의 일종으로 병렬 데이터를 직렬화 하여 통신하는 개별 집적 회로이다. 비동기 통신이므로 동기 신호가 전달되지 않는다. 따라서 수신 쪽에서 동기신호를 찾아내어 데이터의 시작과 끝을 시간적으로 알아 처리할 수 있도록 약속되어 있다. 디지털 회로는 자체의 클럭 신호를 사용하여 정해진 속도로 수신 데이터로 부터 비트 구간을 구분하고 그 비트의 논리 상태를 결정하여 데이터 통신을 한다.
UART는 보통 마이크로컨트롤러에도 포함되어 있다. 듀얼 UART, 곧 DUART는 두 개의 UART를 하나의 칩에 합친 것이다. 수많은 현대의 집적 회로(IC)는 동기화 통신도 지원하는 UART와 함께한다. 이러한 장치들은 USARTs(범용 동기화 송수신기: universal synchronous/asynchronous receiver/transmitter)로 부른다.
Example
#include <termios.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/signal.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <errno.h>
int transfer_byte(int from, int to, int is_control);
typedef struct {char *name; int flag; } speed_spec;
void print_status(int fd) {
int status;
unsigned int arg;
status = ioctl(fd, TIOCMGET, &arg);
fprintf(stderr, "[STATUS]: ");
if(arg & TIOCM_RTS) fprintf(stderr, "RTS ");
if(arg & TIOCM_CTS) fprintf(stderr, "CTS ");
if(arg & TIOCM_DSR) fprintf(stderr, "DSR ");
if(arg & TIOCM_CAR) fprintf(stderr, "DCD ");
if(arg & TIOCM_DTR) fprintf(stderr, "DTR ");
if(arg & TIOCM_RNG) fprintf(stderr, "RI ");
fprintf(stderr, "\r\n");
}
int main(int argc, char *argv[])
{
int comfd;
struct termios oldtio, newtio; //place for old and new port settings for serial port
struct termios oldkey, newkey; //place tor old and new port settings for keyboard teletype
char *devicename = argv[1];
int need_exit = 0;
speed_spec speeds[] =
{
{"1200", B1200},
{"2400", B2400},
{"4800", B4800},
{"9600", B9600},
{"19200", B19200},
{"38400", B38400},
{"57600", B57600},
{"115200", B115200},
{NULL, 0}
};
int speed = B9600;
if(argc < 2) {
fprintf(stderr, "example: %s /dev/ttyS0 [115200]\n", argv[0]);
exit(1);
}
comfd = open(devicename, O_RDWR | O_NOCTTY | O_NONBLOCK);
if (comfd < 0)
{
perror(devicename);
exit(-1);
}
if(argc > 2) {
speed_spec *s;
for(s = speeds; s->name; s++) {
if(strcmp(s->name, argv[2]) == 0) {
speed = s->flag;
fprintf(stderr, "setting speed %s\n", s->name);
break;
}
}
}
fprintf(stderr, "C-a exit, C-x modem lines status\n");
tcgetattr(STDIN_FILENO,&oldkey);
newkey.c_cflag = B9600 | CRTSCTS | CS8 | CLOCAL | CREAD;
newkey.c_iflag = IGNPAR;
newkey.c_oflag = 0;
newkey.c_lflag = 0;
newkey.c_cc[VMIN]=1;
newkey.c_cc[VTIME]=0;
tcflush(STDIN_FILENO, TCIFLUSH);
tcsetattr(STDIN_FILENO,TCSANOW,&newkey);
tcgetattr(comfd,&oldtio); // save current port settings
newtio.c_cflag = speed | CS8 | CLOCAL | CREAD;
newtio.c_iflag = IGNPAR;
newtio.c_oflag = 0;
newtio.c_lflag = 0;
newtio.c_cc[VMIN]=1;
newtio.c_cc[VTIME]=0;
tcflush(comfd, TCIFLUSH);
tcsetattr(comfd,TCSANOW,&newtio);
print_status(comfd);
while(!need_exit) {
fd_set fds;
int ret;
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
FD_SET(comfd, &fds);
ret = select(comfd+1, &fds, NULL, NULL, NULL);
if(ret == -1) {
perror("select");
} else if (ret > 0) {
if(FD_ISSET(STDIN_FILENO, &fds)) {
need_exit = transfer_byte(STDIN_FILENO, comfd, 1);
}
if(FD_ISSET(comfd, &fds)) {
need_exit = transfer_byte(comfd, STDIN_FILENO, 0);
}
}
}
tcsetattr(comfd,TCSANOW,&oldtio);
tcsetattr(STDIN_FILENO,TCSANOW,&oldkey);
close(comfd);
return 0;
}
int transfer_byte(int from, int to, int is_control) {
char c;
int ret;
do {
ret = read(from, &c, 1);
} while (ret < 0 && errno == EINTR);
if(ret == 1) {
if(is_control) {
if(c == '\x01') { // C-a
return -1;
} else if(c == '\x18') { // C-x
print_status(to);
return 0;
}
}
while(write(to, &c, 1) == -1) {
if(errno!=EAGAIN && errno!=EINTR) { perror("write failed"); break; }
}
} else {
fprintf(stderr, "\nnothing to read. probably port disconnected.\n");
return -2;
}
return 0;
}