Click here to Skip to main content
15,888,264 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hey all,

After hours of browsing and reading, I still can't figure out why my code isn't working. I saw similar code snippets on different websites, but I can't seem to get it to work. The writing part is working, but the reading goes wrong. Every 'real character' is followed by three null terminators. Writing a string of 19 characters works and the FPGA I am using gives the correct data on the display. The FPGA should reverse the input and send this back to the serial port. In the Hyperterminal this is working without any problem.

Can someone maybe point me on my mistake and tell me what I am doing wrong?

Thanks in advance =)
C++
<code>
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include    <commdlg.h>
//#include	<windef.h>
#define    BUFFERLENGTH 19

void writeToSerial(char *line, HANDLE hSerial, DWORD dwBytesWritten);
void printBuffer(char * buffRead, DWORD dwBytesRead);

     
int main(){
    HANDLE hSerial;
    COMMTIMEOUTS timeouts;
    COMMCONFIG dcbSerialParams;
    char *line, *buffWrite, *buffRead;
    DWORD dwBytesWritten, dwBytesRead;
    /* Create a handle to the serial port */    
    hSerial = CreateFile("COM3",
                            GENERIC_READ | GENERIC_WRITE,
                            0,
                            NULL,
                            OPEN_EXISTING,
                            FILE_ATTRIBUTE_NORMAL,
                            NULL);
    /* Check if the handle is valid */                        
    if(hSerial == INVALID_HANDLE_VALUE){
       if(GetLastError() == ERROR_FILE_NOT_FOUND){
          printf("Serial port does not exist \n");
       }else{
          printf("Port occupied. Please close terminals!\n");
       }
    }else{
       printf("Handle created\n");    
       /* Check the state of the comm port */
       if(!GetCommState(hSerial, &dcbSerialParams.dcb)){
          printf("Error getting state \n");
       }else{
          printf("Port available\n"); 
          /* Configure the settings of the port */
          dcbSerialParams.dcb.DCBlength = sizeof(dcbSerialParams.dcb);
          /* Basic settings */    
          dcbSerialParams.dcb.BaudRate = CBR_57600;
          dcbSerialParams.dcb.ByteSize = 8;
          dcbSerialParams.dcb.StopBits = ONESTOPBIT;
          dcbSerialParams.dcb.Parity = NOPARITY;
          /* Misc settings */
          dcbSerialParams.dcb.fBinary = TRUE;
          dcbSerialParams.dcb.fDtrControl = DTR_CONTROL_DISABLE;
          dcbSerialParams.dcb.fRtsControl = RTS_CONTROL_DISABLE;
          dcbSerialParams.dcb.fOutxCtsFlow = FALSE;
          dcbSerialParams.dcb.fOutxDsrFlow = FALSE;
          dcbSerialParams.dcb.fDsrSensitivity= FALSE;
          dcbSerialParams.dcb.fAbortOnError = TRUE;
          /* Apply the settings */
          if(!SetCommState(hSerial, &dcbSerialParams.dcb)){
            printf("Error setting serial port state \n");
          }else{
            printf("Settings applied\n");  
            GetCommTimeouts(hSerial,&timeouts);
              //COMMTIMEOUTS timeouts = {0};
            timeouts.ReadIntervalTimeout = 50;
            timeouts.ReadTotalTimeoutConstant = 50;
            timeouts.ReadTotalTimeoutMultiplier = 10;
            timeouts.WriteTotalTimeoutConstant = 50;
            timeouts.WriteTotalTimeoutMultiplier= 10;
            
            if(!SetCommTimeouts(hSerial, &timeouts)){
                  printf("Error setting port state \n");
            }else{
                /* Ready for communication */
                line = "Something else\r";
                //****************Write Operation*********************//
                writeToSerial(line, hSerial, dwBytesWritten);
                //***************Read Operation******************//
                if(ReadFile(hSerial, buffRead, BUFFERLENGTH, &dwBytesRead, NULL)){
                   printBuffer(buffRead, dwBytesRead);                     
                }
             }          
          }
       }
    }
    CloseHandle(hSerial);
    system("PAUSE");
    return 0;

}
void printBuffer(char * buffRead, DWORD dwBytesRead){
     int j;
     for(j = 0; j < dwBytesRead; j++){
         if(buffRead[j] != '\0'){    
           printf("%d: %c\n", j, buffRead[j]);
         }
     }   
}

