CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 7 of 7
  1. #1
    Join Date
    Feb 2006
    Posts
    153

    Serial Communication (WriteFile)

    Hi all,

    I require some guidance on Serial communication.

    Currently, I have an array of data to send which are stored as

    unsigned short int sendData[10];

    so when I call writeFile, i pass the pointer to the start of sendData
    WriteFile(hComm, sendData, dwToWrite, &dwWritten, &osWrite)

    My question is What should I specify for the bytes to write field (dwToWrite)?

    - Should I specify 20 OR
    - Should I specify 2 and then keep incrementing the pointer to the next 2 bytes b4 i call WriteFile,

    eg. WriteFile(hComm, sendData[1], 2, &dwWritten, &osWrite)

    The reason why I am asking this question is I have another application file to READ in the data sent out (by the above codes), I cant seem to read in >1 byte of data... it only fills my receiver buffer with the 1st byte of data.

    Thank you
    FT
    Last edited by fulltime; October 10th, 2007 at 10:30 AM.

  2. #2
    Join Date
    Jul 2003
    Posts
    147

    Thumbs up Re: Serial Communication (WriteFile)

    I attached a couple of files I have used in the past for serial comms. They are pretty basic, but work.
    Attached Files Attached Files
    "Live only for tomorrow, and you will have a lot of empty yesterdays today."

  3. #3
    Join Date
    Jun 2002
    Location
    Cambridge, UK
    Posts
    28

    Re: Serial Communication (WriteFile)

    Some things to remember when writting or reading some data in this way.
    1. Timeouts will be much longer than you intended. Check the parameters and the SetCommTimeouts() timeout structure.
    2. You un-neccesarily make lots of calls down through the kernel, so you are wasting context-switches. Only a problem though if you want to write data continuously though; the scarry problem here is that because of UART buffering, your code may behave differently on machines with differing UART architectures because of the way the drivers handle them. Leads to bugs reported by users. (Asside, if you happen to be sending over anything other than RS232 and use a media-converter or anything in between, this approach can be fraught with problems too.)
    3. Writting data in nibbles is good, especially if you use a state-machine, because it could leave your application free to process user input. Weigh this against either doing overlapped I/O or using a thread.

    - the code in 'tmecham's post is a pretty good place to start learning. Good luck!

  4. #4
    Join Date
    Feb 2006
    Posts
    153

    Re: Serial Communication (WriteFile)

    Thank you to the both of your for the reply. I was looking at the codes for readFile as shown below and I got this question

    int CSerial::ReadData( void *buffer, int limit )
    {

    if( !m_bOpened || m_hIDComDev == NULL ) return( 0 );

    BOOL bReadStatus;
    DWORD dwBytesRead, dwErrorFlags;
    COMSTAT ComStat;

    ClearCommError( m_hIDComDev, &dwErrorFlags, &ComStat );
    if( !ComStat.cbInQue ) return( 0 );

    dwBytesRead = (DWORD) ComStat.cbInQue;
    if( limit < (int) dwBytesRead ) dwBytesRead = (DWORD) limit;

    bReadStatus = ReadFile( m_hIDComDev, buffer, dwBytesRead, &dwBytesRead, &m_OverlappedRead );
    if( !bReadStatus ){
    if( GetLastError() == ERROR_IO_PENDING ){
    WaitForSingleObject( m_OverlappedRead.hEvent, 2000 );
    return( (int) dwBytesRead );
    }
    return( 0 );
    }

    return( (int) dwBytesRead );

    }

    The 2nd parameter of the readFile function takes in a pointer to the buffer that receives data from a file. Is the data type of this buffer crucial? Eg. can i specify unsigned short int for the buffer type yet my limit is specified as anything except for 2 bytes?

  5. #5
    Join Date
    Jun 2002
    Location
    Cambridge, UK
    Posts
    28

    Re: Serial Communication (WriteFile)

    I would not use anything other than a buffer-pointer to something 8-bit to recieve the eventual data: By specifying a 16-bit type, you are assuming that the data will have the intended endian-ness and also that it will be in sync/frame correctly. If not your application is just dealing with garbage. If the entire serial transfer is using short int only, and you have another way of getting back into sync, you are welcome to pass a buffer of short-int and it will work fine. But if the UART drops a single character, and both ends do not use a pause of at least 1 second when errors occur, they may never be able to get back into sync.

    However! Here is a handy trick (code written on-the-fly)
    Code:
    #pragma pack(1)
    typedef struct _telegram
    {
    unsigned char startB;
    short value1;
    short value2;
    unsigned char crc;
    } telegram;
    #pragma pop
    
    ...
    int ret = ReadFile(hFile, &telegram, sizeof(telegram), &dwBytesRead, 0);
    ...
    if ((sizeof(telegram) == dwBytesRead) && CheckCRC(telegram))
    {
    mouseX = telegram.value1;
    mouseY = telegram.value2;
    }
    I have used the pragma directive to byte-align structure members(remember to turn it off afterwards), and make packing/unpacking the data easier. Note that packed struct types like this can be re-used anywhere else in code elsewhere which does not need to know about the packing used (the compiller remembers it all for you).

    Remember that when transfering data over any medium that does not do integrity-checks, for your, you want a CRC test or something right up-front before you try to access the data in any way.
    Looking at your first post, you have 10 values, pack them into a struct, put a known-value in front of them like 0x5A5A, and then a known end-CRC made from the sum of all the preceding members of the struct...
    Code:
    typedef struct _telegram {
    short int head;
    short int data[10];
    short int crc;
    }
    sum=telegram.head = 0x5A5A;
    for (int i=0;i<10 ++i) sum+= telegram.data[i];
    telegram.crc = sum;
    ...use the reverse of above to test the crc.
    I assume you either use an acknowledging message to prompt the remote end, or have sizeable delays between data exchanges. You need to have one or the other, and you should be home free. Especially if you code the struct packing into a shared headder file, or document it like protocols do.
    Last edited by Conrad Braam; October 11th, 2007 at 03:20 AM.

  6. #6
    Join Date
    Feb 2006
    Posts
    153

    Re: Serial Communication (WriteFile)

    Thank you. Your explanation is very clear. Yes, I specified a 16bit type as its agreed btwn the sender and receiver that the data sent is word (16bits)aligned..


    Thank you so much...
    FT

  7. #7
    Join Date
    Jun 2002
    Location
    Cambridge, UK
    Posts
    28

    Re: Serial Communication (WriteFile)

    Good stuff, glad we could help.
    Just to clarify for anyone else reading this sample, the data should be typed
    unsigned short, to make it portable unless we ensure the correct compiler options.
    try using the typedef to make future changes/platforms easier.
    Code:
    typedef WORD unsigned short;

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured