Documentation/Allspark2-Orin NX WikiEnglish · NX
Browse documentation
Additional documentation

UART C Demo

UART Communication C Demo serialTest 1. serialTest.h : Header file that declares functions related to serial communication. 2. serialTest.c : Source file containing the serial c…

3 min read · English documentation

Included Files

UART Communication C Demo serialTest

  1. serialTest.h: Header file that declares functions related to serial communication.
  2. serialTest.c: Source file containing the serial communication implementation.
  3. main.c: Main program file containing the program entry point, the main() function. It handles serial-port initialization, data transfer, and program control.
  4. Makefile: File used to compile and build the project. It defines the compilation process and the rules for object files and executables.

Source File serialTest.c:

#include "serialTest.h"
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <errno.h>
#include <string.h>
#include <sys/select.h>  
#include <unistd.h>    
int open_serial(const char *dev) {
    int fd = open(dev, O_RDWR | O_NOCTTY | O_NDELAY); // Open the serial device
    if (fd == -1) {
        perror("Open serial error");
        return -1;
    }
    return fd;
}

int config_serial(int fd, int baud_rate) {
    struct termios options;
    if (tcgetattr(fd, &options) != 0) {
        perror("Set serial error");
        return -1;
    }

    // Set the serial-port baud rate according to the supplied value
    switch (baud_rate) {
        case 9600:
            cfsetispeed(&options, B9600);
            cfsetospeed(&options, B9600);
            break;
        case 115200:
            cfsetispeed(&options, B115200);
            cfsetospeed(&options, B115200);
            break;
        // Add other common baud rates as needed
        default:
            fprintf(stderr, "Unsupported baud rate: %d\n", baud_rate);
            return -1;
    }

    // Configure 8 data bits, 1 stop bit, and no parity
    options.c_cflag &= ~PARENB;  // No parity
    options.c_cflag &= ~CSTOPB;  // 1 stop bit
    options.c_cflag &= ~CSIZE;   // Clear the data-bit setting
    options.c_cflag |= CS8;      // 8 data bits

    options.c_cflag |= (CLOCAL | CREAD); // Enable serial reception

    // Set raw mode without input or output processing
    options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    options.c_oflag &= ~OPOST;
    options.c_iflag &= ~(IXON | IXOFF | IXANY);

    if (tcsetattr(fd, TCSANOW, &options) != 0) {
        perror("Set serial error");
        return -1;
    }

    return 0;
}

int write_serial(int fd, const void *buf, size_t len) {
    ssize_t bytes_written = write(fd, buf, len);
    if (bytes_written < 0) {
        perror("Write serial error");
        return -1;
    }
    return bytes_written;
}

int read_serial(int fd, char *buf, size_t len) {
    ssize_t bytes_read = read(fd, buf, len);
    if (bytes_read < 0) {
        perror("Read serial error");
        return -1;
    }
    return bytes_read;
}

// Close the serial port
void close_serial(int fd) {
    if (close(fd) < 0) {
        perror("Close serial error");
    } else {
        printf("Close serial succeed\n");
    }
}

Function Descriptions

1. open_serial(const char *dev)

int open_serial(const char *dev) {
    int fd = open(dev, O_RDWR | O_NOCTTY | O_NDELAY); // Open the serial device
    if (fd == -1) {
        perror("Open serial error");
        return -1;
    }
    return fd;
}

Function:

This function opens the specified serial device and obtains its serial-port file descriptor.

Parameter:

dev: A string containing the serial device path (for example, /dev/ttyUSB0 or /dev/ttyS1).

Return value:

If the serial device is opened successfully, the function returns the file descriptor (fd).

If opening fails, the function returns -1 and sets errno to indicate the cause of the error.

2. config_serial(int fd, int baud_rate)

int config_serial(int fd, int baud_rate) {
    struct termios options;
    if (tcgetattr(fd, &options) != 0) {
        perror("Set serial error");
        return -1;
    }

    // Set the serial-port baud rate according to the supplied value
    switch (baud_rate) {
        case 9600:
            cfsetispeed(&options, B9600);
            cfsetospeed(&options, B9600);
            break;
        case 115200:
            cfsetispeed(&options, B115200);
            cfsetospeed(&options, B115200);
            break;
        // Add other common baud rates as needed
        default:
            fprintf(stderr, "Unsupported baud rate: %d\n", baud_rate);
            return -1;
    }

    // Configure 8 data bits, 1 stop bit, and no parity
    options.c_cflag &= ~PARENB;  // No parity
    options.c_cflag &= ~CSTOPB;  // 1 stop bit
    options.c_cflag &= ~CSIZE;   // Clear the data-bit setting
    options.c_cflag |= CS8;      // 8 data bits

    options.c_cflag |= (CLOCAL | CREAD); // Enable serial reception

    // Set raw mode without input or output processing
    options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    options.c_oflag &= ~OPOST;
    options.c_iflag &= ~(IXON | IXOFF | IXANY);

    if (tcsetattr(fd, TCSANOW, &options) != 0) {
        perror("Set serial error");
        return -1;
    }

    return 0;
}

