UART 串口示例代码

/* uart_tx.c */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <getopt.h>
#include <termios.h>

#define TEST_LEN (1024 * 400)
static char *dev_name = "/dev/ttyS2";
static int baud_rate = 9600;
static struct option opts[] = {
    {"device", required_argument, NULL, 'd'},
    {"baud", required_argument, NULL, 'b'},
    {"help", no_argument, NULL, 'h'},
};

static void parse_cmd(int argc, char *argv[])
{
    int ch;

    while ((ch = getopt_long(argc, argv, "d:b:l:h", opts, NULL)) != -1) {
        switch (ch) {
        case 'd':
            //printf("dev_name: %s\n", optarg);
            dev_name = optarg;
            break;
        case 'b':
            //printf("baud_rate: %s\n", optarg);
            baud_rate = atoi(optarg);
            break;
        case 'h':
            printf("Usage: %s -d dev_name -b baud_rate\n", argv[0]);
            printf("like:\n");
            printf("\t %s -d /dev/ttyS2\n", argv[0]);
            printf("\t %s --device /dev/ttyS2 -b 9600\n", argv[0]);
            break;
        default:
            printf("Unknown option or invalid format!\n");
            printf("Pls: %s --help for more info\n", argv[0]);
            break;
        }
    }
}

int set_serial(int fd, int baud_rate, int nBits, char nEvent, int nStop)
{
    struct termios tty_cfg;

    memset(&tty_cfg, 0, sizeof(tty_cfg));
    tty_cfg.c_cflag |= (CLOCAL|CREAD); /* CREAD 开启串行数据接收,CLOCAL并打开本地连接模式 */
    tty_cfg.c_cflag &= ~CSIZE; /* 设置数据位 */

    switch(baud_rate) {
    case 2400:
        cfsetispeed(&tty_cfg, B2400);
        cfsetospeed(&tty_cfg, B2400);
        break;
    case 4800:
        cfsetispeed(&tty_cfg, B4800);
        cfsetospeed(&tty_cfg, B4800);
        break;
    case 9600:
        cfsetispeed(&tty_cfg, B9600);
        cfsetospeed(&tty_cfg, B9600);
        break;
    case 115200:
        cfsetispeed(&tty_cfg, B115200);
        cfsetospeed(&tty_cfg, B115200);
        break;
    case 460800:
        cfsetispeed(&tty_cfg, B460800);
        cfsetospeed(&tty_cfg, B460800);
        break;
    default:
        cfsetispeed(&tty_cfg, B9600);
        cfsetospeed(&tty_cfg, B9600);
        break;
    }

    switch(nBits) {
    case 7:
        tty_cfg.c_cflag |= CS7;
        break;
    case 8:
        tty_cfg.c_cflag |= CS8;
        break;
    }

    switch(nEvent) {
    case '0':  /* 奇校验 */
        tty_cfg.c_cflag |= PARENB; /* 开启奇偶校验 */
        tty_cfg.c_iflag |= (INPCK | ISTRIP); /*INPCK打开输入奇偶校验;ISTRIP去除字符的第八个比特  */
        tty_cfg.c_cflag |= PARODD; /*启用奇校验(默认为偶校验)*/
        break;
    case 'E': /*偶校验*/
        tty_cfg.c_cflag |= PARENB; /*开启奇偶校验  */
        tty_cfg.c_iflag |= ( INPCK | ISTRIP); /*打开输入奇偶校验并去除字符第八个比特*/
        tty_cfg.c_cflag &= ~PARODD; /*启用偶校验*/
        break;
    case 'N': /*无奇偶校验*/
        tty_cfg.c_cflag &= ~PARENB;
        break;
    }

    /* 设置停止位;若停止位为1,则清除CSTOPB,若停止位为2,则激活CSTOPB */
    if(nStop == 1)
        tty_cfg.c_cflag &= ~CSTOPB; /*默认为一位停止位; */
    else if( nStop == 2)
        tty_cfg.c_cflag |= CSTOPB; /* CSTOPB表示送两位停止位 */

    /* flow control option */
    tty_cfg.c_cflag |= CRTSCTS;

    /* 设置最少字符和等待时间,对于接收字符和等待时间没有特别的要求时*/
    tty_cfg.c_cc[VTIME] = 0; /* 非规范模式读取时的超时时间;*/
    tty_cfg.c_cc[VMIN]  = 0; /* 非规范模式读取时的最小字符数*/
    tcflush(fd, TCIFLUSH); /* tcflush清空终端未完成的输入/输出请求及数据;TCIFLUSH表示清空正收到的数据,且不读取出来 */

    /*激活配置使其生效*/
    if((tcsetattr(fd, TCSANOW, &tty_cfg)) != 0) {
        printf("com set error");
        exit(1);
    }

    return 0;
}