void writeToSerial(char *line, HANDLE hSerial, DWORD dwBytesWritten){
    WriteFile(hSerial, line, 19, &dwBytesWritten,NULL);
    if(dwBytesWritten){
       printf("Writing success, you wrote '%s'\n", line);
    }else{
       printf("Writing went wrong =[\n");      
    }
}
Posted

Looks to me that the FPGA might not return your characters fast enough and you are running on the read timeout of 50ms. You might want to try two things:

- reflect the characters by a loop-plug on your serial line

if that works fine

- extend the ReadIntervalTimeout and ReadTotalTimeoutConstant values for testing to 1000ms and see if that is the problem.

Just on the side, at two places I saw that you still have the constant value of 19 in your code. Needs to be replaced by strlen() respectively the buffer size.

Good luck!
 
Share this answer
 
Comments
jitsejan 13-Apr-12 5:36am    
Thanks for your reply. I am not sure what you mean by the loop-plug on the serial line? I am using a USB cable which functions as a serial cable, so I can't measure the pins.
nv3 13-Apr-12 5:43am    
With a loop-plug I mean piece of hardware that connects the transmit with the receive line and, if used, and handshake modem signals of the line, so that every character you send is immediately reflected back to your receive line.
jitsejan 13-Apr-12 6:29am    
Okay. That is not going to work then unfortunately.
There must be a compiler warning for the ReadFile line because buffRead is nowhere initialized:
C++
char *line, *buffWrite, *buffRead;
...
if(ReadFile(hSerial, buffRead, BUFFERLENGTH, &dwBytesRead, NULL)){

This can produce unpredictable results.
 
Share this answer
 
Comments
jitsejan 13-Apr-12 5:34am    
Thanks for your reply. I allocate the memory now beforehand.
<pre lang="c++">
char line[BUFFERLENGTH];
char buffWrite[BUFFERLENGTH];
char buffRead[BUFFERLENGTH+1];
</pre>
but this doesn't change the behaviour. The problem is that I only allocate BUFFERLENGTH+1 for the output of the serial, and since the output contains the '\0\0\0' after each character, the input of length 19 doesn't fit in the buffer of length 19+1. I thought it would require (BUFFERLENGTH*4)-4 characters, but this is too big. I want to correct the null characters afterwards like the following code, by cleaning the 'dirty buffer' into a new string by neglecting the '\0', but also that seems not to be working.

<pre lang="c++">
if(ReadFile(hSerial, buffRead, 4*(BUFFERLENGTH-1), &dwBytesRead, NULL)){
printBuffer(buffRead, dwBytesRead);
}

void printBuffer(char * buffRead, DWORD dwBytesRead){
int j, k = 0;
char outputLine[BUFFERLENGTH];
for(j = 0; j < 4*(BUFFERLENGTH-1); j++){
if(buffRead[j] != '\0' && buffRead[j] != 13){
outputLine[k] = buffRead[j];
k++;
}
}
printf("Output: '%s'\n", outputLine);
}
</pre>
Jochen Arndt 13-Apr-12 6:32am    
I suggest to find out where the problem is rather than trying to read in the wrong data. You can read the data byte by byte:

unsigned char c;
while (ReadFile(hSerial, &c, sizeof(unsigned char), &dwBytesRead, NULL) &&
dwBytesRead == sizeof(unsigned char))
{
printf("%02X ", (unsigned)c);
dwBytesRead = 0;
}
printf("\nReading terminated. Last error %d\n", GetLastError());
jitsejan 13-Apr-12 8:30am    
Thank you. That already helps me a bit further. I am not there yet, but at least I have some progress =)

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS


CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900