C언어 환경에서 wiringPi 라이브러리로 간단한 시리얼 통신을 구현해봅니다.
wiringPi 라이브러리 설치
C언어 wiringPi 라이브러리로 간단하게 시리얼 통신을 구현하는 방법을 알아보겠습니다. Ubuntu 환경에서 개발을 진행합니다. wiringPi 라이브러리가 아직 설치되지 않았다면 아래의 블로그 글 도움을 받아 설치하시면 됩니다.
설치가 완료되었으면 아래의 명령으로 설치가 잘 되었는지 확인해보면 됩니다.
$ gpio readall
시리얼 통신 구현
먼저 필요로 하는 헤더파일들을 불러옵니다.
#include <stdio.h>
#include <stdlib.h> // exit()
#include <wiringPi.h>
#include <wiringSerial.h>
특징적으로, wiringPi에서 시리얼 통신을 구현할 때는 wiringSerial.h
헤더 파일을 불러와줘야 됩니다.
그 후 보드레이트(Baud rate)와 연결된 USB to Serial 장치를 설정합니다.
#define baudrate 19200
char * device = "/dev/ttyUSB0"
OS에 연결된 시리얼 장치의 이름은 장치를 연결한 후 아래의 명령들로 확인할 수 있습니다.
$ dmesg | grep tty
$ dmesg | tail
이제 main 함수 내에서 시리얼 포트를 엽니다.
int main(void){
int serial; // serial 장치 디스크립터
unsigned long time = 0; // 통신 Delay 시간
if((serial = serialOpen(device, baudrate)) < 0){ // 시리얼 포트 오픈 실패시
perror("serialOpen");
exit(1);
}
if(wiringPiSetup() == -1){ // wiringPi 초기화 실패시
perror("wiringPiSetup");
exit(1);
}
// 이하에서 통신 진행
serial
변수는 오픈된 시리얼 포트를 의미하는 디스크립터 변수입니다. serialOpen
함수를 이용해서 시리얼 포트를 열어주고 있습니다. serialOpen
함수는 지정해준 디바이스로 시리얼 포트를 잘 열면 시리얼 디스크립터를 반환해 주고, 못 열면 음수를 반환합니다. 위의 코드는 음수가 반환된 경우 에러로 간주하고 메시지 출력 후 종료하고 있습니다.
그리고 wiringPi의 초기화를 진행합니다. wiringPiSetup()
함수도 실패하면 -1을 반환하므로, 그것을 캐치해서 에러를 처리해줍니다.
이렇게 초기 설정이 끝나면, 아래처럼 통신을 진행합니다. 위의 코드를 이어서 작성합니다.
while(1){
if(millis() - time >= 1000){ // 마지막 문자를 전송한 시간 이후 1초 경과시
serialPutchar(serial, 'A'); // 'A' 문자를 오픈된 시리얼 포트로 전송
time = millis(); // 방금 문자를 전송한 시간을 기억
}
if(serialDataAvail(serial)){ // 시리얼 포트에서 읽어올 데이터가 있으면
printf("%c", serialGetchar(serial)); // 포트에서 읽어와서 출력
fflush(stdout); // 표준 출력 스트림을 비우고, 화면에 출력
}
}
}
주요하게 세 가지 함수를 사용하고 있습니다. serialPutchar()
함수를 이용해서 한 바이트를 전송하고 있고, serialGetchar()
함수를 사용해서 한 바이트를 읽어오고 있습니다. 그리고 읽을 데이터가 있는지 확인은 serialDataAvail()
함수로 하는 것을 볼 수 있습니다.
문자열 단위로 데이터를 전송하려면, serialPuts()
함수를 이용합니다.
serialPuts(serial, "MagmaTart");