linux 阻塞/非阻塞模式下触摸框数据的获取

linux 在针对文件进行IO读写时,存在几种方式,非阻塞模式,阻塞模式也即非同步,同步模式。两个不同的模式读取数据时,同是read获取,但是返回值可能不一样。

非阻塞模式

此种模式下,需要不停的轮询获取数据,且设置的时间周期需要参考对应设置的时间周期,多次调试才可达到最优。下面分享一下串口非阻塞模式读取的基本流程。

  1. open
input_fd = open("/dev/ttyS1", O_RDWR | O_NOCTTY | O_NDELAY);
此处使用O_NDELAY来设置非阻塞模式。O_NDELAY 是system V早起版本引入的,后续尽量使用POSIX  规定的O_NONBLOCK,允许多次打开时必须设成非阻塞模式.。
这样产生的结果就是在读取不到数据 或者 写入的缓存区满了 马上会return,而不会阻塞等待。 在读取操作时,读取到文件末尾是返回的是0;读不到数据时也会马上返回,但值是-1 并且设置erron 为EAGAIN。
  1. fctnl
    fctnl 是通过设备文件设置文件属性,此处也是可以设置为非阻塞模式的。
	fcntl(input_fd, F_SETFL, FNDELAY); 
设置FNDELAY 属性是为了read 时,在没有数据时返回0,实际好像还是-1
  1. select
while(1){
        FD_ZERO(&r_fds);
        FD_SET(input_fd, &r_fds);
        //set Time Out
        //sys.boot_completed
        memset(&timeout,0x00,sizeof(timeout));
        timeout.tv_sec = 0;
        timeout.tv_usec = 3*1000; // 3 ms
        ret = ::select(input_fd + 1, &r_fds, NULL, NULL, &timeout);
        if(ret == 0)
        {
            continue;
        }
        else if(ret < 0)
        {
            break;
        }
        else if((ret > 0) && FD_ISSET(input_fd, &r_fds))
        {
        	//  read the data bytes
        }
}

监听描述符对应的设备文件是否有IO操作,并设置轮询的时间周期(第四个时间参数不能为NULL)。更多select 操作https://www.cnblogs.com/stupidoliver/p/8760480.html
https://www.cnblogs.com/alantu2018/p/8612722.html

  1. read

阻塞模式

此种模式下,只需要设置好阻塞模式,只要有数据过来,马上触发数据读取流程,类似中断处理。

  1. open
input_fd = open("/dev/ttyS1", O_RDWR | O_NOCTTY );
打开文件时,去掉O_NDELAY/O_NONBLOCK参数。
  1. fctnl
	fcntl(input_fd, F_SETFL, 0); 
设置F_SETFL项时,将value置为0,则为阻塞模式。
  1. select
while(1){
        FD_ZERO(&r_fds);
        FD_SET(input_fd, &r_fds);
        ret = ::select(input_fd + 1, &r_fds, NULL, NULL, NULL);
        if(ret == 0)
        {
            continue;
        }
        else if(ret < 0)
        {
            break;
        }
        else if((ret > 0) && FD_ISSET(input_fd, &r_fds))
        {
        	//  read the data bytes
        }
}

监听描述符对应的设备文件是否有IO操作,第四个时间参数设置为NULL,有数据过来才会往下走

  1. read
int readFullTouchData(int fd, unsigned char* data, unsigned int nLen)
{
    int nRet = -1;
    int nContentRet = -1;
    int n_offset = 0;
    unsigned char unContentBuf[DATA_CONTENT_SIZE];
    input_fd = fd;

    // 1: get the right touch data head code
    // 2: get the check touch devie
    // 0: get the check touch devie
    nRet = checkHeadCode(input_fd);
    if(nRet == 0){
        printf("\033[41;32m [%s][%d] can`t find the available data \033[0m \n",__FUNCTION__,__LINE__);
        return -1;
    }

    // get the correct check code
    if(nRet == 2){
        return 2;
    }
    // save the head code to buffer
    memcpy(data, headerData, (DATA_LEN_SIX - DATA_CONTENT_SIZE));
    n_offset += (DATA_LEN_SIX - DATA_CONTENT_SIZE);

    //  read the content data
    memset(unContentBuf, 0x00 , DATA_CONTENT_SIZE*sizeof(unsigned char));
    nContentRet = readDataBytes(input_fd, unContentBuf, DATA_CONTENT_SIZE);
    printf("\033[41;32m [%s][%d] read data bytes. nContentRet = %d \033[0m \n",__FUNCTION__,__LINE__,nContentRet);
    if(nContentRet <= 0){
        return -1;
    }

    memcpy((data + n_offset), unContentBuf, DATA_CONTENT_SIZE * sizeof(unsigned char));
    // show the touch data
    showTouchData(data, DATA_LEN_SIX);
    return 1;

}