Function:

This function configures the serial port's baud rate, data bits, stop bits, and parity.

Parameters:

fd: The serial-port file descriptor obtained using the open_serial() function.

baud_rate: An integer containing the baud rate (such as 9600 or 115200).

Return value:

Returns 0 if configuration succeeds.

Returns -1 if configuration fails and sets errno to indicate the cause of the error.

3. write_serial(int fd, const void *buf, size_t len)

int write_serial(int fd, const void *buf, size_t len) {
    ssize_t bytes_written = write(fd, buf, len);
    if (bytes_written < 0) {
        perror("Write serial error");
        return -1;
    }
    return bytes_written;
}

Function:

This function writes the specified byte data to the serial port.

Parameters:

fd: The serial-port file descriptor obtained using the open_serial() function.

buf: A pointer to the data to write.

len: The number of bytes to write.

Return value:

If the write succeeds, the function returns the number of bytes written.

If the write fails, the function returns -1 and sets errno to indicate the cause of the error.

Example:

int bytes_write = write_serial(fd1, Msg, strlen(Msg));
if (bytes_write < 0) {
        close_serial(fd1);
        return -1;  
}

4. int read_serial(int fd, char *buf, size_t len)

int read_serial(int fd, char *buf, size_t len) {
    ssize_t bytes_read = read(fd, buf, len);
    if (bytes_read < 0) {
        perror("Read serial error");
        return -1;
    }
    return bytes_read;
}

Function:

This function reads the specified length of data from the serial port.

Parameters:

fd: The serial-port file descriptor obtained using the open_serial() function.

buf: A pointer to the buffer that receives the data.

len: The number of bytes to read.

Return value:

If the read succeeds, the function returns the actual number of bytes read.

If the read fails, the function returns -1 and sets errno to indicate the cause of the error.

Example:

int read_serial(int fd, char *buf, size_t len) {
    ssize_t bytes_read = read(fd, buf, len);
    if (bytes_read < 0) {
        perror("Read serial error");
        return -1;
    }
    return bytes_read;
}

5. void close_serial(int fd)

Function:

This function closes the specified serial device and releases its resources.

Parameter:

fd: The serial-port file descriptor obtained using the open_serial() function.

Return value:

No return value.

Example:

close_serial(fd1);
close_serial(fd2);

Main Program main.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>  
#include "serialTest.h"

int main(int argc, char *argv[]) {
    if (argc != 4) {
        fprintf(stderr, "Usage: %s <serial device> <serial device> <baud rate> \n", argv[0]);
        return 1;
    }

    const char *dev1 = argv[1];   // Serial device path, such as "/dev/ttyS0"
    const char *dev2 = argv[2];   // Serial device path, such as "/dev/ttyS1"
    int baud_rate = atoi(argv[3]);  // Read the baud rate from the command line
   
    int fd1,fd2;
  
    const char *Msg ="This is serial Test!";
    char buffer[256];


    fd1 = open_serial(dev1);
    if (fd1 == -1) {
        return 1;
        }

    fd2 = open_serial(dev2);
    if (fd2 == -1) {
        return 1;
        }

    if (config_serial(fd1,baud_rate) != 0){
        close_serial(fd1); 
        return -1;
        }

    if (config_serial(fd2,baud_rate) != 0){
        close_serial(fd2); 
        return -1;
        }

    int bytes_write = write_serial(fd1, Msg, strlen(Msg));
        printf("bytes_write: %d\n", bytes_write);
        if (bytes_write < 0) {
            close_serial(fd1);
            return -1;  
        }

    printf("Serial1: %s\n", Msg);

    sleep(1); 

    int bytes_read = read_serial(fd2, buffer, sizeof(buffer) - 1);
    printf("bytes_read: %d\n", bytes_read);
    if (bytes_read > 0) {
        buffer[bytes_read] = '\0';  // Add the string terminator
        printf("Serial2: %s\n", buffer);
        }
    close_serial(fd1);
    close_serial(fd2);
    return 0;
}

Compiling

cd serialTest
make

Running

./serialTest

./serialTest /dev/ttyUSB0 /dev/ttyUSB1 115200

Successful Run