How should I send 9 binary into serial port?
Is there anything wrong with this? I get no reaction from the serial port. What should I do for the write file?
#include <iostream>
#include <windows.h>
using namespace std;
int main(){
unsigned char data[9];
data[0] = { 0x00 };
data[1] = { 0x5A };
data[2] = { 0x56 };
data[3] = { 0xFF };
data[4] = { 0x04 };
data[5] = { 0x00 };
data[6] = { 0x00 };
data[7] = { 0x00 };
data[8] = { 0xB3 };
DWORD buffer = 0;
HANDLE port;
DCB dcb = { 0 };
port = CreateFile("COM1",
GENERIC_READ | GENERIC_WRITE,0,0,OPEN_EXISTING,0,0);
//DCB dcb;
DWORD m_baudrate = 9600, m_bytesize = 8, m_parity = 0, m_stopbit = 1, ok, m_useRtsCts = 0;
dcb.DCBlength = sizeof(dcb);
GetCommState(port, &dcb);
dcb.BaudRate = m_baudrate;
dcb.ByteSize = (BYTE)m_bytesize;
dcb.Parity = m_parity;
dcb.StopBits = m_stopbit;
if (m_useRtsCts)
dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcb.fNull = FALSE;
dcb.fAbortOnError = FALSE;
ok = SetCommState(port, &dcb);
if (port){
BuildCommDCB("COM1:9600,n,8,1", &dcb);
cout << "Hello" << endl;
PurgeComm(port, PURGE_RXCLEAR | PURGE_TXCLEAR);
WriteFile(port, data, sizeof(data), &buffer, 0);
}
else{
cout << "World" << endl;
}
CloseHandle(port);
system("Pause");
return 0;
}
I can send the data but the binary cannot turn on the light. the hexadecimal code to turn everything on is
00 5A 56 FF 03 00 00 00 B2
how ever after i use CommUart asistant to open to port once then the things can function. Could anyone tell me what is the problem at the Open port there? Thank You!
can anyone tell me what is wrong?
However with this set of code i can run it normally? May i know where of my setting was wrong above there.
#include <iostream>
#include <corewindow.h>
using namespace std;
int main(){
//unsigned char data[9] = {0,90,86,255,3,0,0,0,178};
unsigned char data[9];
data[0] = { 0x00 };
data[1] = { 0x5A };
data[2] = { 0x56 };
data[3] = { 0xFF };
data[4] = { 0x03 };
data[5] = { 0x00 };
data[6] = { 0x00 };
data[7] = { 0x00 };
data[8] = { 0xB2 };
DWORD buffer = 0;
HANDLE port;
DCB dcb = { 0 };
port = CreateFile("COM1",
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
0,
0);
if (port == (HANDLE)-1)
{
return 0;
}
SetupComm(port, 1024, 1024);
FillMemory(&dcb, sizeof(dcb), 0);
dcb.DCBlength = sizeof(dcb);
BuildCommDCB("9600,n,8,1", &dcb);
if (!SetCommState(port, &dcb))
{
return 0;
}
COMMTIMEOUTS to;
memset(&to, 0, sizeof(to));
to.ReadIntervalTimeout = 100;
to.ReadTotalTimeoutMultiplier = 10;
to.ReadTotalTimeoutConstant = 10;
SetCommTimeouts(port, &to);
PurgeComm(port, PURGE_TXCLEAR | PURGE_RXCLEAR);
if (port){
cout << "Hello" << endl;
WriteFile(port, data, sizeof(data), &buffer, 0);
system("pause");
data[0] = { 0x00 };
data[1] = { 0x5A };
data[2] = { 0x56 };
data[3] = { 0xFF };
data[4] = { 0x04 };
data[5] = { 0x00 };
data[6] = { 0x00 };
data[7] = { 0x00 };
data[8] = { 0xB3 };
WriteFile(port, data, sizeof(data), &buffer, 0);
}
else{
cout << "World" << endl;
}
CloseHandle(port);
system("pause");
return 0;
}
There is no way that code could work. It should not have compiled.
At a minimum, the first parameter to Writefile is the file handle, and the third parameter is the number of bytes to write.
WriteFile(
hcomm,
"the string",
strlen ("the string"),
Also, you probably need to set the serial port's characteristics. That can be done using the command line or control panel, but it is often useful for the program to handle the details itself, after opening the file:
DCB dcb;
dcb.DCBlength = sizeof(dcb);
GetCommState(m_hCom, &dcb); /* retrieve current settings */
dcb.BaudRate = m_baudrate; /* alter bits per second */
dcb.ByteSize = (BYTE)m_bytesize; /* bits per character */
dcb.Parity = m_parity;
dcb.StopBits = m_stopbit;
if (m_useRtsCts)
dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
dcb.fDtrControl = DTR_CONTROL_DISABLE; // no handshake
dcb.fNull = FALSE; /* don't strip NULs */
dcb.fAbortOnError = FALSE; /* keep going after errors */
ok=SetCommState(hcomm, &dcb);
Addendum
To write the nine binary values as character values, any of these techniques would work. All rely on expressing the binary numbers as bytes:
char data[] = "\000\132\124\000\003\000\000\000\261";
WriteFile(hcomm, data, sizeof data, NULL, NULL);
or
char data[] = {0, 0132, 0124, 0, 3, 0, 0, 0, 0261};
WriteFile(hcomm, data, sizeof data, NULL, NULL);
or
char data[] = {0, 0x5a, 0x54, 0, 3, 0, 0, 0, 0xb1};
WriteFile(hcomm, data, sizeof data, NULL, NULL);
Setting telepathy mode on, I'd assume that TS wants to send 9-bit data. A typical way to achieve it is to use parity as a 9th data bit. The main idea is to cause a parity error to signify the 9th bit set. The details depend on the available hardware ad drivers.
If uart supports MARK/SPACE parities, something like this would work:
send_9_bits(unsigned char data, bool ninth_bit) {
if(ninth_bit) set_parity_mark();
else set_parity_space();
uart_write(data);
}
with the receiving end to analyze parity error status:
unsigned short receive_9_bits() {
unsigned short data = uart_read();
bool ninth_bit;
if (even_parity(data & 0x00ff) {
ninth_bit = PARERR(data >> 8)? 1: 0;
} else {
ninth_bit = PARERR(data >> 8)? 0: 1;
}
return (data & 0x0ff) | (ninth_bit << 8);
}
The serial port cannot work with a baud rate of 0. The baud rate, byte size, parity and stop bits must all be set to match the settings used by the device you are communicating with. And only certain standard values are supported by the serial hardware.
Related
I'm making frames with the bytes that I read from a controller.
The first 100-200 frames are good, but after that I start to get bad frames. I checked 10000 times that my class' parsing of frames is good. That's why I'm asking if there is maybe a problem with reading from the device.
This is my code:
int ConnectDevice::getBytes() {
DCB dcb;
BYTE Byte;
DWORD dwBytesTransferred;
DWORD dwCommModemStatus;
HANDLE hPort = CreateFile(
chosePort().c_str(),
GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
0,
NULL);
if (!GetCommState(hPort, &dcb)) {
std::cout.flush();
system("cls");
getBytes();
}
dcb.BaudRate = 115200;
dcb.ByteSize = 8;
dcb.StopBits = ONESTOPBIT;
dcb.Parity = NOPARITY;
dcb.fDtrControl = DTR_CONTROL_DISABLE;
COMMTIMEOUTS timeout;
timeout.ReadIntervalTimeout = 50;
timeout.ReadTotalTimeoutConstant = 50;
timeout.ReadTotalTimeoutMultiplier = 50;
timeout.WriteTotalTimeoutConstant = 50;
timeout.WriteTotalTimeoutMultiplier = 10;
SetCommTimeouts(&Byte, &timeout);
if (!SetCommState(hPort, &dcb))
return false;
while (1) {
SetCommMask(hPort, EV_RXCHAR | EV_ERR);
if (_deviceProtocol->IsFrameReady != 1) {
WaitCommEvent(hPort, &dwCommModemStatus, 0);
if (dwCommModemStatus & EV_RXCHAR)
ReadFile(hPort, &Byte, 1, &dwBytesTransferred, NULL);
else if (dwCommModemStatus & EV_ERR)
return 0x101;
_parseFrame->ParseGCSFrame(Byte);
} else if (_deviceProtocol->IsFrameReady == 1) {
_deviceProtocol->IsFrameReady = 0;
_kalmanFilter->displayKalman();
}
}
return 0;
}
I am trying to get my software to read and write writing a CAT25512 EEPROM from a Raspberry Pi 3 with Raspbian (Debian) Linux. Before writing to the memory a Write Enable Latch (WEL) has to be set with command 0x06. This write is successful. It is then checked with the read status register command 0x05, which also succeeds. Then the write, read, and successive status read commands get no response and/or fail.
I have tried adding some delays to wait for the HW. I have also restructured the code many times.
I apologize in advance for the complete file, but I'm not sure where the problem lies.
#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>
#include <string>
#include <cstring>
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
#define WAIT_FOR_EEPROM(a) do { for (int z=0; z<0x3FFF; z++); } while (eepromBusy((a) != 0x02));
const char *device = "/dev/spidev0.0";
uint8_t mode=SPI_MODE_0;
uint8_t bits=8;
uint32_t baud=500000;
uint8_t buffer[4] = {0};
int transfer(int spi_file, uint8_t* buffer, int length); // Prototype
int eepromBusy(int spi_file) {
buffer[0] = 0x05;
buffer[1] = 0x00;
transfer(spi_file, buffer, 2);
return (buffer[1]);
}
int main() {
int fd = open(device,O_RDWR);
if (fd < 0) printf("can't open device");
int ret;
ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
if (ret == -1) printf("can't set spi mode");
ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
if (ret == -1) printf("can't set bits!");
ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &baud);
if (ret == -1) printf("can't set speed!");
ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
if (ret == -1) printf("can't set spi mode");
ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
if (ret == -1) printf("can't set bits!");
ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &baud);
if (ret == -1) printf("can't set speed!");
printf("spi mode set as %u\n", mode);
printf("bits per byte set as %u\n", bits);
printf("max speed set at %u\n", baud);
do {
// Write Enable
buffer[0] = 0x06;
transfer(fd, buffer, 1);
// Read Status
buffer[0] = 0x05;
buffer[1] = 0x00;
transfer(fd, buffer, 2);
} while (!(buffer[1] & 0x02));
printf("Status Reg: %x\n", buffer[1]);
WAIT_FOR_EEPROM(fd)
// usleep(100);
// Write Byte
buffer[0] = 0x02;
buffer[1] = 0x00;
buffer[2] = 0x10;
buffer[3] = 0xAA;
transfer(fd, buffer, 4);
/* uint8_t busy = -1;
do {
usleep(50);
buffer[0] = 0x05;
buffer[1] = 0x00;
transfer(fd, buffer, 2);
busy = buffer[1] & 0x01;
} while (busy);
*/
WAIT_FOR_EEPROM(fd)
// Read Byte
buffer[0] = 0x03;
buffer[1] = 0x00;
buffer[2] = 0x10;
buffer[3] = 0x00;
transfer(fd, buffer, 4);
printf("Received byte: %i\n", buffer[3]);
if (close(fd) > 0) printf("can't close device");
return 0;
}
int transfer(int spi_file, uint8_t *buffer, int length) {
//struct spi_ioc_transfer spi[length] = {0};
int ret = -1;
struct spi_ioc_transfer tr[length] = {0};
for (int x=0; x<length; ++x) {
tr[x].tx_buf = (unsigned long)(buffer+x);
tr[x].rx_buf = (unsigned long)(buffer+x);
tr[x].len = sizeof(*(buffer+x));
tr[x].delay_usecs = 0;
tr[x].speed_hz = baud;
tr[x].bits_per_word = bits;
tr[x].cs_change = 0;
};
ret = ioctl(spi_file, SPI_IOC_MESSAGE(length), &tr);
if (ret < 1) printf("Transfer Error!!! First Byte Was: 0x%x\n", buffer[0]);
return ret;
}
I am currently getting the Transfer Error!!! First Byte Was: 0x5 error twice, indicating that the WAIT_FOR_EEPROM(fd) commands are not properly being executed.
In the beginning, the WEL bit is set with command 0x06 and the status is correctly reported as 2. The data read from EEPROM has read out as 0 or 211 depending on how I've tweaked the code. It should be 0xAA (170).
I would appreciate any suggestions.
I guess the transfer() function is responsible to setup and execute one SPI command per call.
Why you are using an array of 'struct spi_ioc_transfer' ?
Why are you loop over the number of bytes in buffer and setup a 'spi_ioc_transfer' structure for each ?
Take a look at https://raw.githubusercontent.com/raspberrypi/linux/rpi-3.10.y/Documentation/spi/spidev_test.c
Below is my code. I want to send hex values and get the output as hex in the hyper terminal. I am not sure how to send it.
I am getting some garbage values in the hyperterminal output. It is reading but not sending the hex output.
#include "stdafx.h"
#include <Windows.h>
#include <stdio.h>
#include <string.h>
#include <conio.h>
#include <stdint.h>
#define BUFFERLENGTH 256
int main(void)
{
HANDLE hComm; // Handle to the Serial port
char ComPortName[] = "\\\\.\\COM6"; // Name of the Serial port(May Change) to be opened,
BOOL Status;
DWORD dwEventMask; // Event mask to trigger
unsigned char TempChar; // Temperory Character
char SerialBuffer[256]; // Buffer Containing Rxed Data
DWORD NoBytesRead; // Bytes read by ReadFile()
int i = 0;
printf("\n\n +==========================================+");
printf("\n | Serial Communication (Win32 API) |");
printf("\n +==========================================+\n");
/*----------------------------------- Opening the Serial Port --------------------------------------------*/
hComm = CreateFile(ComPortName, // Name of the Port to be Opened
GENERIC_READ | GENERIC_WRITE, // Read/Write Access
0, // No Sharing, ports cant be shared
NULL, // No Security
OPEN_EXISTING, // Open existing port only
0, // Non Overlapped I/O
NULL); // Null for Comm Devices
if (hComm == INVALID_HANDLE_VALUE)
printf("\n Error! - Port %s can't be opened", ComPortName);
else
printf("\n Port %s Opened\n ", ComPortName);
/*------------------------------- Setting the Parameters for the SerialPort ------------------------------*/
DCB dcbSerialParams = { 0 }; // Initializing DCB structure
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
Status = GetCommState(hComm, &dcbSerialParams); //retreives the current settings
if (Status == FALSE)
printf("\n Error! in GetCommState()");
dcbSerialParams.BaudRate = CBR_9600; // Setting BaudRate = 9600
dcbSerialParams.ByteSize = 8; // Setting ByteSize = 8
dcbSerialParams.StopBits = ONESTOPBIT; // Setting StopBits = 1
dcbSerialParams.Parity = EVENPARITY; // Setting Parity = None
Status = SetCommState(hComm, &dcbSerialParams); //Configuring the port according to settings in DCB
if (Status == FALSE)
{
printf("\n Error! in Setting DCB Structure");
}
else
{
printf("\n Setting DCB Structure Successfull\n");
printf("\n Baudrate = %d", dcbSerialParams.BaudRate);
printf("\n ByteSize = %d", dcbSerialParams.ByteSize);
printf("\n StopBits = %d", dcbSerialParams.StopBits);
printf("\n Parity = %d", dcbSerialParams.Parity);
}
/*------------------------------------ Setting Timeouts --------------------------------------------------*/
while (1)
{
COMMTIMEOUTS timeouts = { 0 };
timeouts.ReadIntervalTimeout = 5000;
timeouts.ReadTotalTimeoutConstant = 5000;
timeouts.ReadTotalTimeoutMultiplier = 1000;
timeouts.WriteTotalTimeoutConstant = 5000;
timeouts.WriteTotalTimeoutMultiplier = 1000;
if (SetCommTimeouts(hComm, &timeouts) == FALSE)
printf("\n Error! in Setting Time Outs");
else
printf("\n\n Setting Serial Port Timeouts Successfull");
printf("\n |--------- Serial Communication (Win32 API) --------|");
printf("Starting to write......");
//char lpBuffer[] = "ABC"; // lpBuffer should be char or byte array, otherwise write wil fail
uint8_t message[15];
message[0] = 0x16;
message[1] = 0x16;
message[2] = 0x02;
message[3] = 0x01;
message[4] = 0x07;
message[5] = 0x08;
message[6] = 0x00;
message[7] = 0xFF;
message[8] = 0xFF;
message[9] = 0x01;
message[10] = 0x00;
message[11] = 0x01;
message[12] = 0x00;
message[13] = 0xFF;
message[14] = 0xFF;
//byte(bytestosend)[15] = { message[0], message[1], message[2], message[3], message[4], message[5], message[6], message[7], message[8], message[9],message[10], message[11],message[12], message[13], message[14] };
DWORD dNoOFBytestoWrite; // No of bytes to write into the port
DWORD dNoOfBytesWritten = 0; // No of bytes written to the port
dNoOFBytestoWrite = sizeof(message); // Calculating the no of bytes to write into the port
Status = WriteFile(hComm, // Handle to the Serialport
message, // Data to be written to the port
dNoOFBytestoWrite, // No of bytes to write into the port
&dNoOfBytesWritten, // No of bytes written to the port
NULL);
if (Status == TRUE)
printf("\n\n %X %X %X %X %X %X %X %X %X %X %X %X %X %X %X- Written to %s", message[0], int(message[1]), int(message[2]), int(message[3]), int(message[4]), int(message[5]), int(message[6]), int(message[7]), int(message[8]), int(message[9]), int(message[10]), int(message[11]), int(message[12]), int(message[13]), int(message[14]), ComPortName);
else
printf("\n\n Error %d in Writing to Serial Port", GetLastError());
int k;
for (k = 0; k < 50; k++)
{
printf("");
}
/*-----------------------------------Read --------------------------------------------*/
int l;
for (l = 0; l < 50; l++)
{
printf("");
}
printf("\n\n Waiting for Data Reception");
dwEventMask = 1;
//Status = WaitCommEvent(hComm, &dwEventMask, NULL); //Wait for the character to be received
/*-------------------------- Program will Wait here till a Character is received ------------------------*/
if (Status == FALSE)
{
printf("\n Error! in Setting WaitCommEvent()");
}
else //If WaitCommEvent()==True Read the RXed data using ReadFile();
{
printf("\n\n Characters Received");
do
{
//byte(TempChar)[15] = { message[0], message[1], message[2], message[3], message[4], message[5], message[6], message[7], message[8], message[9],message[10], message[11],message[12], message[13], message[14] };
//if(! ReadFile(hComm, &TempChar, sizeof(TempChar), &NoBytesRead, NULL))
if (!ReadFile(hComm, &TempChar, sizeof(TempChar), &NoBytesRead, NULL))
///* ReadFile(
// _In_ HANDLE hFile,
// _Out_writes_bytes_to_opt_(nNumberOfBytesToRead, *lpNumberOfBytesRead) __out_data_source(FILE) LPVOID lpBuffer,
// _In_ DWORD nNumberOfBytesToRead,
// _Out_opt_ LPDWORD lpNumberOfBytesRead,
// _Inout_opt_ LPOVERLAPPED lpOverlapped
// );*/
//if (!ReadFile(hComm, SerialBuffer, BUFFERLENGTH, &NoBytesRead, NULL))
{
printf("wrong character" );
}
//printf("/n /n %X %X %X %X %X %X %X %X %X %X %X %X %X %X %X", int(TempChar[0]), int(TempChar[1]), int(TempChar[2]), int(TempChar[3]), int(TempChar[4]), int(TempChar[5]), int(TempChar[6]), int(TempChar[7]), int(TempChar[8]), int(TempChar[9]), int(TempChar[10]), int(TempChar[11]), int(TempChar[12]), int(TempChar[13]), int(TempChar[14]));
SerialBuffer[i] = TempChar;
//printf("%X is the read", SerialBuffer[i]);
i++;
} while (NoBytesRead > 0);
/*------------Printing the RXed String to Console----------------------*/
printf("\n\n ");
int j = 0;
for (j = 0; j < i - 1; j++) // j < i-1 to remove the dupliated last character
printf("%X are the values read", SerialBuffer[j]);
}
}
CloseHandle(hComm);//Closing the Serial Port
printf("\n ==========================================\n");
_getch();
}
I am giving this as input 16 16 02 01 07 08 FF FF 01 00 01 00 FF FF values, and I want the same to be read in hyperterminal. But I am getting some garbage values. I want the same hex values to be in the hyperterminal.
At very first: What you send is just data. There is no such thing as decimal or hexadecimal data, all that you have is binary data, i. e. the bits stored in groups of (typically) 8 for your bytes. Decimal or hexadecimal literals are just different representations for one and the same (binary) values:
char a[] = { 0x61, 0x62, 0x63, 0 };
char b[] = { 97, 98, 99, 0 };
a and b will now contain exactly the same values, which happen, if interpreted as ASCII characters, to represent the string "abc"...
If, however, your intention is to represent arbitrary binary data in a human readable format (as Intel HEX files do), then you would need to represent each data byte by two chars, e. g. convert the data byte containing 'N', having ASCII value of 78, into a byte sequence of '4', 'e' or alternatively '4', 'E'.
However, this will double your communication overhead, so I'd do the conversion only after receiving the data:
std::vector<char> received = readFromSerial();
// assuming arbitrary data..
for(auto c : received)
std::cout << std::setfill('0') << std::hex << std::setw(2)
<< static_cast<unsigned int>(static_cast<unsigned char>(c)) << std::endl;
Side note: you need the double cast to prevent sign extension for negative characters (at least if char is signed).
If you should prefer signed or unsigned char depends on if you want to represent data in the range of [-128;127] or of [0;255] respectively...
I'm trying to read/write from a com port.
When I open the Com Port I make it Non overlapped.
Everything works fine, but when I read a 0xFF byte it sees it like an EOF and finishes the read.
Can I make a Non overlapped read 0xFF?
Here is my code:
//Opening the com port:
hComm = CreateFile( s.c_str(), // COM PORT
GENERIC_READ | GENERIC_WRITE, //
0, // exclusive access
NULL, // no security
OPEN_EXISTING, // must be a port
0 , // async i/o
NULL); //
//Port init:
void initPort(int baud)
{
uart_baud = baud;
DCB dcb;
dcb.DCBlength = sizeof(DCB);
GetCommState(hComm, &dcb); // read current config
dcb.BaudRate = baud;
dcb.ByteSize = 8;
dcb.StopBits = ONESTOPBIT;
dcb.Parity = NOPARITY;
dcb.fParity = FALSE;
SetCommState(hComm, &dcb);
}
//Reading:(PS: private: char rx_packet[1024]; int rx_size;)
int readByte(int timeout)
{
COMMTIMEOUTS CommTimeOuts;
CommTimeOuts.ReadIntervalTimeout = 1;
CommTimeOuts.ReadTotalTimeoutMultiplier = timeout;
CommTimeOuts.ReadTotalTimeoutConstant = 0;
CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
CommTimeOuts.WriteTotalTimeoutConstant = 0;
SetCommTimeouts(hComm, &CommTimeOuts);
char byte;
DWORD bytes = 0;
if (ReadFile(hComm, &byte, 1, &bytes, NULL))
{
return bytes == 1 ? byte : -1;
}
return -1;
}
void readPacket(void)
{
int data_read;
bool first_read = true;
rx_size = 0;
DWORD dwEventMask;
DWORD ERR = 0;
if (!SetCommMask(hComm, EV_RXCHAR)) return;
if (!WaitCommEvent(hComm, &dwEventMask, NULL)) return;
while (rx_size < MAX_PACKET_SIZE)
{
data_read = readByte(first_read ? 200 : 50);
first_read = false;
if (data_read == -1)return;
rx_packet[rx_size] = (char)data_read;
rx_size++;
}
}
//Writing port:
bool writeByte(char byte)
{
DWORD bytes = 0;
WriteFile(hComm, &byte, 1, &bytes, NULL);
return bytes == 1 ? true : false;
}
void RvcCommUART::writePacket(BYTE *data , UINT16 size)
{
int tx_index = 0;
while (tx_index < size)
{
if (writeByte(data[tx_index]) == false) return;
tx_index++;
}
}
It seems that your char is signed (its signedness is implementation-dependent), so 0xFF is -1.
Use unsigned char to represent "bytes".
I need to send binary data over a serial port, without any bytes getting reinterpreted as control characters along the way. I'm currently setting up my serial port as follows:
#include <windows.h>
// open serial port
HANDLE hSerial;
hSerial = CreateFile ("COM1", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
// get serial parameters
DCB dcbSerialParams = {0};
dcbSerialParams.DCBlength = sizeof (dcbSerialParams);
if (!GetCommState(hSerial, &dcbSerialParams)) {
cout << "error getting state\n";
exit(0);
}
// set serial params
dcbSerialParams.BaudRate = CBR_115200;
dcbSerialParams.ByteSize = 8;
dcbSerialParams.StopBits = ONESTOPBIT;
dcbSerialParams.Parity = NOPARITY;
if (!SetCommState (hSerial, &dcbSerialParams)) {
cout << "error setting parameters\n";
exit(0);
}
// set time outs
COMMTIMEOUTS timeouts = {0};
timeouts.ReadIntervalTimeout = 50;
timeouts.ReadTotalTimeoutConstant = 10;
timeouts.ReadTotalTimeoutMultiplier = 10;
timeouts.WriteTotalTimeoutConstant = 10;
timeouts.WriteTotalTimeoutMultiplier = 10;
if (!SetCommTimeouts (hSerial, &timeouts)) {
cout << "problem setting timeout values\n";
exit(0);
} else cout << "timeouts set\n";
When I issue ReadFile commands, I can get and display bytes from 0 to 255 with no problem. but I'm having no such luck with WriteFile. Is there a way to explicitly set a binary write mode?
EDIT
Ok, here's some more info. I have a windows machine and a linux single board computer hooked up through serial, the code above on the windows side is followed by:
unsigned char temp = 0;
bool keepReading = true;
while (keepReading) {
DWORD dwBytesRead = 0;
ReadFile (hSerial, &temp, 1, &dwBytesRead, NULL);
if (1 == dwBytesRead) cout << (unsigned int) temp << " ";
if (255 == temp) keepReading = false;
}
cout << endl;
bool keepWriting = true;
char send = 0;
while (keepWriting) {
DWORD dwBytesWritten = 0;
WriteFile (hSerial, &send, 1, &dwBytesWritten, NULL);
send++;
if (256 == send) keepWriting = false;
}
My code on the linux side looks like this:
int fd = open("/dev/ttymxc0", O_RDWR | O_NOCTTY);
struct termios options;
bzero (options, sizeof(options));
options.c_cflag = B115200 | CS8 | CLOCAL | CREAD;
options.c_iflat = IGNPAR;
options.c_oflag = 0;
options.c_lflag = ICANON;
options.c_cc[VMIN] = 1;
options.c_CC[VTIME] = 0;
tcflush (fd, TCIFLUSH);
tcsetattr (fd, ICSANOW, &options);
bool keepWriting = true;
char send = 0;
while (keepWriting) {
write (fd, &send, 1);
send++;
if (256 == send) keepWriting = false;
}
bool keepReading = true;
while (keepReading) {
char temp = 0;
int n = read (fd, &temp, 1);
if (-1 == n) {
perror ("Read error");
keepReading = false;
} else if (1 == n) {
cout << temp << " ";
}
if (256 == temp) keepReading = false;
}
cout << endl;
close(fd);
I start up the code on both machines, and the first set of while loops runs fine. The terminal on the windows side displays 0 through 255. Then it just sits there. If I output the number of bytes read on the linux side for the second set of while loops, it continually gives me 0 bytes. This would indicate a closed port normally, but I just sent a bunch of info through it so how could that be?
As Jonathan Potter mentions, most likely you don't have XON/XOFF flow control turned off. Add these lines before the call to SetCommState:
dcbSerialParams.fOutX = 0;
dcbSerialParams.fInX = 0;
Some other fields which you may need to set:
dcbSerialParams.fNull = 0;
dcbSerialParams.fDtrControl = DTR_CONTROL_DISABLE;
dcbSerialParams.fRtsControl = RTS_CONTROL_DISABLE;
I think what may be happening is that Linux is detecting a break, and resetting the port, or the fact that canonical mode is set is messing it up. Try these settings in addition to what you have already:
options.c_iflag |= IGNBRK;
options.c_iflag &= ~BRKINT;
options.c_iflag &= ~ICRNL;
options.c_oflag = 0;
options.c_lflag = 0;
Alright so I figured it out, rather, a co-worker did. On the linux side, in the file /etc/inittab I had to comment out the line:
T0:23:respawn:/sbin/getty -L ttymxc0 115200 vt100
This was grabbing the serial port in a way that made it unusable for receiving bytes. I now see the expected output.