serial쪽 드라이버를 다루는 법입니다.
시리얼 다루는 방법은 두가지가 있는데 하나는 canonical mode이고
하나는 non-canonical mode입니다.
전자는 enter가 들어오기전까지 버퍼링하는 것이고, 후자는 그냥 받는
즉시 읽을 수 있는 형태입니다.(맞나?...^^)
옛날에 장난으로 serial programming짰던걸 올려드립니다.
근데 돌아갈지는 장담못합니다. 원래 돌렸던게 어디있는지 못찾아서
다른 app에 넣었던거를 약간 수정본겁니다.
========================
/*
* non-canonical mode(한 문자단위 입력 모드) serial programming
* nocan.c를 수정 본 것.(driver형태로)
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
// for nocannew.c: serial communication
#include
#include
#include
// nocannew.c =========================
enum comport_number { COM1, COM2, COM3, COM4 };
int serial_open(int which_port); // return value = serial file descriptor
void serial_close(void);
int getch(void);
//#define BAUDRATE B38400 //baudrate setting
#define BAUDRATE B9600 //baudrate setting
#define _POSIX_SOURCE 1 // POSIX compliant source
struct termios oldtio, newtio; // for terminal attribute save & setting
int serial_fd; // serial port file descriptor
int serial_open(int which_port)
{
char *port_str;
switch(which_port)
{
case COM1:
port_str = "/dev/ttyS0";
break;
case COM2:
port_str = "/dev/ttyS1";
break;
case COM3:
port_str = "/dev/ttyS2";
break;
case COM4:
port_str = "/dev/ttyS3";
break;
default:
printf("input serial port error\n");
exit(EXIT_FAILURE);
}
serial_fd = open(port_str, O_RDWR | O_NOCTTY );
if( serial_fd < 0 )
{
printf("serial_port open error: %s\n", port_str);
return -1;
}
tcgetattr(serial_fd,&oldtio); // 현재 설정을 oldtio에 저장
bzero(&newtio, sizeof(newtio));
//newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD; // 흐름제어 없음
newtio.c_iflag = IGNPAR;
//newtio.c_iflag = IGNPAR|ICRNL;
#if 0 // raw output
newtio.c_oflag &= ~OPOST;
#endif
// preprocessing output: 즉 output하기 전에 어떤 처리를 해서 ouput을 한다.
newtio.c_oflag |= OPOST; // post processing enable
newtio.c_oflag |= ONLCR; // 유닉스 용의 newline(NL:'\n')을 dos용의 newline인
// CR-NL('\r'\'n')으로 자동 전환 옵션
// set input mode (non-canonical, no echo,...)
//newtio.c_lflag = 0;
newtio.c_lflag &= ~(ICANON|ECHO|ECHOE|ISIG);
newtio.c_cc[VTIME] = 0; // 문자 사이의 timer를 disable
newtio.c_cc[VMIN] = 1; // 최소 5 문자 받을 때까진 blocking
tcflush(serial_fd, TCIFLUSH);
tcsetattr(serial_fd,TCSANOW,&newtio);
return 0;
}
void serial_close(void)
{
// 원래의 attribute로 돌려 놓는다.
tcsetattr(serial_fd, TCSANOW, &oldtio);
close(serial_fd);
}
void gprintf(char *fmt,...)
{
char buf[512];
int ret;
va_list ap;
va_start(ap,fmt);
vsprintf(buf, fmt, ap);
va_end(ap);
ret = write(serial_fd, (void *)buf, strlen(buf));
if( ret < 0 )
{
printf("serial write error: %s\n", strerror(errno));
}
}
int getch(void)
{
int read_bytes;
unsigned char buf;
read_bytes = read(serial_fd, &buf, 1); // 1 문자를 받으면 리턴
if( read_bytes > 0 )
return (int)buf;
if( (read_bytes < 0) && (errno != EINTR) && (errno != EAGAIN) )
return -1;
return -1;
}
#if 1
int main(void)
{
int i = 10, ch;
serial_open(COM2);
while(i--)
{
gprintf("serial_print: %d\n", i);
}
ch = getch();
printf("ch = %d\n", ch);
gprintf("ch = %d\n", ch);
serial_close();
}
#endif