1. 程式人生 > >串列埠高效能處理串列埠資料,按位讀取處理案例

串列埠高效能處理串列埠資料,按位讀取處理案例

在現在的工控或者家用裝置通訊專案中,用到很多串列埠或者類串列埠通訊協議,其中 很多協議需要讀取操作,在讀取中為了防止阻塞,提高處理效能,縮短處理時間經常用到 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>>>>>>>>>>>>>>>> ------------\n"); 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\n", device); return -1; } set_speed(); if (set_parity() < 0){ printf("set parity error !\n"); 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!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); 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.\n"); } //printf("get out a serial data!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); //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!\n"); return ret; } } int uni_recv_protocol(unsigned char* buf, int n) { int rc, i; int count = 0; fprintf(stderr,"GET serial<<<<<<<<<<<<< ------------\n"); 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 \n", 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 !!!!!!!!!!!!!!!!\n");
                //printf("send >>>>>>>>>>\n");
                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!\n");
                    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 !!!!!!!!!!!!!!!!\n");
            for(i =0; i < i_uart_index; i++){
                printf("%02X \n", 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!!!!!!!!!!!!!!!!\n");
                //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!\n");
                    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!!!!!!!!!!!!!!!!\n");
                i_uart_index = 0;
            }
        }else{
            i_uart_index = 0;
        }
    
    }
}




int main()
{
    
    uni_InitUart();
    uni_InitUart_recv_pthread();
    return 0;
}

相關推薦

串列高效能處理串列資料讀取處理案例

在現在的工控或者家用裝置通訊專案中,用到很多串列埠或者類串列埠通訊協議,其中 很多協議需要讀取操作,在讀取中為了防止阻塞,提高處理效能,縮短處理時間經常用到 select 函式來 讀取串列埠資料,select 是linux 真是個 神器啊,監控某一個檔案或者裝置,當有緩衝過來即可處理,而為了試用不同協議的長短

c#串列seralport接收發送資料生成chart折線圖並儲存

剛剛從頭開始學習c#,在查詢資料過程中,感覺各位大神寫的太高深了,這裡是我寫的一個串列埠程式,希望與同我一樣的小白們一同努力,不要放棄,向更深一步加油吧;程式要求:與兩個串列埠進行通訊,定時發出資料,對返回的資料進行處理(幀頭幀尾識別),經過演算法,得到一組資料,並將其輸出到

串列除錯助手上輸入資料然後再數碼管顯示(C語言版本)

//串列埠除錯助手上輸入資料,然後再數碼管顯示 #include <reg52.h> #include "uart.h"   //數碼管從0-F uint8 number[]={0x0c0,0x0F9,0x0A4,0x0B0,     0x99,0x92,0x8

在HAL庫的基礎上修改串列中斷函式使串列中斷接收不定長資料且不發生丟失現象。

        之前一直用STM32CUBE配置工程,但是一用到USART1的DMA接收中斷,或者USART1的接收中斷,就會出現問題,在之前的除錯中發現USART1的DMA與ADC1的DMA有衝突(原因我也不造啊),後來將USART1的DMA接收中斷改成USART1的接收中

處理20億資料實時使用者行為服務系統架構實踐

攜程實時使用者行為服務作為基礎服務,目前普遍應用在多個場景中,比如猜你喜歡(攜程的推薦系統)、動態廣告、使用者畫像、瀏覽歷史等等。 以猜你喜歡為例,猜你喜歡為應用內使用者提供潛在選項,提高成交效率。旅行是一項綜合性的需求,使用者往往需要不止一個產品。作為一站式的旅遊服務平臺,跨業務線的推薦,特別是實

利用柵格處理list集合資料使每行顯示兩條或者多資料時候

這個是微信小程式的框架,TouchUI,做頁面查詢資料是list的物件,但是要用柵格每行顯示兩條資料 <ui-row wx:for="{{resumeCoverImg}}" wx:key="unique" class="resumeCoverImg">

C# 多執行緒+佇列處理大批量資料進而縮短處理時間

