免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1269 | 回复: 0
打印 上一主题 下一主题

比较好用的串口测试程序 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-01-14 16:24 |只看该作者 |倒序浏览

                               
               
               
               
serial.c,串口基本操作的封装:#include termios.h>            /* tcgetattr, tcsetattr */
#include stdio.h>              /* perror, printf, puts, fprintf, fputs */
#include unistd.h>             /* read, write, close */
#include fcntl.h>              /* open */
#include sys/signal.h>
#include sys/types.h>
#include string.h>             /* bzero, memcpy */
#include limits.h>             /* CHAR_MAX */
#include "serial.h"
/*
* Decription for TIMEOUT_SEC(buflen,baud);
* baud bits per second, buflen bytes to send.
* buflen*20 (20 means sending an octect-bit data by use of the maxim bits 20)
* eg. 9600bps baudrate, buflen=1024B, then TIMEOUT_SEC = 1024*20/9600+1 = 3
* don't change the two lines below unless you do know what you are doing.
*/
#define TIMEOUT_SEC(buflen,baud) (buflen*20/baud+2)
#define TIMEOUT_USEC 0
#define CH_TO_WAIT 5
#define CH_BITS 11
#define BUFFER_LEN  1024    /* sendfile() */
static INT32    fd;             //File descriptor for the port
static struct termios termios_old, termios_new;
static fd_set   fs_read, fs_write;
static struct timeval tv_timeout;
static void     set_baudrate (INT32);
static INT32    get_baudrate ();
static void     set_data_bit (INT32 databit);
static INT32    baudrate2Bxx (INT32 baudrate);
static INT32    Bxx2baudrate (INT32 _baudrate);
static INT32    set_port_attr (
                             INT32 baudrate,         //
                             INT32 databit,
                             const char *stopbit,
                             char parity);
