博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
串口编程(二) - 代码实现
阅读量:6267 次
发布时间:2019-06-22

本文共 13946 字,大约阅读时间需要 46 分钟。

1. 串口编程

串口编程的一般步骤为:

    1. 打开串口设备(一般为/dev/ttyS[n])
    1. 设置串口参数(包括波特率、数据位、停止位、校验位等)
    1. 监听接口,当有数据时通知CPU
    1. 读取串口(写入数据到串口)
    1. 关闭串口设备

mark

2. 代码示例

1). 串口的基本配置

/************************************************************************ * Function_name: serial_open * Description: Open the /dev/ttyS[n] serial device * Input:  *      1. int port_num: the serial device port number * Output: None * Return: the device description * * Autor        Time            Content * Jimmy    2018-04-05          Create   * ************************************************************************/int serial_open(int port_num){    int fd = -1;    char device[16];    memset(device, '\0', sizeof(device));    sprintf(device, "/dev/ttyS%d", port_num);    fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY);    if(-1 == fd)    {        printf("Open the %s failed! [%d:%s]\n", device, errno, strerror(errno));        return -1;    }    fcntl(fd, F_SETFL, 0);      //Use the block mode    return fd;}/************************************************************************ * Function_name: set_parm * Description: set the serial device paramters * Input:  *      1. int fd: the device description        2. int speed: the band speed        3. int data_bits: the data bits(7bit or 8bit)        4. int stop_bits: stop  bits(1bit or 2bit)        5. char parity: the parity(odd/even/none) * Output: None * Return:         0:  succeed        -1: error * * Autor        Time            Content * Jimmy    2018-04-05          Create   * ************************************************************************/int set_parm(int fd, int speed, int data_bits, int stop_bits, char parity){    struct termios old_opt;    struct termios new_opt;    int rtn = 0;    //1. get the old termios options    rtn = tcgetattr(fd, &old_opt);    if(rtn != 0)    {        printf("tcgetattr failed! [%d:%s]\n", errno, strerror(errno));        rtn = -1;    }    if(0 == rtn)    {        //2. set the io speed        tcflush(fd, TCIOFLUSH);     //flush the io data        //3. set the io speed        switch(speed)        {            case 2400:                cfsetispeed(&new_opt, B2400);                cfsetospeed(&new_opt, B2400);                break;            case 4800:                cfsetispeed(&new_opt, B4800);                cfsetospeed(&new_opt, B4800);                break;            case 9600:                cfsetispeed(&new_opt, B9600);                cfsetospeed(&new_opt, B9600);                break;            case 19200:                cfsetispeed(&new_opt, B19200);                cfsetospeed(&new_opt, B19200);                break;            case 38400:                cfsetispeed(&new_opt, B38400);                cfsetospeed(&new_opt, B38400);                break;            case 57600:                cfsetispeed(&new_opt, B57600);                cfsetospeed(&new_opt,  B57600);                break;            case 115200:                cfsetispeed(&new_opt, B115200);                cfsetospeed(&new_opt, B115200);                break;            case 230400:                cfsetispeed(&new_opt, B230400);                cfsetospeed(&new_opt, B230400);                break;            default:                cfsetispeed(&new_opt, B115200);                cfsetospeed(&new_opt, B115200);                break;        }        //4. set the data bits         new_opt.c_cflag &= ~CSIZE;        switch(data_bits)        {            case 7:                new_opt.c_cflag |= CS7;                break;            case 8:                new_opt.c_cflag |= CS8;                break;            default:                printf("Error on set the data bits\n");                break;        }        //5. set the stop bits        switch(stop_bits)        {            case 1: //set the stop 1 bit                new_opt.c_cflag &= ~CSTOPB;                break;            case 2:                new_opt.c_cflag |= CSTOPB;                break;            default:                printf("Error on set the stop bits\n");                break;        }        //6. set the parity        switch(parity)        {            case 'N':            case 'n':                new_opt.c_cflag &= ~PARENB; //clear parity enable                 break;            case 'E':            case 'e':                new_opt.c_cflag |= PARENB; //clear parity enable                 new_opt.c_cflag &= ~PARODD;                new_opt.c_cflag |= (INPCK | ISTRIP);                break;            case 'O':            case 'o':                new_opt.c_cflag |= PARENB;                new_opt.c_cflag |= PARODD;                new_opt.c_cflag |= (INPCK | ISTRIP);   //Enable the input parity checking, and strip the eigth bit                break;            default:                printf("Error on set the parity!\n");                break;        }        //7. set the wait time and mix received characters        new_opt.c_cc[VTIME] = 0;        new_opt.c_cc[VMIN] = 0;        //8. set the attribute and valid now        tcflush(fd, TCIOFLUSH);        if(tcsetattr(fd, TCSANOW, &new_opt) != 0)        {            printf("Error on tcsetattr! [%d:%s]!\n", errno, strerror(errno));            rtn = -1;        }    }    printf("set the parameter ok!\n");    return rtn;}/************************************************************************ * Function_name: serial_send * Description: send data to the serial device * Input:         1. int fd: device description        2. char *p_buf: the send data buffer        3. int len: the data length * Output: None * Return:         >=0:    on succeed        -1:     input argument illegal        -2:     write data error * * Autor        Time            Content * Jimmy    2018-04-05          Create   * ************************************************************************/int serial_send(int fd, char *p_buf, int len){    int wr_len = -1;    if((fd < 0) || (NULL == p_buf) || (len < 0))    {        printf("Input arguments are illegal!\n");        return -1;    }    wr_len = write(fd, p_buf, len);    if(wr_len < 0)    {        printf("write %d bytes failed!\n", len);        return -1;    }    return wr_len;}/************************************************************************ * Function_name: serial_recv * Description: recv the data from serial device * Input:         1. int fd: device description        2. char *p_buf: the recv data buffer        3. int len: the data length * Output: None * Return:         >=0:    on succeed        -1:     input argument illegal        -2:     write data error * * Autor        Time            Content * Jimmy    2018-04-05          Create   * ************************************************************************/int serial_recv(int fd, char *p_buf, int len){    int rd_len = 0;    if((fd < 0) || (NULL == p_buf) || (len <= 0))    {        printf("Input arguments are illegal!\n");        return -1;    }    rd_len = read(fd, p_buf, len);    if(rd_len < 0)    {        printf("write %d bytes failed!\n", len);        return -2;    }    return rd_len;}/************************************************************************ * Function_name: serial_recv_pthread * Description: read data thread, used to read the serial device port * Input:         1. void *data: the data that transfer to the thread  * Output: None * Return: None * * Autor        Time            Content * Jimmy    2018-04-05          Create   * ************************************************************************/void * serial_recv_pthread(void *p_data){    char recv_buf[RECV_LEN];    int rtn_val = 0;    int len = 0;    int recv_len = 0; //total received data length    fd_set rdfs;    struct timeval tv;    while(FALSE == THREAD_EXIT)    {        //1. set the read fd set        FD_ZERO(&rdfs);        FD_SET(*(int *)p_data, &rdfs);                tv.tv_sec = 5;  //Delay time is 5 seconds        tv.tv_usec = 0;        //2. wait the serial port data comming        rtn_val = select(*(int *)p_data+1, &rdfs, NULL, NULL, &tv);        if(rtn_val == -1)        {            printf("select failed!\n");            continue;        }        else if(0 == rtn_val)        {            printf("Time out[5 seconds]\n");            continue;        }        else        {            //3. read the port data to buffer            do{                len = serial_recv(*(int *)p_data, &recv_buf[recv_len], 128);                recv_len += len;            }while(len > 0);            printf("Received total length is %d\n", recv_len);        }    }        return (void *)0;}