public void DealData(){                int pageSize = 200; //建立佇列                         var queue = new MessageQueueManager<Model>

IE瀏覽器無法載入資料F12就可以載入

Root cause: 程式碼裡用到console物件,而某些版本的IE不開控制檯,是沒有這個物件的。 因為上下文中沒有console這個物件, 所以就直接拋異常了,但是不開啟控制檯看不到。打開了控制檯,上下文中就有這個物件,所以就不會拋錯了 Action: 1.刪除co

用spark分析北京積分落戶資料使用者所在單位分析

載入剛才解析json格式儲存而成的csv檔案。 按使用者所在單位分析 df = spark.read.format("csv").option("header", "true").load("jif

用spark分析北京積分落戶資料使用者年齡分析

載入剛才解析json格式儲存而成的csv檔案。 按使用者年齡分析 df = spark.read.format("csv").option("header", "true").load("jifen

把excel中的資料條件分割成多個檔案

要求 有個excel檔案,把檔案中的資料按照某列,將相同的資料存為一個excel檔案。 VBA程式碼 執行下面的程式碼後,會在該excel的同級目錄下建立一個新資料夾“拆分出的表格”,拆分後生成的新檔案會存在這個目錄下。 我拆分了30個檔案,大約一分

用spark分析北京積分落戶資料使用者分數分析

按使用者分數分析 #匯入積分落戶人員名單資料 sqlContext = SQLContext(sc) df = sqlContext.read.format('com.databricks.spark

matlab 在批量處理csv檔案資料的時候常用的處理函式

本篇文章中我將完成如何大批量處理csv檔案的資料。首先講解程式裡用到的函式。 在此之前,向新手科普一下matlab註釋多行的小技巧:註釋:ctrl+r  取消註釋:ctrl+t 1、str = strrep(str1, str2, str3) 用於刪掉某些不需要的符號,比

異或取反

spa 位運算 符號 targe 取反 span 特殊性 一個 target 位運算符:是指對二進制位從低位到高位對齊後進行運算。 1、按位與 & 二進制“與”運算規則:1&1=1 1&0=0 0&0=0 例如

讀取位元組讀取

現代儲存器基本儲存單元都是以位元組為單位, 這樣就設立了按位元組來編號地址,如000代表0地址,001代表了1地址……,這樣一個個按位元組為單位的空間組成了整個大的儲存器 所謂的按位元組都取就是,給第一個地址編號,CPU從儲存器相對應的地址編號中讀取一個位元組的資料。 下面來說下按字讀取,字是一個不定大小

非 ~ 處理等同於indexof

就來看看~1的計算步驟: 將1(這裡叫:原碼)轉二進位制 = 00000001 按位取反 = 11111110 發現符號位(即最高位)為1(表示負數),將除符號位之外的其他數字取反 = 10000001 末位加1取其補碼 =

leetcode_461. Hamming Distance 計算漢明距離異或運算計算整數的二進位制表示中1的個數 java

題目: The Hamming distance between two integers is the number of positions at which the corresponding bits are different. Given two int

java中複製文字檔案的方式我總結為14種(字元讀取4中位元組讀取8種!??)

java中複製檔案的方式 如果按照字元來讀取的話,可以有4種,基本的2種,高效的2種,高效特殊的1種 第0種: public class CopyFileDemo { public static void main(String[] args) throws Except

在linux上寫好串列程式後利用windows上的串列除錯助手互發資料

我是用QT4在Linux上寫的串列埠程式,具體的程式碼就不寫了,網上搜一下很多。這裡主要說一下寫完程式碼之後,之前也行。要做的事情。 1,使用命令在終端上檢視有哪些串列埠驅動。 可以看出ttyS0 ttyS1能用 .一般ttyS0指com1,ttyS1指co

串列除錯助手上輸入資料0-9然後再數碼管顯示(組合語言版本)

//實驗目的:串列埠除錯助手上輸入資料0-9,然後再數碼管顯示 org 00H ljmp start org 23H //中斷入口地址 ljmp uart_interrupt  org 30H start:               mov P0,#0xff//設定