새로 라즈베리파이 4를 입수해서, 기존에 했던 것들을 그대로 옮기는 작업이 필요해졌다. 우선 1 단계로 UART 작업을 시작하기로 했다.
들리는 바에 따르면 라즈베리파이 4는 6 개까지 UART를 지원한다고 한다. 정말 그런지 테스트를 다 해보고 싶었으나, UART는 현 프로젝트에 별로 중요한 내용이 아닌 관계로, 라즈베리파이 3에서 했던 내용, 특히 할당된 하드웨어 핀을 그대로 쓰는 것에 초점을 맞추고자 한다.
라즈베리파이 3에는 '/dev/ttyS0'와 '/dev/ttyAMA0' 두 개의 시리얼 디바이스가 지원이 되었다. 이 중에 miniuart인 '/dev/ttyS0'는 좀 불안한 구석이 있어서, '/dev/ttyAMA0'로 작업을 진행했었다.
세부적인 사항에 대해서는 라즈베리파이 UART에 대해 잘 정리되어 있는 글로 아래 황제곰님의 글을 추천한다. 라즈베리파이 4의 여러 UART를 골라 쓰는법, 기존의 UART0를 쓰는 법들이 잘 정리되어있다.
지난 번과 같이 /boot/cmdline.txt에서 console=serial0,115200 를 지우거나, serial0를 serial1으로 바꾼다.
마찬가지로 이전과 동일한 파이선 프로그램으로 간단한 출력 테스트를 해보았다.
import serial
import time
ser = serial.Serial(
port='/dev/ttyAMA0',
baudrate=115200,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS
)
time.sleep(1)
# Send 'A' repeatedly to the serial port
while True:
ser.write(b'A')
time.sleep(1)
여기까지 별 문제가 없었고,
이번에는 좀 더 복잡해 보이도록 C 테스트 프로그램을 만들어 테스트 해보았다. 간단한 터미널 에코 기능을 한다.
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
int open_serial_port(char *port_name, speed_t baudrate) {
int fd;
struct termios tty;
fd = open(port_name, O_RDWR | O_NOCTTY | O_SYNC);
if (fd < 0) {
perror("error opening serial port");
return -1;
}
memset(&tty, 0, sizeof(tty));
if (tcgetattr(fd, &tty) != 0) {
perror("error from tcgetattr");
close(fd);
return -1;
}
cfsetospeed(&tty, baudrate);
cfsetispeed(&tty, baudrate);
tty.c_cflag |= (CLOCAL | CREAD);
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8;
tty.c_cflag &= ~PARENB;
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CRTSCTS;
tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
tty.c_iflag &= ~(IXON | IXOFF | IXANY | INPCK | PARMRK);
tty.c_oflag &= ~OPOST;
tty.c_cc[VTIME] = 10;
tty.c_cc[VMIN] = 0;
if (tcsetattr(fd, TCSANOW, &tty) != 0) {
perror("error from tcsetattr");
close(fd);
return -1;
}
return fd;
}
int write_serial_port(char *data, size_t len) {
int num = write(fd, data, len);
if (num != len) {
perror("error writing to serial port");
return -1;
}
return num;
}
int read_serial_port(char *buf, size_t len) {
int num = read(fd, buf, len);
if (num < 0) {
perror("error reading from serial port");
return -1;
}
return num;
}
void close_serial(){
close(fd);
}
int main(){
int fd;
int num;
char buf[256];
fd = open_serial_port("/dev/ttyAMA0", B115200);
if(fd < 0)
return -1;
write_serial_port(fd, "Hello, world!\n", 14);
while(TRUE){
num = read_serial_port(fd, buf, 1);
if(num > 0){
printf("Received: %c\n", buf[0]);
}
}
close(fd);
}