• [WinAPI] 串口读写


      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <windows.h>
      4 
      5 HANDLE hComm;
      6 OVERLAPPED m_ov;
      7 COMSTAT comstat;
      8 DWORD    m_dwCommEvents;
      9 
     10 //如果在调用CreateFile创建句柄时指
     11 //定了FILE_FLAG_OVERLAPPED标志,那么调用ReadFile和WriteFile对该句柄进
     12 //行的操作就应该是重叠的;如果未指定
     13 //重叠标志,则读写操作应该是同步的
     14 //在同步执行时,函数直到操作完成后才返回。这意味着同步执行时线程会被阻塞,从
     15 //而导致效率下降。在重叠执行时,即使操作还未完成,这两个函数也会立即返回,费
     16 //时的I/O操作在后台进行
     17 bool openport(char *portname)//打开一个串口
     18 {
     19     hComm = CreateFile(portname,
     20         GENERIC_READ | GENERIC_WRITE,
     21         0,
     22         0,
     23         OPEN_EXISTING,
     24         FILE_FLAG_OVERLAPPED,    
     25         0);
     26     if (hComm == INVALID_HANDLE_VALUE)
     27         return FALSE;
     28     else
     29         return true;
     30 }
     31 
     32 
     33 bool setupdcb(int rate_arg)
     34 {
     35     DCB  dcb;
     36     int rate= rate_arg;
     37     memset(&dcb,0,sizeof(dcb)); //在一段内存块中填充某个给定的值,是对较大的结构//体或数组进行清零操作的一种最快方法
     38     if(!GetCommState(hComm,&dcb))//获取当前DCB配置
     39     {
     40         return FALSE;
     41     }
     42     /* -------------------------------------------------------------------- */
     43     // set DCB to configure the serial port
     44     dcb.DCBlength       = sizeof(dcb);
     45     /* ---------- Serial Port Config ------- */
     46     dcb.BaudRate        = rate;
     47     dcb.Parity      = NOPARITY;
     48     dcb.fParity     = 0;
     49     dcb.StopBits        = ONESTOPBIT;
     50     dcb.ByteSize        = 8;
     51     dcb.fOutxCtsFlow    = 0;
     52     dcb.fOutxDsrFlow    = 0;
     53     dcb.fDtrControl     = DTR_CONTROL_DISABLE;
     54     dcb.fDsrSensitivity = 0;
     55     dcb.fRtsControl     = RTS_CONTROL_DISABLE;
     56     dcb.fOutX           = 0;
     57     dcb.fInX            = 0;
     58     /* ----------------- misc parameters ----- */
     59     dcb.fErrorChar      = 0;
     60     dcb.fBinary         = 1;
     61     dcb.fNull           = 0;
     62     dcb.fAbortOnError   = 0;
     63     dcb.wReserved       = 0;
     64     dcb.XonLim          = 2;
     65     dcb.XoffLim         = 4;
     66     dcb.XonChar         = 0x13;
     67     dcb.XoffChar        = 0x19;
     68     dcb.EvtChar         = 0;
     69     /* -------------------------------------------------------------------- */
     70     // set DCB
     71     if(!SetCommState(hComm,&dcb))
     72     {
     73         return false;
     74     }
     75     else
     76         return true;
     77 }
     78 //在用readfile和writefile读写串行口时,需要考虑超时问题, 读写串口的超时有两
     79 //种:间隔超时和总超时, 写操作只支持总超时,而读操作两种超时均支持, 如果所有
     80 //写超时参数均为0,那么就不使用写超时。
     81 bool setuptimeout(DWORD ReadInterval,DWORD ReadTotalMultiplier,DWORD ReadTotalconstant,DWORD WriteTotalMultiplier,DWORD WriteTotalconstant)               
     82 {
     83     COMMTIMEOUTS timeouts;
     84     timeouts.ReadIntervalTimeout=ReadInterval; //读间隔超时
     85     timeouts.ReadTotalTimeoutConstant=ReadTotalconstant; //读时间系数
     86     timeouts.ReadTotalTimeoutMultiplier=ReadTotalMultiplier; //读时间常量
     87     timeouts.WriteTotalTimeoutConstant=WriteTotalconstant; // 写时间系数
     88     timeouts.WriteTotalTimeoutMultiplier=WriteTotalMultiplier; //写时间常//量, 总超时的计算公式是:总超时=时间系数×要求读/写的字符数+时间常量
     89     if(!SetCommTimeouts(hComm, &timeouts))
     90     {
     91         return false;
     92     }
     93     else
     94         return true;
     95 }
     96 void ReceiveChar(){
     97     BOOL  bRead = TRUE;
     98     BOOL  bResult = TRUE;
     99     DWORD dwError = 0;
    100     DWORD BytesRead = 0;
    101     char RXBuff;
    102     while(true){
    103         bResult = ClearCommError(hComm, &dwError, &comstat);
    104         // 在使用ReadFile 函数进行读操作前,应先使用ClearCommError函数清除错误
    105         if(comstat.cbInQue==0)// COMSTAT结构返回串口状态信息
    106             //本文只用到了cbInQue成员变量,该成员变量的值代表输入缓冲区的字节数
    107             continue;
    108         if(bRead){
    109             bResult = ReadFile(hComm, // Handle to COMM port串口的句柄
    110                 &RXBuff,// RX Buffer Pointer// 读入的数据存储的地址,即读入的数据将存//储在以该指针的值为首地址的一片内存区
    111                 1,// Read one byte要读入的数据的字节数,
    112                 &BytesRead, // Stores number of bytes read, 指向一个DWORD//数值,该数值返回读操作实际读入的字节数
    113                 &m_ov);           // pointer to the m_ov structure// 重叠操作时,该参数指向一个OVERLAPPED结构,同步操作时,该参数为NULL
    114             printf("%c",RXBuff);
    115             if (!bResult){// 当ReadFile和WriteFile返回FALSE时,不一定就是操作失//败,线程应该调用GetLastError函数分析返回的结果
    116                 switch (dwError = GetLastError()){
    117                 case ERROR_IO_PENDING:
    118                         bRead = FALSE;
    119                         break;
    120                 default:break;
    121                 }
    122             }else{
    123                 bRead = TRUE;
    124             }
    125         }  // close if (bRead)
    126         if (!bRead){
    127             bRead = TRUE;
    128             bResult = GetOverlappedResult(hComm,    // Handle to COMM port
    129                 &m_ov,    // Overlapped structure
    130                 &BytesRead,        // Stores number of bytes read
    131                 TRUE);             // Wait flag
    132         }
    133     }
    134 }
    135 BOOL WriteChar(BYTE* m_szWriteBuffer,DWORD m_nToSend){
    136     BOOL bWrite = TRUE;
    137     BOOL bResult = TRUE;
    138     DWORD BytesSent = 0;
    139     HANDLE    m_hWriteEvent;
    140     ResetEvent(m_hWriteEvent);
    141     if (bWrite){
    142         m_ov.Offset = 0;
    143         m_ov.OffsetHigh = 0;
    144         // Clear buffer
    145         bResult = WriteFile(hComm,    // Handle to COMM Port, 串口的句柄
    146             m_szWriteBuffer,        // Pointer to message buffer in calling finction
    147                                     // 即以该指针的值为首地址的nNumberOfBytesToWrite
    148                                     // 个字节的数据将要写入串口的发送数据缓冲区
    149             m_nToSend,                // Length of message to send, 要写入的数据的字节数
    150             &BytesSent,                // Where to store the number of bytes sent
    151                                     // 指向指向一个DWORD数值,该数值返回实际写入的字节数
    152             &m_ov );                // Overlapped structure
    153                                     // 重叠操作时,该参数指向一个OVERLAPPED结构,
    154                                     // 同步操作时,该参数为NULL
    155         if (!bResult){                // 当ReadFile和WriteFile返回FALSE时,不一定就是操作失
    156             //败,线程应该调用GetLastError函数分析返回的结果
    157             DWORD dwError = GetLastError();
    158             switch (dwError){
    159             case ERROR_IO_PENDING: //GetLastError函数返回//ERROR_IO_PENDING。这说明重叠操作还未完成
    160                     // continue to GetOverlappedResults()
    161                     BytesSent = 0;
    162                     bWrite = FALSE;
    163                     break;
    164             default:break;
    165             }
    166         }
    167     } // end if(bWrite)
    168     if (!bWrite){
    169         bWrite = TRUE;
    170         bResult = GetOverlappedResult(hComm,    // Handle to COMM port
    171             &m_ov,        // Overlapped structure
    172             &BytesSent,        // Stores number of bytes sent
    173             TRUE);             // Wait flag
    174         
    175         // deal with the error code
    176         if (!bResult){
    177             printf("GetOverlappedResults() in WriteFile()");
    178         }
    179     } // end if (!bWrite)
    180     
    181     // Verify that the data size send equals what we tried to send
    182     if (BytesSent != m_nToSend){
    183         printf("WARNING: WriteFile() error.. Bytes Sent: %d; Message Length: %d
    ", BytesSent, strlen((char*)m_szWriteBuffer));
    184     }
    185     return true;
    186 }
    187 
    188 
    189 void   main(){
    190     if(openport("com4"))
    191         printf("open comport success
    ");
    192     if(setupdcb(115200))
    193         printf("setupDCB success
    ");
    194     if(setuptimeout(0,0,0,0,0)) //如果所有写超时参数均为0,那么就不使用写超时
    195         printf("setuptimeout success
    ");
    196     PurgeComm(hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT); // 在读写串口之前,还要用PurgeComm()函数清空缓冲区
    197     //PURGE_TXABORT      中断所有写操作并立即返回,即使写操作还没有完成。
    198     //PURGE_RXABORT      中断所有读操作并立即返回,即使读操作还没有完成。
    199     //PURGE_TXCLEAR      清除输出缓冲区
    200     //PURGE_RXCLEAR      清除输入缓冲区
    201     //WriteChar("please send data now",20);
    202     printf("received data:
    ");
    203     ReceiveChar( );
    204     system("pause");
    205 }
  • 相关阅读:
    shell中括号的特殊用法 linux if多条件判断
    uboot kernel 博客
    meson 中调用shell script
    200. 岛屿数量
    9. 回文数
    53. 最大子序和
    394. 字符串解码
    32. 最长有效括号
    leetcode排序的题 912. 排序数组 215. 数组中的第K个最大元素
    c++引用和运算符重载思考
  • 原文地址:https://www.cnblogs.com/zjutlitao/p/3709910.html
Copyright © 2020-2023  润新知