2). 发送数据

数据有三个自由度(x,y,yaw),我们设计了一个如上图所示的轨迹,没200mm产生一个坐标点(循环产生)。

mark

mark

/************************************************************************ * Function_name: calc_checksum  * Description: calc the data crc  * Input:         1. char *buf: data buffer        2. int data_len: the buffer data length * Output: None * Return:  crc number * * Autor        Time            Content * Jimmy    2018-04-05          Create   * ************************************************************************/char calc_crc(char *buf,int data_len){    int i = 0;    char sum;    unsigned short tmp = 0;        while (i < data_len)    {        tmp += ((unsigned char)buf[i]);        i++;    }    tmp = tmp & 0x00ff;    sum = tmp ;        return sum;}/************************************************************************ * Function_name: send_data * Description: send the data to device[data is eaggle, 4*4 sq.m] * Input:         1. void *data: the data that transfer to the thread  * Output: None * Return: None * * Autor        Time            Content * Jimmy    2018-04-05          Create   * ************************************************************************/int send_data(int fd){    int rtn = 0;    int i=0;    int y_dir = 1;    int x_dir = 1;    int x=0;     int y=0;    int yaw = 0;    map_coor_t t_map_coor;    memset(&t_map_coor, 0, sizeof(map_coor_t));    t_map_coor.head[0] = 0xEE;    t_map_coor.head[1] = 0xFF;    t_map_coor.cmd_type = 0x01;    t_map_coor.type = 0x00;        while(FALSE == THREAD_EXIT)    {        x += 200*x_dir;        if(x >= 20000)        {            x = 20000;            x_dir = -1;            yaw = 31416;            goto FLAG_1;        }        if(x <= -20000)        {            x = -20000;            x_dir = 1;            yaw = 0;            goto FLAG_1;        }        if(y >= 20000)        {            y = 20000;            y_dir = -1;            yaw = 15708;        }        if(y <= -20000)        {            y = -20000;            y_dir = 1;            yaw = -15708;        }        goto FLAG_2;        FLAG_1:        for(i=1; i<=10; i++)        {            y += 200*y_dir;            {                t_map_coor.x = x;                t_map_coor.y = y;                t_map_coor.yaw = (y_dir==1)? 15708:-15708;                 t_map_coor.crc = calc_crc((char *)&t_map_coor, sizeof(map_coor_t)-1);                 printf("x=%d, y=%d, yaw=%d\n", x, y, t_map_coor.yaw);                sleep(1);                serial_send(fd, (char *)&t_map_coor, sizeof(t_map_coor));            }        }        FLAG_2:        {            t_map_coor.x = x;            t_map_coor.y = y;            t_map_coor.yaw = yaw;            t_map_coor.crc = calc_crc((char *)&t_map_coor, sizeof(map_coor_t)-1);             printf("x=%d, y=%d, yaw=%d\n", x, y, yaw);            sleep(1);            serial_send(fd, (char *)&t_map_coor, sizeof(t_map_coor));        }    }    return rtn;}

