출처 : http://god10276.tistory.com/entry/QT%EB%A1%9C-Serial-%ED%86%B5%EC%8B%A0-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0-1
QT로 Serial 통신을 구현하려고 한다.
앞서 기본적으로 QT Creator 를 이용하여 Form을 생성하는 방법과 Button Event 등 Event 함수 등을 설정하는 방법 등에 대해서 기술하였다. 이번에는 실제 Serial 통신은 어떤 식으로 구현하는지 알아보자.
먼저 Window와 다르게 Linux는 /dev/ttyS0 -> COM1 , /dev/ttyS1 -> COM2 .... 이런 식으로 구성되고, USB to Serial 같은 경우에는 /dev/ttyUSB0 이런식으로 구분되기 때문에 따로따로 기술해 주어야 한다. 그래서 다음과 같이 정의했다.
#define DEVICE01 "/dev/ttyS0"
#define DEVICE02 "/dev/ttyS1"
#define DEVICE03 "/dev/ttyS2"
#define DEVICE04 "/dev/ttyUSB0"
#define DEVICE05 "/dev/ttyUSB1"
이런 식으로 정의하여서 사용자가 선택한 Device 장비로 Setting 될 수 있도록 하였다.
또한, BAUDRATE 같은 경우에는 <asm/termbits.h>에 정의되어 있는데 이것은 <termios.h>에 include 된다. 그러므로, <termios.h> Header File 만 Include 해 주면 된다.
역시 편리하게 하기 위해 다음과 같은 방법으로 정의해 두었다.
#define BAUDRATE1200 B1200
#define BAUDRATE2400 B2400
#define BAUDRATE4800 B4800
#define BAUDRATE9600 B9600
#define BAUDRATE14400 B14400
#define BAUDRATE19200 B19200
#define BAUDRATE38400 B38400
#define BAUDRATE56000 B56000
#define BAUDRATE57600 B57600
#define BAUDRATE115200 B115200
기본적으로 Serial 통신을 위해 추가해 준 Header File은 다음과 같다.
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>
이제 본격적인 UI 구성으로 들어가 보자.
그냥 단순하게, Terminal 창 만을 나타낼 수 있도록 구성하였다. 앞부분에서 COM Port를 설정하고 뒷 부분에서 BAUDRATE를 설정한 후에 Connect를 하면 정상적으로 Board와 통신할 수 있게 된다. 해당 UI를 포함한 클래스의 Private member로 다음과 같은 항목들을 추가해 주었다.
QSocketNotifier *notRsRead;
int fd;
char buf[BUFF_SIZE];
QSocketNotifier는 <QSocketNotifier>라는 Header를 추가해 주어야 한다. 이것에 대한 자세한 설명은 추후에 기술하도록 하겠다.
또한, QSocketNotifier에 의해 동작될 Event 함수도 public slots에 정의해 주었다.
public slots:
void setEvent();
// pushButton 사용자 정의 함수
private slots:
void on_connectButton_clicked();
void MainWindow::on_connectButton_clicked()
{
/*
#define DEVICE01 "/dev/ttyS0"
#define DEVICE02 "/dev/ttyS1"
#define DEVICE03 "/dev/ttyS2"
#define DEVICE04 "/dev/ttyUSB0"
#define DEVICE05 "/dev/ttyUSB1"
#define BAUDRATE1200 B1200
#define BAUDRATE2400 B2400
#define BAUDRATE3800 B4800
#define BAUDRATE9600 B9600
#define BAUDRATE14400 B14400
#define BAUDRATE19200 B19200
#define BAUDRATE38400 B38400
#define BAUDRATE56000 B56000
#define BAUDRATE57600 B57600
#define BAUDRATE115200 B115200
*/
struct termios newtio;
int res;
QString temp_port, port;
QString temp_baudrate, baudrate;
temp_port = ui->portBox->currentText();
if(temp_port == "ttyS0")
{
fd = open(DEVICE01, O_RDWR | O_NOCTTY | O_NONBLOCK);
}
else if(temp_port == "ttyS1")
{
fd = open(DEVICE02, O_RDWR | O_NOCTTY | O_NONBLOCK);
}
else if(temp_port == "ttyS2")
{
fd = open(DEVICE03, O_RDWR | O_NOCTTY | O_NONBLOCK);
}
else if(temp_port == "ttyUSB0")
{
fd = open(DEVICE04, O_RDWR | O_NOCTTY | O_NONBLOCK);
}
else
{
fd = open(DEVICE05, O_RDWR | O_NOCTTY | O_NONBLOCK);
}
memset(&newtio, 0, sizeof(newtio));
temp_baudrate = ui->baudrateBox->currentText();
if(temp_baudrate == "1200")
newtio.c_cflag = BAUDRATE1200;
else if(temp_baudrate == "2400")
newtio.c_cflag = BAUDRATE2400;
else if(temp_baudrate == "4800")
newtio.c_cflag = BAUDRATE4800;
else if(temp_baudrate == "9600")
newtio.c_cflag = BAUDRATE9600;
else if(temp_baudrate == "19200")
newtio.c_cflag = BAUDRATE19200;
else if(temp_baudrate == "38400")
newtio.c_cflag = BAUDRATE38400;
else if(temp_baudrate == "57600")
newtio.c_cflag = BAUDRATE57600;
else if(temp_baudrate == "115200")
newtio.c_cflag = BAUDRATE115200;
newtio.c_cflag |= CS8;
newtio.c_cflag |= CLOCAL | CREAD;
newtio.c_iflag = IGNPAR;
newtio.c_oflag = 0;
newtio.c_lflag = 0;
newtio.c_cc[VINTR] = 0; /* Ctrl-c */
newtio.c_cc[VQUIT] = 0; /* Ctrl-\ */
newtio.c_cc[VERASE] = 0; /* del */
newtio.c_cc[VKILL] = 0; /* @ */
newtio.c_cc[VEOF] = 4; /* Ctrl-d */
newtio.c_cc[VTIME] = 0; /* inter-character timer unused */
newtio.c_cc[VMIN] = 1; /* blocking read until 1 character arrives */
newtio.c_cc[VSWTC] = 0; /* '\0' */
newtio.c_cc[VSTART] = 0; /* Ctrl-q */
newtio.c_cc[VSTOP] = 0; /* Ctrl-s */
newtio.c_cc[VSUSP] = 0; /* Ctrl-z */
newtio.c_cc[VEOL] = 0; /* '\0' */
newtio.c_cc[VREPRINT] = 0; /* Ctrl-r */
newtio.c_cc[VDISCARD] = 0; /* Ctrl-u */
newtio.c_cc[VWERASE] = 0; /* Ctrl-w */
newtio.c_cc[VLNEXT] = 0; /* Ctrl-v */
newtio.c_cc[VEOL2] = 0; /* '\0' */
tcflush(fd, TCIFLUSH);
tcsetattr(fd, TCSANOW, &newtio);
notRsRead = new QSocketNotifier(fd, QSocketNotifier::Read, this);
connect(notRsRead, SIGNAL(activated(int)), this, SLOT(setEvent()));
}
void MainWindow::setEvent()
{
int szRead;
szRead = read(fd, buf, BUFF_SIZE);
buf[szRead] = '\0';
ui->textEdit->insertPlainText(buf);
ui->textEdit->moveCursor(QTextCursor::End);
}
이게 실제 구현부이다. open을 통해 Com port를 열어 주고, BAUDRATE 설정을 통해 통신 속도를 설정해 준다. 그리고 QSocketNotifier로 Message가 오면 setEvent 함수가 동작할 수 있도록 구현하였다. 자세한 내용은 Source를 조금 읽어보면 쉽게 확인할 수 있을것이다.
여기서 중요한 부분은
struct termios newtio;
이부분인데, 따로 정의하지 않아도 Header File안에 정의되어 있으므로 사용할 수 있다. 이 부분을 설정해주고 사용하여야 정상적인 통신이 가능하다.
'QT > Examples' 카테고리의 다른 글
Hello World를 띄우자. (0) | 2015.04.08 |
---|---|
QT에서 이미지 출력하는 방법 (0) | 2015.04.03 |
Qt에서 OpenCV 사용하기 (0) | 2015.03.30 |