I have an Atmel mirocontroller sending data which I want to receive on my PC over COM1.
When I attach a terminal program, the data is received correctly (it is all ascii, all printable except for \n).
However, my code appears to be receiving junk (non-ascii chars). Can anyone see what I am doing wrong? Thanks
Sending code, just for info
// USART options.
static const usart_options_t USART_CONSOLE_OPTIONS =
{
.baudrate = 115200,
.charlength = 8,
.paritytype = USART_NO_PARITY,
.stopbits = USART_1_STOPBIT,
.channelmode = USART_NORMAL_CHMODE
};
Receiving code
E_boolean OpenCom1(void)
{
COMMTIMEOUTS timeouts;
comPortHandle = CreateFile("COM1", // Specify port device: default "COM1"
GENERIC_READ | GENERIC_WRITE, // Specify mode that open device.
0, // the device isn't shared.
NULL, // the object gets a default security.
OPEN_EXISTING, // Specify which action to take on file.
0, // default (not overlapped i/o).
NULL); // default (hTemplate must be NULL for COM devices).
if (comPortHandle == INVALID_HANDLE_VALUE)
return False;
deviceControlBlock.DCBlength = sizeof(deviceControlBlock);
if((GetCommState(comPortHandle, &deviceControlBlock) == 0))
{
// CodeMe: do what?
return False;
}
deviceControlBlock.BaudRate = CBR_115200;
deviceControlBlock.StopBits = ONESTOPBIT;
deviceControlBlock.Parity = NOPARITY;
deviceControlBlock.ByteSize = DATABITS_8;
deviceControlBlock.fRtsControl = 0;
if (!SetCommState(comPortHandle, &deviceControlBlock))
{
// CodeMe: do what?
return False;
}
// set short timeouts on the comm port.
timeouts.ReadIntervalTimeout = MAXDWORD;
timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
timeouts.ReadTotalTimeoutConstant = 1000; // oen second
timeouts.WriteTotalTimeoutMultiplier = 1;
timeouts.WriteTotalTimeoutConstant = 1;
if (!SetCommTimeouts(comPortHandle, &timeouts))
{
// CodeMe: do what?
return False;
}
FlushFileBuffers(comPortHandle);
PurgeComm (comPortHandle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
return True;
}//OpenCom1()
// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
void ReadCharacterFromCom1(INPUT char *theCharacter)
{
DWORD numBytesRead;
numBytesRead = 0;
while (numBytesRead == 0)
{
ReadFile(comPortHandle, // handle of file to read
theCharacter, // store read data here
sizeof(char), // number of bytes to read
&numBytesRead, // pointer to number of bytes actually read
NULL);
}
return;
}//ReadCharacterFromCom1()
The function "ReadFile" is called with a "sizeof(char)" for number of bytes to read. This will alway be evaluated to be 1, probably not the value that you intended. The result is every call to the ReadCharacterFromCom1 will only read 1 valid character from the port and return, the rest that you saw are the junks left in the buffer because the buffer is not (manually) terminated with a null.
Suggest that you change it to:
/* ============================================================ */
DWORD ReadCharacterFromCom1(char *pszBuffer, int nMaxCharToRead)
{
DWORD dwBytesRead = 0;
while (dwBytesRead == 0)
{ ReadFile(comPortHandle, // handle of file to read
pszBuffer, // store read data here
nMaxCharToRead, // number of bytes to read
&dwBytesRead, // pointer to number of bytes actually read
NULL);
}
// terminate string with null
pszBuffer[dwBytesRead] = 0;
return dwBytesRead;
}
// test code ------------------------
char szBuffer[512];
DWORD dwCount = ReadCharacterFromCom1(szBuffer, sizeof(szBuffer)-1);
printf(_T("Receive %d chars: <%s>"), nCount, szBuffer);
Assuming baud rate, number of data bits, parity and the number of stop bits are set up correctly you most likley are missing to set up any kind of flow control. You do not show us (fully) how you initialise the DCB.
Flow control inhibits buffer overflows in the sender/receiver.
Depending on what kind of serial cabeling you use and what kind of data shall be transferred soft- or hardware flow control can be used.
Hardware flow control is the preferred kind of flow control as it works for plain ASCII and binary data to be transferred. Its requiers a fully wired serial connection. It is also referred to as RTS and/or DTR flow control.
If you only have the mininal three-wire RS232/V.24 cabeling you might like to use software flow control (also referrred to as Xon/Xoff handshake). Xon/Xoff-handshake flow control works for ASCII data to be transfered only. To send binary data via such a connection it needs to be encode to pure ASCII. Use base64 encoding for example to do so.
How to set up flow control under windows you might like to read here: http://www.cplusplus.com/forum/windows/89698/
This http://msdn.microsoft.com/en-us/library/ff802693.aspx might serve as a reference.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With