char buff[TEST_LEN];

int main(int argc, char *argv[])
{
    int fd=0;
    int cnt=0;
    int sum=0;
    static int num=0;
    char *p=NULL;

    parse_cmd(argc, argv);
    printf("TX: dev_name=%s, baud_rate=%d\n", dev_name, baud_rate);

    fd = open(dev_name,O_RDWR|O_NOCTTY|O_NDELAY);
    if(fd < 0) {
        printf("Can't Open %s\n", dev_name);
        return -1;
    }

    set_serial(fd, baud_rate, 8, 'N', 1);
    sleep(1);

    memset(buff, 0x55, TEST_LEN);
    //printf("start send: %ds\n", time(NULL));
    p = &buff[0];
    while(1) {
        cnt = write(fd, p, (TEST_LEN-sum));
        if(cnt < 0) {
            //sleep(1);
            continue;
        }
        sum += cnt;
        if(sum >= TEST_LEN)
            break;
        p += cnt;
        printf("TX%d: cnt = %d, sum = %d\n", num++, cnt, sum);
    }
    
    printf("send %d: %ds\n", sum, time(NULL));
    
    close(fd);
    return 0;
}

 

 

/* uart_rx.c */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <getopt.h>
#include <termios.h>

#define TEST_LEN (1024 * 400)
static char *dev_name = "/dev/ttyS2";
static int baud_rate = 9600;
static struct option opts[] = {
    {"device", required_argument, NULL, 'd'},
    {"baud", required_argument, NULL, 'b'},
    {"help", no_argument, NULL, 'h'},
};

static void parse_cmd(int argc, char *argv[])
{
    int ch;

    while ((ch = getopt_long(argc, argv, "d:b:l:h", opts, NULL)) != -1) {
        switch (ch) {
        case 'd':
            //printf("dev_name: %s\n", optarg);
            dev_name = optarg;
            break;
        case 'b':
            //printf("baud_rate: %s\n", optarg);
            baud_rate = atoi(optarg);
            break;
        case 'h':
            printf("Usage: %s -d dev_name -b baud_rate\n", argv[0]);
            printf("like:\n");
            printf("\t %s -d /dev/ttyS2\n", argv[0]);
            printf("\t %s --device /dev/ttyS2 -b 9600\n", argv[0]);
            break;
        default:
            printf("Unknown option or invalid format!\n");
            printf("Pls: %s --help for more info\n", argv[0]);
            break;
        }
    }
}