**3). main函数

/************************************************************************************* * Filename:  * Autor: Jimmy  2018-04-05 * ************************************************************************************/ #include 
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define SERIAL_PORT 1#define RECV_LEN 1024#define TRUE 0#define FALSE 1#define PACKED __attribute__ ((packed)) //Cancel byte alignmen/************************************************************************ * Function_name: installsig * Description: install the SIGINT and SIGTERM signal * Input: 1. * Output: None * Return: None * * Autor Time Content * Jimmy 2018-04-05 Create * ************************************************************************/void sigroutine(int signo){ if(g_serial_fd == -1) { printf("g_serial_fd was not init !!\n"); } else { close(g_serial_fd); } THREAD_EXIT = TRUE;} void installsig() { struct sigaction act; sigemptyset(&act.sa_mask); act.sa_flags = SA_RESETHAND; act.sa_handler = sigroutine; if (sigaction(SIGINT,&act,NULL) < 0) { printf("install sigal error\n"); } else { printf("install for sigTERM \n"); } if (sigaction(SIGTERM,&act,NULL) < 0) { printf("install sigal error\n"); } else { printf("install for sigTERM \n"); }}/************************************************************************ * Function_name: main * Description: * Input: 1. * Output: None * Return: None * * Autor Time Content * Jimmy 2018-04-05 Create * ************************************************************************/int main(int argc, char *argv[]){ int fd = -1; int rtn = 0; pthread_attr_t thread_attr; pthread_t serial_id; if(argc != 2) { printf("argc error! argc=%d\n", argc); return -1; } //0. install the sigaction installsig(); int serial_port = atoi(argv[1]); printf("serial_port=%d\n", serial_port); //1. open the serial port //fd = open_port(SERIAL_PORT); fd = serial_open(serial_port); if(fd == -1) { exit(EXIT_FAILURE); } g_serial_fd = fd; //2. set the serial port parameters rtn = set_parm(fd, 115200, 8, 1,'N' ); if(rtn != 0) { exit(EXIT_FAILURE); } //3. start the read thread pthread_attr_init(&thread_attr); pthread_attr_setdetachstate(&thread_attr,PTHREAD_CREATE_DETACHED); //detached the thread, with mian thread wait pthread_create(&serial_id,&thread_attr, serial_recv_pthread, NULL); //4. send the data to serail port_ send_data(fd); return 0;}

转载于:https://www.cnblogs.com/Jimmy1988/p/8722352.html

你可能感兴趣的文章
spring mvc 基于注解 配置默认 handlermapping
查看>>
半小时学会上传本地项目到github
查看>>
Android学Jni/Ndk 开发记录(一)
查看>>
Linux Tcl和Expect的安装
查看>>
WPF中的依赖项属性(转)
查看>>
linux防火墙相关 iptables
查看>>
最简单的单例模式
查看>>
JPopupMenu的使用以及JPopupMenu中子组件的事件处理
查看>>
从反汇编的角度看引用和指针的区别
查看>>
拓马长枪定乾坤
查看>>
UIProgressView的详细使用
查看>>
Silverlight实用窍门系列:70.Silverlight的视觉状态组VisualStateGroup
查看>>
照片筛选与上传功能
查看>>
Hello ZED
查看>>
常见web攻击方式
查看>>
hdu 4472
查看>>
oracle存储过程中is和as区别
查看>>
windows 2003 群集
查看>>
几个gcc的扩展功能
查看>>
Spark一个简单案例
查看>>