I made a super simple arduino uno sketch to send a serial byte once every second:
void setup(){
Serial.begin(9600);
}
void loop(){
Serial.write(12); // send a byte with the value 12
delay(1000);
}
My arduino is hooked up to com 3.
On the other end of the line, I have a C++ program with the following read function:
int Serial::ReadData(char *buffer, unsigned int nbChar)
{
//Number of bytes we'll have read
DWORD bytesRead;
//Number of bytes we'll really ask to read
unsigned int toRead;
//Use the ClearCommError function to get status info on the Serial port
ClearCommError(this->hSerial, &this->errors, &this->status);
//Check if there is something to read
if(this->status.cbInQue>0)
{
//If there is we check if there is enough data to read the required number
//of characters, if not we'll read only the available characters to prevent
//locking of the application.
if(this->status.cbInQue>nbChar)
{
toRead = nbChar;
}
else
{
toRead = this->status.cbInQue;
}
//Try to read the require number of chars, and return the number of read bytes on success
if(ReadFile(this->hSerial, buffer, toRead, &bytesRead, NULL) && bytesRead != 0)
{
return bytesRead;
}
}
//If nothing has been read, or that an error was detected return -1
return -1;
}
This seems to check only one time if data is available, so obviously I have to loop through it until data comes in. I did that in my main program:
#include "Serial.h"
#include <iostream>
using namespace std;
int main(void)
{
Serial serial("COM3");
char* c = "";
int len = strlen(c);
while(c == "")
{
serial.ReadData(c, len);
}
cout << "\n\n";
system("PAUSE");
}
When I do this, my C++ program gets stuck in an infinite loop waiting for data from the arduino, and I cannot figure out why this is happening. My program never sees the data the arduino is sending.
This Serial class works and is configured properly because I can SEND all the data I want to the arduino without any problems. My issues are only with reading back from the arduino.
Can someone please help me figure out why this is not working?
-
1Welcome to Arduino SE! Have you verified the Arduino code outputs the right data with the serial monitor? If so, I think this question should be migrated to another site to address the C++ code. Thanks!Anonymous Penguin– Anonymous Penguin2014年07月31日 00:23:05 +00:00Commented Jul 31, 2014 at 0:23
-
I think your C++ program needs to know what data rate (baud) to use.user3388– user33882014年07月31日 00:35:20 +00:00Commented Jul 31, 2014 at 0:35
-
Can you also confirm that the receiver program works if you send some "correct" data with a terminal program? The answers to those two questions will tell you whether to look at the Arduino, the receiving CPU, or the serial line.JRobert– JRobert2014年07月31日 00:36:13 +00:00Commented Jul 31, 2014 at 0:36
-
I want to send keypad data from Arduino to Code Composer Studio or CCS and i'm using Texas instruments (TMS320F8069). When I send the data, I hope that CCS will show the Arduino data that i already send. And the CCS will send it back. It's like a TR > RX program. But, it's not work. I mean the CCS console (serial monitor) doesn't show the data. So, can you guys help me solve this problem? Here my CCS code... const int LEN = 1; char msgg[LEN + 1]; int numBytes = 0; for(;;) { msgg [numBytes] = 0; scia_msg(msg); // Wait for inc character while(SciaRegs.SCIFFRX.bit.RXFFST !=1) { } // wait for XRDYAmirullah S.– Amirullah S.2018年09月28日 04:13:37 +00:00Commented Sep 28, 2018 at 4:13
2 Answers 2
The problem is in your C++ program at the other end of the line (not the Arduino side):
char* c = "";
int len = strlen(c);
while(c == "")
{
serial.ReadData(c, len);
}
Here, len
is zero because that is the length of "" , the empty string! Thus, in your loop, you ask ReadData
to read 0 bytes. Hence, the condition of your while
loop is always true as, c
never changes.
Also, the while
condition seems incorrect as it is not recommended in C++ to compare 2 strings (defines as char *
or char [...]
) with ==
. In your situation, what is important is the number of characters read by ReadData
:
char c[LEN + 1];
int numBytes = 0;
while(true)
{
numBytes = serial.ReadData(c, LEN);
if (numBytes != -1)
{
// Terminate the string if we want to use c variable as a string
c[numBytes] = 0;
break;
}
}
in the code above, LEN
is the number of characters you want to read at one time, in you example it should be set to 1, either as a #define
or as a const
variable:
// either:
#define LEN 1
// or:
const int LEN = 1;
The code above also ensures that c
can be used as a normal string, by adding a 0
at the end. This is mandatory only if you want to use string functions on c
such as strlen
, strcpy
, strchr
... otherwise numBytes
is enough to manage the number of characters read into c
.
char* c = "";
while(c == "")
The variable named c is a misnomer, because it is a pointer to a string, not a character. For example c = 0x123456.
You should use a more explicit name for your variable.
This first line assigns a pointer to an empty string to the c pointer. So, the value stored at address 0x123456 == whatever pointer to a static memory address containing '0円'
Note that no memory has been allocated to hold characters. Only a pointer to char has been allocated. Thus you cannot store anything in your string!!
You could write something like:
char data[2] = "";
That would allocate a pointer, and a string to hold 2 characters
The second line, while(c == "")
compares a real memory pointer (e.g. 0x123456) with a compiler pointer.
""
is not a real application pointer, you should not manipulate it.
So that second line relies on a compiler behavior.
If I were you I would wrap the multi-char routine into a single-char routine. For example:
int ReadChar(char *c)
{
return ReadData(c, 1);
}
Then:
main()
{
char c;
ReadChar(&c);
}
On a different note, I think the compiler should catch such error.
The line c == ""
would never do anything useful and should be caught.