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...
Related
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
I have copied this code to write through the serial port in c++. It works properly, but what I need now is to know how to convert a string into an array of bytes, because I want to write several strings to communicate with an arduino. I paste the code here:
#include <windows.h>
#include <stdio.h>
int main()
{
// Define the five bytes to send ("hello")
char bytes_to_send[5];
bytes_to_send[0] = 104;
bytes_to_send[1] = 101;
bytes_to_send[2] = 108;
bytes_to_send[3] = 108;
bytes_to_send[4] = 111;
// Declare variables and structures
HANDLE hSerial;
DCB dcbSerialParams = {0};
COMMTIMEOUTS timeouts = {0};
// Open the highest available serial port number
fprintf(stderr, "Opening serial port...");
hSerial = CreateFile(
"\\\\.\\COM1", GENERIC_READ|GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if (hSerial == INVALID_HANDLE_VALUE)
{
fprintf(stderr, "Error\n");
return 1;
}
else fprintf(stderr, "OK\n");
// Set device parameters (38400 baud, 1 start bit,
// 1 stop bit, no parity)
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
if (GetCommState(hSerial, &dcbSerialParams) == 0)
{
fprintf(stderr, "Error getting device state\n");
CloseHandle(hSerial);
return 1;
}
dcbSerialParams.BaudRate = CBR_38400;
dcbSerialParams.ByteSize = 8;
dcbSerialParams.StopBits = ONESTOPBIT;
dcbSerialParams.Parity = NOPARITY;
if(SetCommState(hSerial, &dcbSerialParams) == 0)
{
fprintf(stderr, "Error setting device parameters\n");
CloseHandle(hSerial);
return 1;
}
// Set COM port timeout settings
timeouts.ReadIntervalTimeout = 50;
timeouts.ReadTotalTimeoutConstant = 50;
timeouts.ReadTotalTimeoutMultiplier = 10;
timeouts.WriteTotalTimeoutConstant = 50;
timeouts.WriteTotalTimeoutMultiplier = 10;
if(SetCommTimeouts(hSerial, &timeouts) == 0)
{
fprintf(stderr, "Error setting timeouts\n");
CloseHandle(hSerial);
return 1;
}
// Send specified text (remaining command line arguments)
DWORD bytes_written, total_bytes_written = 0;
fprintf(stderr, "Sending bytes...");
if(!WriteFile(hSerial, bytes_to_send, 5, &bytes_written, NULL))
{
fprintf(stderr, "Error\n");
CloseHandle(hSerial);
return 1;
}
fprintf(stderr, "%d bytes written\n", bytes_written);
// Close serial port
fprintf(stderr, "Closing serial port...");
if (CloseHandle(hSerial) == 0)
{
fprintf(stderr, "Error\n");
return 1;
}
fprintf(stderr, "OK\n");
// exit normally
return 0;
}
Here is the part I want to change:
// Define the five bytes to send ("hello")
char bytes_to_send[5];
bytes_to_send[0] = 104;
bytes_to_send[1] = 101;
bytes_to_send[2] = 108;
bytes_to_send[3] = 108;
bytes_to_send[4] = 111;
I want to use my own strings and a method to transform them into bytes, so that I can send them through the serial port.
A string already is an array of bytes.
char bytes_to_send[] = "hello";
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.
I am trying to write code in c++ to write and read from serial port i wrote the following code and i am now trying to test this by making loop back on USB to serial cable and when i write any thing except zero i read it successfully but when write zero the program stops reading and doesnot read any thing after the zero and give me zeroes when displaying the read buffer (in this program it displays zeroes for reading buffer but if i write any thing like making writing loop write "words=127-i" the reader buffer will display all i write till it reaches zero) plz any help quickly
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <commdlg.h>
#include <iostream>
//#include <windef.h>
using namespace std;
int nread,nwrite;
void main()
{
HANDLE hSerial;
COMMTIMEOUTS timeouts;
COMMCONFIG dcbSerialParams;
char words[128], *buffWrite;
DWORD dwBytesWritten, dwBytesRead;
hSerial = CreateFile(TEXT("COM1"),GENERIC_READ |GNERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(hSerial == INVALID_HANDLE_VALUE)
{
if (GetLastError() == ERROR_FILE_NOT_FOUND)
{
printf(" serial port does not exist \n");
}
printf(" some other error occured. Inform user.\n");
}
// DCB dcbSerialParams ;
//GetCommState( hSerial, &dcbSerialParams.dcb);
if (!GetCommState(hSerial, &dcbSerialParams.dcb))
{
printf("error getting state \n");
}
dcbSerialParams.dcb.DCBlength = sizeof(dcbSerialParams.dcb);
dcbSerialParams.dcb.BaudRate = CBR_2400;
dcbSerialParams.dcb.ByteSize = 8;
dcbSerialParams.dcb.StopBits = ONESTOPBIT;
dcbSerialParams.dcb.Parity = NOPARITY;
dcbSerialParams.dcb.fBinary = TRUE;
dcbSerialParams.dcb.fDtrControl = DTR_CONTROL_ENABLE;
dcbSerialParams.dcb.fRtsControl = RTS_CONTROL_ENABLE;
dcbSerialParams.dcb.fOutxCtsFlow = TRUE;
dcbSerialParams.dcb.fOutxDsrFlow = TRUE;
dcbSerialParams.dcb.fDsrSensitivity= FALSE;
dcbSerialParams.dcb.fAbortOnError = TRUE;
if(!SetCommState(hSerial, &dcbSerialParams.dcb))
{
printf(" error setting serial port state \n");
}
SetCommMask( hSerial,EV_RXCHAR);
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");
}
// printf("This is a string to be written to serial port COM1 \n\n\n");
//****************Write Operation*********************//
//words = "This is a string to be written to serial port COM1";
//dwBytesWritten=1;
cout<<"Data written to write buffer is \n";
for(int i=0;i<128;i++)
{
words[i]=i;
cout<<(int)words[i]<<",";
}
cout<<endl;
nwrite = strlen(words);
buffWrite = words;
dwBytesWritten = 0;
if (!WriteFile(hSerial, buffWrite, nwrite, &dwBytesWritten, NULL))
{
printf("error writing to output buffer \n");
}
//***************Read Operation******************//
char buffsRead[128]="0",*buffRead;
dwBytesRead = 0;
nread = strlen(buffsRead);
buffRead = buffsRead;
//ReadFile(hSerial, buffRead, nread, &dwBytesRead, NULL);
if (!ReadFile(hSerial, buffRead, nread, &dwBytesRead, NULL))
{
printf("error reading from input buffer \n");
}
// printf("Data read from read buffer is \n %s \n",(int)buffsRead);
cout<<"Data read from read buffer is \n ";
for(int j=0;j<128;j++)
{
cout<<(int)buffsRead[j]<<",";
}
cout<<endl;
CloseHandle(hSerial);
// system("PAUSE");
}
The problem is in your calculation of the number of bytes to write. You have
nwrite = strlen(words);
and that does not work on binary data, because strlen stops at the first '\0' (NUL character).
Just adjust nwrite inside your loop, so that it ends up with the number of characters added. Replace
words[i]=i;
with
words[nwrite++] = i;
and get rid of nwrite = strlen(words); and things will work better.
I am writing a program in Visual C++ to access serial port.Code is given below:-
#include "stdafx.h"
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <commdlg.h>
int nread,nwrite;
void main()
{
COMMTIMEOUTS timeouts;
COMMCONFIG dcbSerialParams;
char *words,*buffRead, *buffWrite;
DWORD dwBytesWritten,dwBytesRead;
HANDLE hSerial= CreateFile(L"COM1", GENERIC_READ | GENERIC_WRITE,
0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
if ( hSerial == INVALID_HANDLE_VALUE)
{
if (GetLastError() == ERROR_FILE_NOT_FOUND)
{
printf(" serial port does not exist \n");
}
printf(" some other error occured. Inform user.\n");
}
//DCB dcbSerialParams ;
//GetCommState( hSerial, &dcbSerialParams.dcb);
if (!GetCommState(hSerial, &dcbSerialParams.dcb))
{
printf("error getting state \n");
}
dcbSerialParams.dcb.DCBlength = sizeof(dcbSerialParams.dcb);
dcbSerialParams.dcb.BaudRate = CBR_1200;
dcbSerialParams.dcb.ByteSize = 8;
dcbSerialParams.dcb.StopBits = ONESTOPBIT;
dcbSerialParams.dcb.Parity = NOPARITY;
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;
if (!SetCommState(hSerial, &dcbSerialParams.dcb))
{
printf(" error setting serial port state \n");
}
GetCommTimeouts(hSerial,&timeouts);
timeouts.ReadIntervalTimeout = 1000;
timeouts.ReadTotalTimeoutConstant = 1000;
timeouts.ReadTotalTimeoutMultiplier = 1000;
timeouts.WriteTotalTimeoutConstant = 1000;
timeouts.WriteTotalTimeoutMultiplier= 1000;
if(!SetCommTimeouts(hSerial, &timeouts))
{
printf("error setting port state \n");
}
//****************Write Operation*********************//
words = "B";
nwrite = strlen(words);
buffWrite = words;
dwBytesWritten = 0;
if (!WriteFile(hSerial, buffWrite, nwrite, &dwBytesWritten, NULL))
{
printf("error writing to output buffer \n");
}
printf("Data written to write buffer is\n %s \n",buffWrite);
//***************Read Operation******************//
buffRead = 0;
dwBytesRead = 0;
nread = strlen(words);
if (!ReadFile(hSerial, buffRead, nread, &dwBytesRead, NULL))
{
printf("error reading from input buffer \n");
}
printf("Data read from read buffer is \n %s \n",buffRead);
CloseHandle(hSerial);
}
Above program is working properly while write operation (i.e writing data on serial port) but while read operation its is not reading data from serial port.
I am getting output on console window is given below:-
Data written to write buffer is
B
error reading from input buffer
Data read from read buffer is
<null>
I want to know where I am getting wrong and how to resolve it.
The second ReadFile parameter cannot be NULL. It should be valid pointer to some buffer, for example:
dwBytesRead = 0;
nread = strlen(words);
buffRead = new char[nread + 1];
memset(buffRead, 0, nread+1]; // ensure that string will be null-terminated
if (!ReadFile(hSerial, buffRead, nread, &dwBytesRead, NULL))
{
printf("error reading from input buffer \n");
}
...
delete[] buffRead;