zoukankan      html  css  js  c++  java
  • 串口高性能处理串口数据,按位读取处理案例

    在现在的工控或者家用设备通信项目中,用到很多串口或者类串口通信协议,其中 很多协议需要读取操作,在读取中为了防止阻塞,提高处理性能,缩短处理时间经常用到 select 函数来 读取串口数据,select 是linux 真是个 神器啊,监控某一个文件或者设备,当有缓冲过来即可处理,而为了试用不同协议的长短不一,比如心跳包,和数据包,的处理不同,比较合适的做法就是按位读取,当是心跳包的头时,读取接下来的心跳包,处理心跳。当是数据包的时候,读取接下来的数据包,处理数据包。以下是串口读取案例

    接口函数 uart_raw.c:

    //#include "uni_serial.h"
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <termios.h>
    #include <errno.h>
    #include <limits.h>
    #include <unistd.h>
    #include <string.h>
    #include <signal.h>
    #include <pthread.h>
    
    //extern int deal_with_uart_byteBybyte(char buffer);
    
    
    /*
    typedef struct node  
    {  
        char p_send_buff[61];;  
        node* pNext;  
    }Node;
    
    Node* head = NULL;
    
    //创建链表,头结点data=0,pNext=NULL; 
     
    bool createNodeList()  
    {  
        head = (Node*) malloc(sizeof(Node));  
        if(NULL == head)  
        {  
            return false;  
        }  
        else  
        {  
            memset(head->p_send_buff,0,sizeof(char)*61);
            head->pNext = NULL;  
            return true;  
        }  
    }  
    
    
    
    Node* init_node(char *buff )
    {
        Node* node = (Node*)malloc(sizeof(Node));
        int i=0;
        
        for(i=0;i<61;i++)
           head->p_send_buff[i]=buff[i];
        
        node->pNext = NULL;  
        return node2;
    }
    
    
    //增加节点  
    bool addNode(Node* node)  
    {  
        if(NULL == head)  
        {  
            return false;  
        }  
        
        Node* p = head->pNext;  
        Node* q = head;  
        while(NULL != p)  
        {  
            q = p;  
            p = p->pNext;  
        }  
        q->pNext = node;  
        node->pNext = NULL; 
        
        return true;      
    }  
    
    
    //遍历节点
    int num_node(Node* node)
    {
        int num_n=0;
        if(NULL == head)  
        {  
            return 0;  
        }  
        Node* p = head->pNext;  
        //Node* q = head;
        
        while(NULL != p)  
        {  
            //q = p;  
            p = p->pNext;  
            num_n++;
        }  
        return num_n;
    }
    
    
    
        
    //删除节点  
    bool deleteNode(int index)  
    {  
        if(NULL == head)  
        {  
            return false;  
        }  
        Node* p = head->pNext;  
          
        int length = 0;  
        while(NULL != p)  
        {  
            length ++;  
            p = p->pNext;  
        }  
      
        if(length < index)  
        {  
            return false;  
        }  
        else  
        {  
            Node* q = head;  
            p = head;  
            for(int i=0;i<index;i++)  
            {  
                q = p;  
                p = p->pNext;  
            }  
            Node* t = p->pNext;  
            q->pNext = t;  
            free(p);  
            return true;  
        }  
    }  
    
    
    int send_reoute()
    {
        
        
        while(num_node(uart_node) > 5)
        {
            Node* p = head->pNext;  
            Node* q = head;
            //遍历到最后一个节点 
            
            
            while(NULL != p)  
            {  
                //q = p;  
                p = p->pNext;  
            }
            
            // 发送最后一个数据的 BUFF
            // 删除最后一个 节点
            // 释放最后一个节点 内存 指针
            // 长度 减少 
                    
            
    
        }
        
        return 0;
    }
    
    */
    
    
    
    
    
    
    
    
    
    
    
    int deal_with_uart_byteBybyte(unsigned char buffer);
    
    
    int uart_fd;
    int uart_flag_ok=0;
    struct termios options;
    speed_t speed;
    
    //speed=B2400;
    
    
    
    unsigned char  BCC_CheckSum(unsigned char *buf, int len)
    {
        unsigned char i;
        unsigned char checksum = 0;
    
        for(i = 0; i < len; i++) {
            checksum ^= *buf++;
        }
        return checksum;
    } 
    
    
    
    int uni_send_protocol(const unsigned char* buf, int n)
    {
        //tcflush(uart_fd, TCIOFLUSH);
        int rc = 0;
        int i = 0;
        
        fprintf(stderr,"SEND serial>>>>>>>>>>>>>>>> ------------
    ");
        for(i = 0; i < n; i++){
           
            printf("%02X ", buf[i]);
           
            
        }
        
        rc = write(uart_fd, buf, n);
        sync();
        usleep(5000);//5ms
        tcflush(uart_fd, TCIOFLUSH);
        return rc;
    }
    
    
    
    
    
    
    int set_speed() // 波特率 9600 
    {
        int status;
        //struct termios opt;
        tcgetattr(uart_fd,&options);
        tcflush(uart_fd,TCIOFLUSH);
        //cfsetispeed(&options,speed);
        cfsetispeed(&options,B9600);
        
        status = tcsetattr(uart_fd,TCSANOW,&options);
        if(0 != status){
            perror("error: tcsetattr failed!");
            return -1;
        }
    
        tcflush(uart_fd,TCIOFLUSH);
        return 0;
    }
    
    
    
    
    int set_option()
    {
    
        cfmakeraw(&options);/* 配置为原始模式 */
        options.c_cflag &= ~CSIZE;
    
        options.c_cflag |= CS8;
        //options.c_cflag &= ~PARENB;
        
        
        //opt.c_cflag |= CS8;
        
        //校验位  偶校验 
        options.c_cflag |= PARENB;
        
        
        options.c_cflag &= ~PARODD;
        options.c_iflag |= INPCK;
        
        //停止位
        options.c_cflag &= ~CSTOPB;
        
        /*设置等待时间和最小接收字符*/
        options.c_cc[VTIME] = 0;
        options.c_cc[VMIN] = 1;
    
        return 1;
    }
    
    
    
    int set_parity()
    {
    
        if (tcgetattr(uart_fd,&options)!=0) {
            perror("error set_parity:tcgetattr.");
            return -1;
        }
    
        set_option();
    
        if (tcsetattr(uart_fd,TCSANOW,&options) != 0) {
            perror("error set_parity:tcsetattr");
            return -1;
        }
    
        tcflush(uart_fd,TCIOFLUSH);
        return 0;
    }
    
    
    int uni_InitUart()
    {
        const char device[] = "/dev/ttyS2"; 
        int flags = O_RDWR | O_NOCTTY | O_NDELAY |O_SYNC;
    
        uart_fd = open(device, flags );
        if(-1 == uart_fd){
            printf("open %s failed
    ", device);
            return -1;
        }
    
        set_speed();
        if (set_parity() < 0){
            printf("set parity error !
    ");
            return -1;
        }
    
        return uart_fd;
    }
    
    
    int Uart_receive_callBack(char p, int (*ptr)()) 
    {
        (*ptr)(p);
    }
    
    
    
    
    void* run_uart_receive_pid()
    {
        int rc;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           char buffer;
        unsigned char buffer1;
        fd_set rfds;
        struct timeval tv;
        int retval;
        int ret;
    
        while(1)
        {
            FD_ZERO(&rfds);
            FD_SET(uart_fd, &rfds);
    
            tv.tv_sec = 1;
            tv.tv_usec = 1000;
            retval = select(uart_fd + 1, &rfds, NULL, NULL, &tv);
            
            //fprintf(stderr,"select!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    ");
    
            if (retval < 0)
                perror("select()");
            else if (retval)
            {
                if(FD_ISSET(uart_fd, &rfds) )
                {
                    rc = read(uart_fd, &buffer, 1);
                    if(rc >= 0){
                        //printf("%02X ", buffer);
                    }
                    Uart_receive_callBack(buffer, deal_with_uart_byteBybyte);// 读取一个处理一个 
                    buffer=0x00;
                    uart_flag_ok=1;
                }
            }else{
                //return 1;
                //printf("No data within few times.
    ");
            }
    
        //printf("get out a serial data!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    ");
        //tcflush(uart_fd, TCIOFLUSH);
        }
    }
    
    
    int uni_InitUart_recv_pthread()
    {
        pthread_t uart_receive_pid;
    
        int ret = pthread_create(&uart_receive_pid,  NULL, &run_uart_receive_pid, NULL);
        if (ret != 0)
        {
            fprintf(stderr,"%s","uni_receive_serial pthread_create fail!
    ");
            return ret;
        }
    }
    
    
    
    int uni_recv_protocol(unsigned char* buf, int n)
    {
        int rc, i;
        int count = 0;
        fprintf(stderr,"GET serial<<<<<<<<<<<<< ------------
    ");
        for(i = 0; i < n; i++){
            rc = read(uart_fd, &buf[i], 1);
            printf("%02X ", buf[i]);
            if(rc <= 0){
                return rc;
            }
            count++;
        }
    
        tcflush(uart_fd, TCIOFLUSH);
        return count;
    }
    
    
    
    
    
    void uni_release_serial()
    {
        close(uart_fd);
    }
    View Code

    主函数调用实例函数:

    处理函数最好做成回调函数,在引用文件中直接用 extern 来注明外部函数即可。

    extern int deal_with_uart_byteBybyte(char buffer);
    
    int i_uart_index;
    int length_uart;
    
    char buffer_command[16];
    char old_command[16];
    
    
    
    
    
    
    
    int deal_with_uart_byteBybyte(char buffer)
    {
        int i ;
        int count_sum = 0;
        //printf("%02X 
    ", buffer);
    
        if(i_uart_index == 0){ //判断第一个位 
            if(buffer == 0xf1){// 主机心跳包 
                length_uart = 1;
                buffer_command[0] = buffer; //buff == 0xf1 
                i_uart_index++;
            }else if(buffer == 0x11){//主机数据帧 
                buffer_command[0] = buffer;
                i_uart_index++;
            }
        }else if(i_uart_index == 1){ //判断第二个位数 
            if(buffer_command[0] == 0xf1){
                if(buffer == 0x7a){
                    printf("get a heart beat message !!!!!!!!!!!!!!!!
    ");
                    //printf("send >>>>>>>>>>
    ");
                    char buff_heart[2]={0};
                    buff_heart[0]=0XF9;
                    buff_heart[1]=0X7A;
                    //char buff_heart[8]={0XBB,0X00,0X01,0X04,0X02,0X01,0X00,0XBD};
                    if(uni_send_protocol(buff_heart,2) < 0)
                    {
                        printf("write ERROR!
    ");
                        return 0;
                    }
                    i_uart_index = 0;
                }
            }else if(buffer_command[0] == 0x11){
                length_uart = buffer - 0x00;
                buffer_command[1] = buffer;
                i_uart_index++;
            }
        }else{ //判断之后的位数  
            if((length_uart+3) > i_uart_index && 16 > i_uart_index){
                buffer_command[i_uart_index] = buffer;
                i_uart_index++;
            }else if ((length_uart+3) == i_uart_index){
                printf("get a data message !!!!!!!!!!!!!!!!
    ");
                for(i =0; i < i_uart_index; i++){
                    printf("%02X 
    ", buffer_command[i]);
                    //old_command[i]=buffer_command[i];//复制到 old_buff  
                }
                
                for(i =0; i < i_uart_index-1; i++){
                    count_sum += buffer_command[i] - 0x00;
                }
    
                if((count_sum % 256) == buffer_command[i_uart_index -1]){
                    printf("data command check OK!!!!!!!!!!!!!!!!
    ");
                    //int i=0;
                    
                    
                    
                    //TODO deal with command message
                    /*
                    char buff_heart[8]={0XBB,0X00,0X01,0X04,0X02,0X01,0X00,0XBD};
                    if(uni_send_protocol(buff_heart,8) < 0)
                    {
                        printf("write ERROR!
    ");
                        return 0;
                    }*/
                    
                    //第一次
                    
                    if(recved_times==1)
                    {
                        for(i =0; i < i_uart_index; i++){
                            old_command[i]=buffer_command[i];  
                        }
                        recved_times=0;//清零 只同步一次 
                    }
                    else{
                        deal_uart_buff(buffer_command,old_command,i_uart_index);
                        
                        for(i =0; i < i_uart_index; i++){
                            old_command[i]=buffer_command[i];  
                        }
                    }
                    
                    i_uart_index = 0;
                }else{
                    printf("data command check fail!!!!!!!!!!!!!!!!
    ");
                    i_uart_index = 0;
                }
            }else{
                i_uart_index = 0;
            }
        
        }
    }
    
    
    
    
    int main()
    {
        
        uni_InitUart();
        uni_InitUart_recv_pthread();
        return 0;
    }
  • 相关阅读:
    【设计模式
    【设计模式
    【设计模式
    【设计模式
    【设计模式
    【设计模式
    实干猪
    Mysql 千万级快速查询|分页方案
    如何成为一名优秀的CTO(首席技术官)
    成为优秀程序员的10个有效方法
  • 原文地址:https://www.cnblogs.com/hongzhunzhun/p/6541766.html
Copyright © 2011-2022 走看看