int set_serial(int fd, int baud_rate, int nBits, char nEvent, int nStop)
{
    struct termios tty_cfg;

    memset(&tty_cfg, 0, sizeof(tty_cfg));
    tty_cfg.c_cflag |= (CLOCAL|CREAD); /* CREAD 开启串行数据接收,CLOCAL并打开本地连接模式 */
    tty_cfg.c_cflag &= ~CSIZE; /* 设置数据位 */

    switch(baud_rate) {
    case 2400:
        cfsetispeed(&tty_cfg, B2400);
        cfsetospeed(&tty_cfg, B2400);
        break;
    case 4800:
        cfsetispeed(&tty_cfg, B4800);
        cfsetospeed(&tty_cfg, B4800);
        break;
    case 9600:
        cfsetispeed(&tty_cfg, B9600);
        cfsetospeed(&tty_cfg, B9600);
        break;
    case 115200:
        cfsetispeed(&tty_cfg, B115200);
        cfsetospeed(&tty_cfg, B115200);
        break;
    case 460800:
        cfsetispeed(&tty_cfg, B460800);
        cfsetospeed(&tty_cfg, B460800);
        break;
    default:
        cfsetispeed(&tty_cfg, B9600);
        cfsetospeed(&tty_cfg, B9600);
        break;
    }

    switch(nBits) {
    case 7:
        tty_cfg.c_cflag |= CS7;
        break;
    case 8:
        tty_cfg.c_cflag |= CS8;
        break;
    }

    switch(nEvent) {
    case '0':  /* 奇校验 */
        tty_cfg.c_cflag |= PARENB; /* 开启奇偶校验 */
        tty_cfg.c_iflag |= (INPCK | ISTRIP); /*INPCK打开输入奇偶校验;ISTRIP去除字符的第八个比特  */
        tty_cfg.c_cflag |= PARODD; /*启用奇校验(默认为偶校验)*/
        break;
    case 'E': /*偶校验*/
        tty_cfg.c_cflag |= PARENB; /*开启奇偶校验  */
        tty_cfg.c_iflag |= ( INPCK | ISTRIP); /*打开输入奇偶校验并去除字符第八个比特*/
        tty_cfg.c_cflag &= ~PARODD; /*启用偶校验*/
        break;
    case 'N': /*无奇偶校验*/
        tty_cfg.c_cflag &= ~PARENB;
        break;
    }

    /* 设置停止位;若停止位为1,则清除CSTOPB,若停止位为2,则激活CSTOPB */
    if(nStop == 1)
        tty_cfg.c_cflag &= ~CSTOPB; /*默认为一位停止位; */
    else if( nStop == 2)
        tty_cfg.c_cflag |= CSTOPB; /* CSTOPB表示送两位停止位 */

    /* flow control option */
    tty_cfg.c_cflag |= CRTSCTS;

    /* 设置最少字符和等待时间,对于接收字符和等待时间没有特别的要求时*/
    tty_cfg.c_cc[VTIME] = 0; /* 非规范模式读取时的超时时间;*/
    tty_cfg.c_cc[VMIN]  = 0; /* 非规范模式读取时的最小字符数*/
    tcflush(fd, TCIFLUSH); /* tcflush清空终端未完成的输入/输出请求及数据;TCIFLUSH表示清空正收到的数据,且不读取出来 */

    /*激活配置使其生效*/
    if((tcsetattr(fd, TCSANOW, &tty_cfg)) != 0) {
        printf("com set error");
        exit(1);
    }

    return 0;
}

void dump_data(char *buf)
{
    int i;

    for(i=0; i<TEST_LEN; i++) {
        if(i%16 == 0)
            printf("\n");
        printf("0x%x, ", buf[i]);
    }
}

char buff[TEST_LEN];

int main(int argc, char *argv[])
{
    int fd=0;
    int cnt=0;
    int sum=0;
    static int num=0;
    char *p=NULL;

    parse_cmd(argc, argv);
    printf("RX: dev_name=%s, baud_rate=%d\n", dev_name, baud_rate);

    fd = open(dev_name,O_RDWR|O_NOCTTY|O_NDELAY);
    if(fd < 0) {
        printf("Can't Open %s\n", dev_name);
        return -1;
    }

    set_serial(fd, baud_rate, 8, 'N', 1);
    sleep(1);

    memset(buff, 0x0, TEST_LEN);
    //printf("start recv: %ds\n", time(NULL));
    p = &buff[0];
    while(1) {
        cnt = read(fd, p, TEST_LEN);
        if(cnt <= 0) {
            //sleep(1);
            continue;
        }
        sum += cnt;
        if(sum >= TEST_LEN)
            break;
        p += cnt;
        printf("RX%d: cnt = %d, sum = %d\n", num++, cnt, sum);
    }
    printf("recv %d: %ds\n", sum, time(NULL));
    p = NULL;
    close(fd);

    //dump_data(buff);    

    return 0;
}

 

posted @ 2019-07-17 15:48  Vedic  阅读(865)  评论(0编辑  收藏  举报