Linux Serial 통신의 모습
가상 Linux의 가상 포트와 Windows의 실제 포트와 매칭을 시킨 후 Hyper Terminal과 연결된 포트와 연결시키면 Linux에서 보내는 데이터를 Hyper Terminal에 나타나게 된다.
가상의 Linux에 Serial 포트 추가 방법
1. 가상 Linux를 종료한다.
2. 설정에 들어간다.
3. 하드웨어에서 추가를 누른다.
4. Serial Port 선택 후 다음을 누른다.
5. Use physical serial port on the host를 선택 후 다음을 누른다.
6. 물리적 시리얼 포트를 Auto Detect로 선택한 후 종료한다.
위와 같은 방법으로 필요한 만큼의 시리얼 포트를 추가해준다.
Linux Serial 통신에는 여러가지가 있는데 Canonical, Non-Canonical, Asynchronous, Multi Flexing의 방식이 있다.
Canonical
터미널의 기본 처리 방법이며 한 줄 단위로 통신을 한다.
한 줄이란 의미는 New Line, End Of File, End Of Line으로 구분이 된다.
#include <stdio.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/stat.h>
// 속도의 설정은 숫자만 적는게 아니고 B를 꼭 입력해야지만 Define값이 적용된다.
#define SPEED B19200
// 사용할 Port의 위치 지정
#define SPORT "/dev/ttyS9"
int main() {
int iDev = 0;
int iRet = 0;
// 수신용 버퍼
char cBuff[255];
// 원본값 복사를 위해서 Old, New가 존재
struct termios ST_OldState;
struct termios ST_NewState;
// Serial Port Open
// O_NOCTTY는 제어문자를 현재 프로그램 내에서만 적용하라는 의미
iDev = open(SPORT, O_RDWR | O_NOCTTY);
// Open 오류 검사
if (iDev < 0) {
perror(SPORT);
exit(-100);
}
// 현재 Serial Port 상태 저장
// TC - Terminer Control
// Terminer Control 백업을 위해서 Get 한다.
tcgetattr(iDev, &ST_OldState);
// 구조체 초기화
bzero(&ST_NewState, sizeof(ST_NewState));
// Control Flag
// SPEED : 전송속도, cfsetispeed(), cfsetospeed()로도 설정가능
// CS8 : 8N1 (8Bit, No Parity, 1 Stop Bit)
// CLOCAL : Local Connection. 제어를 하지 않음
// CREAD : 문자 수신 가능
ST_NewState.c_cflag = SPEED | CRTSCTS | CS8 | CLOCAL | CREAD;
// Input Flag
//IGNPAR : Parity Error가 있는 문자 Byte 무시
// ICRNL : CR 문자를 NL 문자로 변환 처리
ST_NewState.c_iflag = IGNPAR | ICRNL;
// Output Flag
// 수신된 데이터 그대로 출력
ST_OldState.c_oflag = 0;
// Canonical 통신 기법 사용
ST_NewState.c_lflag = ICANON;
// 제어문자 초기화
bzero(ST_NewState.c_cc, NCCS);
// Read시 Return되기 위한 최소 문자 개수 지정
ST_NewState.c_cc[VMIN] = 1;
// Serial Port 수신 Queue 초기화
tcflush(iDev, TCIFLUSH);
// Serial Port에 새 속성 적용
tcsetattr(iDev, TCSANOW, &ST_NewState);
// Data가 1개 이상이되지 않으면 Blocking
// Serial Port로부터 데이터 수신
iRet = read(iDev, cBuff, 255);
cBuff[iRet] = 0;
printf("[%s] : [%d]\n", cBuff, iRet);
// Serial Port의 원래 속성의 복귀
tcsetattr(iDev, TCSANOW, &ST_OldState);
// Serial Port Close
close(iDev);
return 0;
}
Non-Canonical
한 번에 정해진 크기의 데이터만 읽어 들인다.
타이머의 사용이 가능하다.
Asynchronous
read의 조건이 만족될 때까지 Blocking 되는 방식이다.
호출한 프로그램에게 Signal을 전송한다.
전송된 Signal은 Signal Handler로 처리가 된다.
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/signal.h>
#define SPEED B19200
#define SPORT "/dev/ttyS1"
volatile int iBreak = 0;
void Handle_Serial_Sig(int);
int main() {
// 장치 Description
int iDev = 0;
// Return Value
int iRet = 0;
// 수신용 버퍼
char cBuff[255];
// 기존 Serial Port 상태 정보
struct termios ST_OldState;
// 새로운 Serial Port 상태 정보
struct termios ST_NewState;
// Signal Action 설정 (Software Interrupt 방식)
struct sigaction ST_SigAct;
// Serial Port Open
iDev = open(SPORT, O_RDWR | O_NOCTTY | O_NONBLOCK);
if (iDev < 0) {
perror(SPORT);
exit(-100);
}
// Serial Port 설정 전 Signal Handler 등록
// Interrupt가 발생 할때마다 Handle_Serial_Sig 함수 호출
bzero(&ST_SigAct, sizeof(ST_SigAct));
ST_SigAct.sa_handler = Handle_Serial_Sig;
sigaction(SIGIO, &ST_SigAct, NULL);
// SIGIO Signal 수신 설정
// GETID() : 현재 실행중인 프로그램의 번호
fcntl(iDev, F_SETOWN, getpid());
// File Description 비동기 설정
fcntl(iDev, F_SETFL, FASYNC);
// 현재 Serial Port 상태 저장
tcgetattr(iDev, &ST_OldState);
// 구조체 초기화
bzero(&ST_NewState, sizeof(ST_NewState));
// SPEED : 전송속도, cfsetispeed(), cfsetospeed()로도 설정가능
// CS8 : 8N1 (8Bit, No Parity, 1 Stop Bit)
// CLOCAL : Local Connection. 제어를 하지 않음
// CREAD : 문자 수신 가능
ST_NewState.c_cflag = SPEED | CRTSCTS | CS8 | CLOCAL | CREAD;
//IGNPAR : Parity Error가 있는 문자 Byte 무시
// ICRNL : CR 문자를 NL 문자로 변환 처리
ST_NewState.c_iflag = IGNPAR | ICRNL;
// 수신된 데이터 그대로 출력
ST_OldState.c_oflag = 0;
// Canonical 통신 기법 사용
ST_NewState.c_lflag = ICANON;
// Read시 Return되기 위한 최소 문자 개수 지정
ST_NewState.c_cc[VMIN] = 1;
ST_NewState.c_cc[VTIME] = 0;
// Serial Port 수신 Queue 초기화
tcflush(iDev, TCIFLUSH);
// Serial Port에 새 속성 적용
tcsetattr(iDev, TCSANOW, &ST_NewState);
while (1) {
if (iBreak == 1) {
// Serial Port로 데이터 수신
iRet = read(iDev, cBuff, 255);
cBuff[iRet] = 0;
printf("[%s] : [%d]\n", cBuff, iRet);
break;
}
else {
sleep(2);
}
printf("Go Sleep\n");
}
tcsetattr(iDev, TCSANOW, &ST_OldState);
close(iDev);
return 0;
}
void Handle_Serial_Sig(int Arg) {
printf("Receive SIGIO Signal\n");
iBreak = 1;
}
Multi Flexing
여러 개의 장치들을 다루고자 할 때 유용하다.
Select() 사용방식과 같다.
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <sys/time.h>
#include <sys/types.h>
#define SPEED B19200
#define COMPORT1 "/dev/ttyS0"
#define COMPORT2 "/dev/ttyS1"
char cBuff[255];
void Input_Incomming(int);
int main() {
int iMaxFD = 0;
int iCom1 = 0;
int iCom2 = 0;
struct termios ST_OldST1;
struct termios ST_OldST2;
struct termios ST_NewST1;
struct termios ST_NewST2;
// File Descriptor Set
fd_set ST_RFD;
iCom1 = open(COMPORT1, O_RDWR | O_NOCTTY);
if (iCom1 < 0) {
perror(COMPORT1);
exit(-1);
}
iCom2 = open(COMPORT2, O_RDWR | O_NOCTTY);
if (iCom2 < 0) {
perror(COMPORT2);
exit(-1);
}
tcgetattr(iCom1, &ST_OldST1);
tcgetattr(iCom2, &ST_OldST2);
bzero(&ST_NewST1, sizeof(ST_NewST1));
ST_NewST1.c_cflag = SPEED | CRTSCTS | CS8 | CLOCAL | CREAD;
ST_NewST1.c_iflag = IGNPAR | ICRNL;
ST_NewST1.c_oflag = 0;
// Blocking Read Until 1 Charactor Arrives;
ST_NewST1.c_cc[VMIN] = 1;
ST_NewST2 = ST_NewST1;
tcflush(iCom1, TCIFLUSH);
tcsetattr(iCom1, TCSANOW, &ST_NewST1);
tcflush(iCom2, TCIFLUSH);
tcsetattr(iCom1, TCSANOW, &ST_NewST2);
iMaxFD = iCom2 + 1;
tcsetattr(iCom1, TCSANOW, &ST_OldST1);
tcsetattr(iCom2, TCSANOW, &ST_OldST2);
close(iCom1);
close(iCom2);
return 0;
}
void Input_Incomming(int iPort) {
int iRet = read(iPort, cBuff, 255);
cBuff[iRet] = 0;
printf("[%s] : [%d]\n", cBuff, iRet);
}
'코스웨어 > 15년 스마트컨트롤러' 카테고리의 다른 글
20151208-김재홍-Serial_2일차-RFID_리눅스_CRC (2) | 2015.12.08 |
---|---|
20151207 / 리눅스 시리얼 통신_남수진 (2) | 2015.12.08 |
20151207 리눅스 시리얼 통신 이량경_ (4) | 2015.12.08 |
20151207 임현수 업무일지 리눅스 시리얼통신 (4) | 2015.12.08 |
20151207 윤재희 리눅스 시리얼 통신 (5) | 2015.12.07 |
20151207 - 홍준모 Linux 와 Window 간의 시리얼 통신 1일차, 케노니칼, 논 케노니칼 실습 (4) | 2015.12.07 |
20151207 일일업무보고서_박서연_LinuxSerial통신 (6) | 2015.12.07 |
20151207 - 엄민웅 시리얼 통신 Canonical, Non-Canonical, Asynchronous, Multi Flexing (4) | 2015.12.07 |