readFullTouchData 读取完整一个触摸数据包,包含头码检测,数据内容(坐标,宽度,up、down)。

int checkHeadCode(int nFileFd)
{
    unsigned char ucHeadCode[DATA_LEN_SIX - DATA_CONTENT_SIZE];
    unsigned char ucSingle = 0x00;
    unsigned int  unLoop = 0;
    bool bFind = false;
    int  nCnt = 0;
    // check head code
    memset(ucHeadCode, 0x00, sizeof(ucHeadCode));
    while(unLoop < DATA_LEN_SIX){
        nCnt = read(nFileFd, &ucSingle, 1);
        if(nCnt == 1 && ucSingle == headerData[0]){
            // find the 0x1F  (headcode: 0x1F, 0xF7, 0x43)
            ucHeadCode[0] = headerData[0];
            bFind = true;
            break;
        } else {
            unLoop++;
        }
    }

    if(!bFind){
        printf("\033[41;32m [%s][%d] can`t find the head code 0x1F . \033[0m \n",__FUNCTION__,__LINE__);
        return 0;
    }

    // read the other two head code (0xF7, 0x43)
    nCnt = read(nFileFd, (ucHeadCode + 1), (sizeof(ucHeadCode) - 1));
    printf("\033[41;32m [%s][%d] <0x%02x 0x%02x 0x%02x > \033[0m \n",__FUNCTION__,__LINE__,\
                 ucHeadCode[0],ucHeadCode[1],ucHeadCode[2]);
    // check
    if(ucHeadCode[0] == headerData[0] && ucHeadCode[1] == headerData[1] && \
       ucHeadCode[2] == headerData[2]){
        return 1; // touch data head
    } else if(ucHeadCode[0] == chkBackCode[0] && ucHeadCode[1] == chkBackCode[1] && \
              ucHeadCode[2] == chkBackCode[2]){
        return 2; // check data head
    }

    return 0;
}

checkHeadCode 读取三个字节的数据匹配头码,成功后再读取内容。

// return value
// 1.  >  0 --> success
// 2.  =  0 --> read error
// 3.  = -1 --> hava no data comming
// 4.  = -2 --> param erro
int readDataBytes(int nFileFd, unsigned char buffer[], int nSize)
{
    int nRet = 0;
    unsigned int unCntBytes = 0;
    unsigned char tmpbuf[DATA_LEN_SIX]; // for buffer headcode or content data
    unsigned char *pTmpbuf = tmpbuf;
    if(nFileFd < 3 || buffer == NULL || nSize < 1){
        return PARAM_ERR;
    }
    printf("\033[41;32m [%s][%d] buffer = %p , nSize = %d  \033[0m \n", __FUNCTION__,__LINE__,buffer,nSize);
    memset(buffer, 0x00, nSize);
    memset(tmpbuf, 0x00, DATA_LEN_SIX);
    while(unCntBytes < nSize){
        nRet = read(nFileFd, pTmpbuf, (nSize-unCntBytes));
        if(nRet <= 0){
            // read the end of the file  or  have no data coming
            printf("\033[41;32m [%s][%d] nRet = %d. [0: file end , -1: no data (EAGAIN)] \033[0m \n", __FUNCTION__,__LINE__,nRet);
            return DATA_EMPTY;
        } else {
            // nRet bytes data coming
            pTmpbuf += nRet; // offset the point of the temp buffer
            unCntBytes += nRet;
        }
    }
    // output the bytes
    if(unCntBytes >= nSize){
        memcpy(buffer, tmpbuf, nSize*sizeof(unsigned char));
        nRet = unCntBytes;
    }
    return nRet;
}

readDataBytes 读取触摸协议的原始数据。内部循环读取,读取完整之后返回。

串口编程参数说明

此处有博主分享的一篇很好的文章
https://blog.csdn.net/flfihpv259/article/details/53786604

尤其主要c_cc[VTIME],c_cc[VMIN] 对read 函数的影响。

发布了101 篇原创文章 · 获赞 19 · 访问量 33万+

猜你喜欢

转载自blog.csdn.net/kehyuanyu/article/details/101756151