static void     set_stopbit (const char *stopbit);
static void     set_parity (char parity);
/* Open serial port ComPort at baudrate baud rate. */
INT32 OpenComPort (INT32 ComPort, INT32 baudrate, INT32 databit,
                   const char *stopbit, char parity)
{
    char           *pComPort;
    INT32           retval;
    switch (ComPort) {
    case 0:
        pComPort = "/dev/ttyS0";
        break;
    case 1:
        pComPort = "/dev/ttyS1";
        break;
    case 2:
        pComPort = "/dev/ttyS2";
        break;
    case 3:
        pComPort = "/dev/ttyS3";
        break;
    case 4:
        pComPort = "/dev/ttyTX0";
        break;
    case 5:
        pComPort = "/dev/ttyTX1";
        break;
    default:
        pComPort = "/dev/ttyS0";
        break;
    }
    fd = open (pComPort, O_RDWR | O_NOCTTY); // | O_NONBLOCK);
    if (-1 == fd) {
        fprintf (stderr, "cannot open port %s\n", pComPort);
        return (-1);
    }
    printf("comport fd = %d\n", fd);
    tcgetattr (fd, &termios_old);       /* save old termios value */
    /* 0 on success, -1 on failure */
    retval = set_port_attr (baudrate, databit, stopbit, parity);
    if (-1 == retval) {
        fprintf (stderr, "\nport %s cannot set baudrate at %d\n", pComPort,
                 baudrate);
    }
    return (retval);
}
/* close serial port by use of file descriptor fd */
void CloseComPort ()
{
    /* flush output data before close and restore old attribute */
    tcsetattr (fd, TCSADRAIN, &termios_old);
    close (fd);
}
int getPortFd(){
    return fd;
}
INT32 ReadComPort (void *data, INT32 datalength)
{
    INT32           retval = 0;
    FD_ZERO (&fs_read);
    FD_SET (fd, &fs_read);
    tv_timeout.tv_sec = TIMEOUT_SEC (datalength, get_baudrate ());
    tv_timeout.tv_usec = TIMEOUT_USEC;
    retval = select (fd + 1, &fs_read, NULL, NULL, &tv_timeout);
    if (retval > 0) {
        retval = read (fd, data, datalength);
        return (retval);
    }
    else {
        if (0 == retval ) {
            return (0);
        }else{
            return (-1);
        }
    }
}
INT32 ReadComPortA (void *data, INT32 datalength)
{
    INT32           retval = 0;
    int bytes_read;
    int readlen;
    /**
     * caculate the time of 5 characters and get the maxim
     * with 3ms and 5 ch's time
    */
    tv_timeout.tv_sec = 0;
    tv_timeout.tv_usec = ( (CH_TO_WAIT * CH_BITS) * (1000000/get_baudrate()));
    //printf("port read timeout:%dus\n",tv_timeout.tv_usec);
    bytes_read = 0;
    while(bytes_readdatalength){
        tv_timeout.tv_sec = 0;
        tv_timeout.tv_usec = ( (CH_TO_WAIT * CH_BITS) * (1000000/get_baudrate()));
        FD_ZERO (&fs_read);
        FD_SET (fd, &fs_read);
        retval = select (fd + 1, &fs_read, NULL, NULL, &tv_timeout);
        if ( retval >0 ) {
            readlen = read (fd, (data+bytes_read), datalength);
            bytes_read += readlen;
        } else
            return (bytes_read==0?-1:bytes_read);
    }
    return -1;
}
/*
* Write datalength bytes in buffer given by UINT8 *data,
* return value: bytes written
* Nonblock mode
*/
INT32 WriteComPort (UINT8 * data, INT32 datalength)
{
    INT32           retval, len = 0, total_len = 0;
    FD_ZERO (&fs_write);
    FD_SET (fd, &fs_write);
    tv_timeout.tv_sec = TIMEOUT_SEC (datalength, get_baudrate ());
    tv_timeout.tv_usec = TIMEOUT_USEC;
    for (total_len = 0, len = 0; total_len  datalength;) {
        retval = select (fd + 1, NULL, &fs_write, NULL, &tv_timeout);
        if (retval) {
            len = write (fd, &data[total_len], datalength - total_len);
            if (len > 0) {
                total_len += len;
            }
        }
        else {
            tcflush (fd, TCOFLUSH);     /* flush all output data */
            break;
        }
    }
    return (total_len);
}
/* get serial port baudrate */
static INT32 get_baudrate ()
{
    return (Bxx2baudrate (cfgetospeed (&termios_new)));
}
/* set serial port baudrate by use of file descriptor fd */
static void set_baudrate (INT32 baudrate)
{
    termios_new.c_cflag = baudrate2Bxx (baudrate);  /* set baudrate */
}
static void set_data_bit (INT32 databit)
{
    termios_new.c_cflag &= ~CSIZE;
    switch (databit) {
    case 8:
        termios_new.c_cflag |= CS8;
        break;
    case 7:
        termios_new.c_cflag |= CS7;
        break;
    case 6:
        termios_new.c_cflag |= CS6;
        break;
    case 5:
        termios_new.c_cflag |= CS5;
        break;
    default:
        termios_new.c_cflag |= CS8;
        break;
    }
}
static void set_stopbit (const char *stopbit)
{
    if (0 == strcmp (stopbit, "1")) {
        termios_new.c_cflag &= ~CSTOPB; /* 1 stop bit */
    }
    else if (0 == strcmp (stopbit, "1.5")) {
        termios_new.c_cflag &= ~CSTOPB; /* 1.5 stop bits */
    }
    else if (0 == strcmp (stopbit, "2")) {
        termios_new.c_cflag |= CSTOPB;  /* 2 stop bits */
    }
    else {
        termios_new.c_cflag &= ~CSTOPB; /* 1 stop bit */
    }
}
static void set_parity (char parity)
{
    switch (parity) {
    case 'N':                  /* no parity check */
        termios_new.c_cflag &= ~PARENB;
        break;
    case 'E':                  /* even */
        termios_new.c_cflag |= PARENB;
        termios_new.c_cflag &= ~PARODD;
        break;
    case 'O':                  /* odd */
        termios_new.c_cflag |= PARENB;
        termios_new.c_cflag |= ~PARODD;
        break;
    default:                   /* no parity check */
        termios_new.c_cflag &= ~PARENB;
        break;
    }
}
static INT32 set_port_attr (
                          INT32 baudrate,        // 1200 2400 4800 9600 .. 115200
                          INT32 databit,           // 5, 6, 7, 8
                          const char *stopbit,  //  "1", "1.5", "2"
                          char parity)              // N(o), O(dd), E(ven)
{
    bzero(&termios_new, sizeof (termios_new));
    cfmakeraw (&termios_new);
    set_baudrate (baudrate);
    termios_new.c_cflag |= CLOCAL | CREAD;      /* | CRTSCTS */
    set_data_bit (databit);
    set_parity (parity);
    set_stopbit (stopbit);
    termios_new.c_oflag             = 0;
    termios_new.c_lflag             |= 0;
    termios_new.c_oflag             &= ~OPOST;
    termios_new.c_cc[VTIME]     = 1;        /* unit: 1/10 second. */
    termios_new.c_cc[VMIN]         = 255; /* minimal characters for reading */
    tcflush (fd, TCIFLUSH);
    return (tcsetattr (fd, TCSANOW, &termios_new));
}
/**
* baudrate xxx to Bxxx
*
* @@param baudrate xxx
*
* @@return
*/
static INT32 baudrate2Bxx (INT32 baudrate)
{
    switch (baudrate) {
    case 0:
        return (B0);
    case 50:
        return (B50);
    case 75:
        return (B75);
    case 110:
        return (B110);
    case 134:
        return (B134);
    case 150:
        return (B150);
    case 200:
        return (B200);
    case 300:
        return (B300);
    case 600:
        return (B600);
    case 1200:
        return (B1200);
    case 2400:
        return (B2400);
    case 9600:
        return (B9600);
    case 19200:
        return (B19200);
    case 38400:
        return (B38400);
    case 57600:
        return (B57600);
    case 115200:
        return (B115200);
    default:
        return (B9600);
    }
}
/**
* get boundrate from Bxxx
*
* @@param baudrate Bxxx refers to bound rate
*
* @@return
*/
static INT32 Bxx2baudrate (INT32 _baudrate)
{
/* reverse baudrate */
    switch (_baudrate) {
    case B0:
        return (0);
    case B50:
        return (50);
    case B75:
        return (75);
    case B110:
        return (110);
    case B134:
        return (134);
    case B150:
        return (150);
    case B200:
        return (200);
    case B300:
        return (300);
    case B600:
        return (600);
    case B1200:
        return (1200);
    case B2400:
        return (2400);
    case B9600:
        return (9600);
    case B19200:
        return (19200);
    case B38400:
        return (38400);
    case B57600:
        return (57600);
    case B115200:
        return (115200);
    default:
        return (9600);
    }
}
对应的头文件serial.h:#ifndef _SERIAL_H
#define _SERIAL_H 1
typedef int     INT32;
typedef short   INT16;
typedef char    INT8;
typedef unsigned int UNIT32;
typedef unsigned short UINT16;
typedef unsigned char UINT8;
/* serial.c */
INT32 OpenComPort (INT32 ComPort, INT32 baudrate, INT32 databit,
                                        const char *stopbit, char parity);
