Writing STRINGS to serial port in C++ linux
Solution 1
I'm happy to solve my own solution but yet disappointed to not have seen the trivial matter much sooner. char
by default are signed
in c++, which makes it holding the range -128 to 127. However, we are expecting the ASCII values which are 0 to 255. Hence it's as simple as declaring it to be unsigned char str[]
and everything else should work. Silly me, Silly me.
Still, Thank you everyone for helping me!!!
Solution 2
Are you sure you should end with '\r'? When entering text from console the return key will result in a '\n' character (on Linux) and not '\r'
Also error checking is missing on most functions (open()
, fcntl()
, etc.). Maybe one of these functions fail. To find out how to check for errors read the man page (for example man 2 open
for the open()
command. In case of open()
the man page explains it returns -1 when it could not open the file/port.
After your edit you wrote:
char str[] = {0x56, 0x45, 0x52, 0x0D};
write(tty_fd,str,strlen(str));
which is wrong. strlen
expects a '\0' terminated string which str is obviously not so now it sends your data and whatever there is in memory until it sees a '\0'. You need to add 0x00
to your str
array.
haikalpribadi
Computer Scientist, creator of TypeDB and TypeQL, Founder and CEO of Vaticle
Updated on July 25, 2022Comments
-
haikalpribadi almost 2 years
I know this question is scattered all over the internet, but still, nothing is getting me completely there yet. I want to write data to a serial port in C++ (linux) for a a Propeller board. Program works fine when taking input from the console, but when I write strings to it always return:
ERROR - Invalid command
from the device. I tried creating array ofchar
with Hex values then it worked. here's a working code, below. But how will i be able to just provide a string variable of command and send it to the serial port? perhaps, how do you I convert it to hex values if it's the only way? Thanks everyonenote: the loop is to use user input from console. What i need is a way to send a string variable to the serial port.
#include <string.h> #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <termios.h> int main(int argc,char** argv){ struct termios tio; struct termios stdio; int tty_fd; fd_set rdset; unsigned char c='D'; printf("Please start with %s /dev/ttyS1 (for example)\n",argv[0]); memset(&stdio,0,sizeof(stdio)); stdio.c_iflag=0; stdio.c_oflag=0; stdio.c_cflag=0; stdio.c_lflag=0; stdio.c_cc[VMIN]=1; stdio.c_cc[VTIME]=0; tcsetattr(STDOUT_FILENO,TCSANOW,&stdio); tcsetattr(STDOUT_FILENO,TCSAFLUSH,&stdio); fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK); // make the reads non-blocking memset(&tio,0,sizeof(tio)); tio.c_iflag=0; tio.c_oflag=0; tio.c_cflag=CS8|CREAD|CLOCAL; // 8n1, see termios.h for more information tio.c_lflag=0; tio.c_cc[VMIN]=1; tio.c_cc[VTIME]=5; tty_fd=open(argv[1], O_RDWR | O_NONBLOCK); cfsetospeed(&tio,B115200); // 115200 baud cfsetispeed(&tio,B115200); // 115200 baud tcsetattr(tty_fd,TCSANOW,&tio); //char str[] = {'V','E','R','\r'}; //the above str[] doesn't work although it's exactly the same as the following char str[] = {0x56, 0x45, 0x52, 0x0D}; write(tty_fd,str,strlen(str)); if (read(tty_fd,&c,1)>0) write(STDOUT_FILENO,&c,1); while (c!='q') { if (read(tty_fd,&c,1)>0) write(STDOUT_FILENO,&c,1); // if new data is available on the serial port, print it out if (read(STDIN_FILENO,&c,1)>0) if(c!='q') write(tty_fd,&c,1); // if new data is available on the console, send it to the serial port } close(tty_fd); }
-
Basile Starynkevitch about 12 yearsIs it C or C++ ? If C++, why don't you use
std::string
? -
haikalpribadi about 12 years@BasileStarynkevitch: I've tried doing it:
std::string str="VER\r"; write(tty_fd,str.data(),str.size());
it still returns error. i've tried many ways but only those hex works. do you have any idea? The code is from C, but my program is actually C++. -
Mr Lister about 12 yearsIs it me, or haven't you told us what the error actually says?
-
haikalpribadi about 12 yearsthe serial port just return
ERROR - Invalid command
. So i guess the data reaches the device, but not in the valid format. -
haikalpribadi about 12 years@BasileStarynkevitch Even when I do,
char str[] = {'V', 'E', 'R', '\r'}; write(tty_fd,str,strlen(str));
--it still doesn't work. But again, this works:char str[] = {0x56, 0x45, 0x52, 0x0D}; write(tty_fd,str,strlen(str));
-
rve about 12 yearsSorry, but your solution does not make sense. You are saying
(char)'V' != 0x56
and that(int)'V' == 0x56
??? What platform and compiler are you using??? -
Basile Starynkevitch about 12 yearsa
char str[]
should be terminated by a null byte\0
-
fiorentinoing about 6 yearsas @BasileStarynkevitch already said, the message should be null terminated, e.g.
char str[] = {0x56, 0x45, 0x52, 0x0D, 0x00};
-
-
haikalpribadi about 12 yearsI agree, i haven't done those error checking. But I dont think it's the cause of the problem cause the current commands work (which means the connection is fine). However, it would be really nice if you could point out to me where i should do the checking - all these low level IO is completely new to me, first time. about the
\r
, i dont think it's the issue, cause i even tested this following code and it still returns the same error.char str[] = {'V', 0x45, 0x52, 0x0D}; write(tty_fd,str,strlen(str));
.. and also, i checked on the ASCII table that0x0D
is exactly\r
-
haikalpribadi about 12 yearsand for testing purposes, I tried
\n
too, which didn't work as well. -
Martin James about 12 yearsOK, you need to stop looking at the code now. Connect your serial port to another port on another box and use a terminal app to read what is being sent in both these cases, (which should be the same, but are not).
-
haikalpribadi about 12 years@rve, thanks, but I solved my problem. In regard to your solution, i even tried hard coding the exact value (4) which is suppose to work and it still doesn't. But thanks, really. Anyways, please see my updated question, it has the solution. I can't post it as a solution for now, cause i dont have enough reputation points.