zoukankan      html  css  js  c++  java
  • 串口编程(二)

    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, '', 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]
    ", 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]
    ", 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
    ");
                    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
    ");
                    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!
    ");
                    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]!
    ", errno, strerror(errno));
                rtn = -1;
            }
        }
    
        printf("set the parameter ok!
    ");
        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!
    ");
            return -1;
        }
    
        wr_len = write(fd, p_buf, len);
    
        if(wr_len < 0)
        {
            printf("write %d bytes failed!
    ", 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!
    ");
            return -1;
        }
    
        rd_len = read(fd, p_buf, len);
    
        if(rd_len < 0)
        {
            printf("write %d bytes failed!
    ", 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!
    ");
                continue;
            }
            else if(0 == rtn_val)
            {
                printf("Time out[5 seconds]
    ");
                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
    ", 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
    ", 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
    ", 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 <stdio.h>
    #include <string.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <errno.h>
    #include <termios.h>
    #include <sys/time.h>
    #include <sys/time.h>
    #include <time.h>
    #include <stdlib.h>
    #include <pthread.h>
    #include <signal.h>
    
    #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 !!
    ");
    	}
    	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
    ");
    		
    	}
    	else
    	{
    		printf("install for sigTERM 
    ");
    	}
    
    	if (sigaction(SIGTERM,&act,NULL) < 0)
    	{
    		printf("install sigal error
    ");
    	}
    	else
    	{
    		printf("install for sigTERM 
    ");
    	}
    }
    
    /************************************************************************
     * 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
    ", argc);
    	    return -1;
        }
    	
    	//0. install the sigaction
    	installsig();
    	
        int serial_port = atoi(argv[1]); 
        printf("serial_port=%d
    ", 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;
    }
    
    
  • 相关阅读:
    [zz] 从VMM中终止GUEST OS中运行进程
    [zz]Linux流量监控工具 – iftop (最全面的iftop教程)
    [zz]Ubuntu终端下Nethogs网络流量监控工具
    AtomicBoolean运用
    JDK中的URLConnection参数详解
    java读取文本文件数据
    tomcat时区设置
    java的upload
    java复习(set 、list、map)
    NIO学习笔记1
  • 原文地址:https://www.cnblogs.com/Jimmy1988/p/8722352.html
Copyright © 2011-2022 走看看