void CloseComPort (void);
INT32 ReadComPort (void *data, INT32 datalength);
INT32 WriteComPort (UINT8 * data, INT32 datalength);
/**
* export serial fd to other program to perform
* directly read, write to serial.
*
* @return serial's file description
*/
int getPortFd();
#endif /* serial.c */
测试程序:#include stdio.h>
#include stdlib.h>
#include unistd.h>
#include fcntl.h>
#include "serial.h"
//#define ttyS0  0 //
#define ttyS1  1 //OK
#define ttyS2  2
#define ttyS3  3 //OK
#define ttyTX0 4 //OK
#define ttyTX1 5
static int n_com_port = ttyTX0;
int main (int argc, char *argv[])
{
    int ret = -1;
    int len_tty = -1;
    int fd_rs485;
    unsigned char buf_tty[256];
    if (argc > 1) {
        n_com_port = strtol( argv[1], NULL, 10 );
    }
    ret = OpenComPort(n_com_port, 115200, 8, "1", 'N');
    if (ret  0) {
        fprintf(stderr, "Error: Opening Com Port %d\n", n_com_port);
        return ret;
    }else{
        printf("Open Com Port %d Success, Now going to read port\n", n_com_port);
    }
    while(1){
        bzero(buf_tty, sizeof(buf_tty));
        len_tty = ReadComPort(buf_tty, 255);
        if (len_tty  0) {
            printf("Error: Read Com Port\n");
            break;
        }
        if (len_tty == 0) {
            write(STDOUT_FILENO, ".", sizeof("."));
            continue;
        }
        printf("Recv: %d bytes, [%s]\n", len_tty, buf_tty);
        
        len_tty = WriteComPort(buf_tty, len_tty);
        WriteComPort(" recved:", sizeof(" recved:"));
        if (len_tty  0) {
            printf("Error: WriteComPort Error\n");
        }
        // delay 500 ms to let data transfer complete
        // here will cause bugs
        usleep(500 * 1000);
    }
    CloseComPort();
    printf("Program Terminated\n");
    return(0);
}
测试结果和现象:root@omap3evm:/app/uart# ./test_uart-ttyS0comport fd = 3Open Com Port 0 Success, Now going to read portRecv: 16 bytes, [1234567890abcdef]Recv: 16 bytes, [1234567890abcdef]Recv: 16 bytes, [1234567890abcdef]Recv: 16 bytes, [1234567890abcdef]...........
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/51797/showart_2149166.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP