Skip to content

시리얼 통신

COM (RS232) 포트 및 RS485/CAN1

STEP2에는 2개의 COM (RS232) 포트와 1개의 RS485/CAN 포트가 있습니다. COM 포트(COM1, COM2)가 DSUB-9 커넥터에 배치되고 RS485/CAN 포트는 9핀 커넥터를 CAN 포트와 공유합니다.


아래와 같이 커널 로그를 사용하여 사용 가능한 시리얼 포트를 확인할 수 있습니다.

1
$ dmesg | grep tty


사용 가능한 시리얼 포트 체크

4개의 시리얼 포트가 있지만 STEP2에서는 3개만 사용할 수 있습니다. ttyS3, ttyS4는 STEP2 패널의 COM1 및 COM2 포트를 나타내며 ttyS0은 RS485/CAN 포트를 나타냅니다.


STEP2의 시리얼 포트

COM(RS232) 포트와 RS485 포트는 NRMK 라이브러리 또는 표준 Serial API에 의해 제어됩니다. API 함수에서 tp_open_serial_port 는 시리얼 포트 (RS232 포트 및 RS458 포트)를 열고 설정 값을 적용할 수 있는 가장 유용한 함수입니다. 이 함수의 매개변수는 포트 이름과 통신 baudrate이며 리턴은 시리얼 포트에 대한 파일 서술자 (fd) 입니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
//! @brief Available serial ports on board
#define SERIALPORT1     "/dev/ttyS0"
#define SERIALPORT4     "/dev/ttyS3"
#define SERIALPORT5     "/dev/ttyS4"
#define SERIALPORT6     "/dev/ttyS5"

//! @brief Available serial ports on STEP-PC2
#define RS485PORT       "/dev/ttyS0"    //RS485 port
#define COM1            "/dev/ttyS3"    //COM1 port
#define COM2            "/dev/ttyS4"    //COM2 port

#define RS485_BAUD_LIMIT    1500000 //maximum RS485 baudrate
#define RS232_BAUD_LIMIT    230400      //maximum baudrate

// STEP Serial
int NRMKkbhit(void);
int tp_open_serial_port(const char* portname, unsigned int baud);
int tp_configure_serial_port(int fd, int baud);

참고

STEP2에서는 물리적 특성 때문에 RS232 포트와 RS485의 최대 baudrate 동일하지 않습니다. RS232 포트(COM1, COM2)의 경우 최대 속도는 230400 bps (230.4 Kbps)이며 RS485 포트는 1500000 bps (1.5 Mbps)입니다.

시리얼 통신 예제

아래 예제는 NRMKFoundation 설치 시 포함된 tpserial 예제 입니다. 터미널에 키 입력이 발생했을때 시리얼 포트를 통하여 키를 타겟에 전송하고 타겟으로 부터 데이터를 받아와 터미널에 출력하는 예제입니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include "NRMKhw_tp.h"
int fd=-1;
void * read_thread(void* arg);
void * write_thread(void* arg);
//reading thread
void * read_thread(void* arg)
{
    int nbytes;
    char chr;
    while(1)
    {
        nbytes=read(fd,&chr,1);
        if (nbytes>0){
            printf("%c", chr);
        }
        usleep(1e4);
    }
}
//writing thread
void * write_thread(void* arg)
{
    int kchr;
    while(1)
    {
        if (NRMKkbhit())
        {
            kchr = getchar();
            write(fd,&kchr,1);
        }
        usleep(1e4);
    }
}
/****************************************************************************
 * Signal handler
 ***************************************************************************/
void catch_signal(int sig)
{
    if (fd>0) close(fd);
    exit(1);
}

int main(int argc, char* argv[])
{
    signal(SIGTERM, catch_signal);
    signal(SIGINT, catch_signal);

    int portNum=1;          //COM1 as default
    char portName[100];
    unsigned int baud = 115200;

    if (argc>1)
        portNum = atoi(argv[1]);
    switch (portNum)
    {
        case 0: strcpy(portName, RS485PORT); break;
        case 1: strcpy(portName, COM1); break;
        case 2: strcpy(portName, COM2); break;
        default: strcpy(portName, COM1); break;
    }

    if (argc>2)baud = atoi(argv[2]);

    if ((portNum==0) && (baud>RS485_BAUD_LIMIT))
        baud=RS485_BAUD_LIMIT;
    else if ((portNum>0) && (baud>RS232_BAUD_LIMIT))
        baud=RS232_BAUD_LIMIT;
    if (baud<1200)
        baud=1200;

    printf("Serial example: port=#%s, baud=%i\n", portName, baud);

    fd=tp_open_serial_port(portName, baud);
    if(fd<0)
         return 1;

    usleep(1e5);
    pthread_t tid1,tid2;
    pthread_create(&tid1, NULL, read_thread, NULL);
    pthread_create(&tid2, NULL, write_thread, NULL);
    pthread_join(tid1,NULL);
    pthread_join(tid2,NULL);

    return 0;
}
  • 먼저 시리얼 포트를 열기 위해 tp_open_serial_port 함수를 사용합니다 (line 75).

  • 시리얼 포트에 대한 읽기와 쓰기는 표준 읽기/쓰기 리눅스 라이브러리에 의해 수행되며 읽기/쓰기 작업을 위해 두 개의 스레드를 생성합니다.

  • write_thread 에서 키보드의 입력을 스캔합니다 (line 23 – 35).

  • 임의의 키를 입력하면 write 함수에 의해 캡처되어 시리얼 포트로 전송됩니다. write 함수의 첫 번째 매개 변수는 시리얼 포트의 파일 서술자이고 두 번째 매개 변수는 전송할 데이터 버퍼에 대한 포인터, 마지막 매개 변수는 전송될 바이트 수 입니다.

  • read_thread 는 데이터가 시리얼 포트에 전송될 때까지 기다리는 폴링 루프입니다 (line 9 – 21).

  • 읽기 시스템 함수 nbytes=read(fd,&chr,1) 는 데이터 획득을 위해 사용됩니다. read 의 첫 번째 매개변수는 시리얼 포트의 파일 서술자이고 두 번째 매개변수는 데이터를 저장하는 버퍼에 대한 포인터, 마지막 매개변수는 읽을 바이트 수입니다. read 의 리턴 값은 수신된 바이트의 실제 수입니다.


  1. RS485 핀은 STEP2 블루 커버에서 사용할 수 없으며 자세한 내용은 RS485 포트 설정를 참조하십시오.