먼저 이전 포스트(Raspberry Pi에서 UART를 console이 사용하지 않도록 설정하기)를 참조해 설정을 변경해준다.
C 프로그램에서 UART를 사용하기 위해서는 다음의 헤더 파일을 include 해 준다.
#include <stdio.h>
#include <unistd.h> //Used for UART
#include <fcntl.h> //Used for UART
#include <termios.h> //Used for UART
// -------------------------
// ----- SETUP USART 0 -----
// -------------------------
// At bootup, pins 8 and 10 are already set to UART0_TXD, UART0_RXD
// (ie the alt0 function) respectively
int uart0_filestream = -1;
// OPEN THE UART
// The flags (defined in fcntl.h):
// Access modes (use 1 of these):
// O_RDONLY - Open for reading only.
// O_RDWR - Open for reading and writing.
// O_WRONLY - Open for writing only.
//
// O_NDELAY / O_NONBLOCK (same function) - Enables nonblocking mode.
// When set read requests on the file can return immediately with a failure status
// if there is no input immediately available (instead of blocking).
// Likewise, write requests can also return immediately with a failure status
// if the output can't be written immediately.
//
// O_NOCTTY - When set and path identifies a terminal device,
// open() shall not cause the terminal device to become
// the controlling terminal for the process.
uart0_filestream = open("/dev/ttyAMA0", O_RDWR | O_NOCTTY | O_NDELAY); //Open in non blocking read/write mode
if (uart0_filestream == -1) { // ERROR - CAN'T OPEN SERIAL PORT
printf("Error - Unable to open UART. Ensure it is not in use by another application\n");
}
// CONFIGURE THE UART
// The flags (defined in /usr/include/termios.h
// - see http://pubs.opengroup.org/onlinepubs/007908799/xsh/termios.h.html):
// Baud rate:- B1200, B2400, B4800, B9600, B19200, B38400, B57600,
// B115200, B230400, B460800, B500000, B576000, B921600,
// B1000000, B1152000, B1500000, B2000000, B2500000, B3000000,
// B3500000, B4000000
// CSIZE:- CS5, CS6, CS7, CS8
// CLOCAL - Ignore modem status lines
// CREAD - Enable receiver
// IGNPAR = Ignore characters with parity errors
// ICRNL - Map CR to NL on input
// (Use for ASCII comms where you want to auto correct
// end of line characters - don't use for bianry comms!)
// PARENB - Parity enable
// PARODD - Odd parity (else even)
struct termios options;
tcgetattr(uart0_filestream, &options);
options.c_cflag = B9600 | CS8 | CLOCAL | CREAD; //<Set baud rate
options.c_iflag = IGNPAR;
options.c_oflag = 0;
options.c_lflag = 0;
tcflush(uart0_filestream, TCIFLUSH);
tcsetattr(uart0_filestream, TCSANOW, &options);
코드가 좀 길기는 해도 코멘트를 참고하면 이해하는데 문제는 없을 것이다. 위의 코드는 시리얼 포트를 9600bps, 8 bit data, no parity, non-blocking 모드로 오픈해준다.
시리얼 포트가 오픈되었으면 아래와 같이 데이터를 송수신 할 수 있다.
데이터 전송
//----- TX BYTES -----
unsigned char tx_buffer[20];
unsigned char *p_tx_buffer;
p_tx_buffer = &tx_buffer[0];
*p_tx_buffer++ = 'H';
*p_tx_buffer++ = 'e';
*p_tx_buffer++ = 'l';
*p_tx_buffer++ = 'l';
*p_tx_buffer++ = 'o';
if (uart0_filestream != -1) {
int count = write(uart0_filestream, &tx_buffer[0], (p_tx_buffer - &tx_buffer[0])); //Filestream, bytes to write, number of bytes to write
if (count < 0) {
printf("UART TX error\n");
}
}
데이터 수신
//----- CHECK FOR ANY RX BYTES -----
if (uart0_filestream != -1) {
// Read up to 255 characters from the port if they are there
unsigned char rx_buffer[256];
int rx_length = read(uart0_filestream, (void*)rx_buffer, 255); //Filestream, buffer to store in, number of bytes to read (max)
if (rx_length < 0) {
//An error occured (will occur if there are no bytes)
} else if (rx_length == 0) {
//No data waiting
} else {
//Bytes received
rx_buffer[rx_length] = '\0';
printf("%i bytes read : %s\n", rx_length, rx_buffer);
}
}
일반적인 경우 수신된 데이터가 없을 때 read()를 호출하면 데이터가 수신될 때 까지 실행이 멈추게 되지만 여기서는 시리얼포트를 O_NDELAY 플래그를 사용해 non-blocking 모드로 오픈했기 때문에 read()를 호출했을 때 수신된 데이터가 없어도 바로 리턴하기 때문에 코드 내에서 데이터가 수신되기를 기다려야 한다면 while 루프등을 사용해야 한다.
시리얼 포트를 다 사용했다면 포트를 close하면 된다.
// —— CLOSE THE UART ——
close(uart0_filestream);
시리얼 포트가 동작하는지 확인할 수 있는 가장 쉬운 방법은 Tx와 Rx핀을 서로 연결해 준 다음 프로그램에서 송신한 데이터가 그대로 수신되는지 확인해 보면 된다. (Loopback Test)
댓글 없음:
댓글 쓰기