I am doing some embedded programming using Python for the PC side and C for a controller side. Serial reading in python is easy in a sense that you can read a certain amount of bytes, but I am having ,,problems,, with reading in C. Is it possible to read, for example 5 bytes, without waiting for the 'EOL' character('\n' or 0x0a)? For now, I am adding '\n' at the end of every buffer transmitted from PC to controller but I would like to get rid of that since there is around 1 in 255 chance of failing the transmission (for every byte sent) if byte gets the value b'\x0a' and I always know the number of bytes I should expect from the value of the first byte. Thanks in advance everyone :-)
this is a part of the function
void recv(int port){ //function to receive buffer
//we are gonna receive a message and since this is an echo type of program we will signal
//signal thread to loop it back around
printf("Opened connection on port:%d \n",port);
while(1){
if(stop){
break;
}
//values are simulated with rand(), there is 10% movement to fall out of range
voltage=rand_value(VOLTAGE_MIN-100000,VOLTAGE_MAX 100000);
current=rand_value(CURRENT_MIN-100000,CURRENT_MAX 100000);
temperature=rand_value(TEMP_MIN-30,TEMP_MAX 30);
int nread;
ioctl(port, FIONREAD, &nread);
if (nread > 0) {
memset(buf,0,sizeof(buf));
int n=read(port,&buf,nread); //blocking operation, it waits for "\n"
/* for(int i=0; i<BUF_LEN; i ){
//printf("Msg received: %s",buf);
printf("buf index %d, data 0x%x \n", i, buf[i]);
} */
req=buf[0]; //here we have command ID data ID
// 2bit 6bit
printf("Bytes received: %d, req= 0x%x\n",n,req); //prints the register and count of data received (always gets one above the actual data!)
switch (((req&0b11000000)>>6)){ //SWITCHES COMMAND ID-S
this is opening the port in main
int port=open("/dev/ttyPS1",O_RDWR);
in between these 2 goes termios setup
recv(port);
so even tho i use number of available bytes it completely ignores that and waits for the 0x0a value
CodePudding user response:
You can use the read system call (or fread for FILE*).
Usage with file descriptor:
int fd = STDIN_FILENO; // or your stream
int max_len = 10;
char buffer[max_len];
int actual_len = read(fd, buffer, max_len);
if (actual_len < 0) {
exit(1); // error
}
Usage with FILE*:
FILE* file = stdin; // or your stream
int max_len = 10;
char buffer[max_len];
int actual_len = fread(file, buffer, max_len);
if (actual_len < 0) {
exit(1); // error
}
The read systemcall reads up to n bytes into a buffer and returnes the number it could read. So if your stream has "hello" (without null terminator) as content, it will return 5.
And also I think you missunerstood EOF. EOF isn't actually a transmitted byte, it is a placeholder for stdio to signal that no more bytes were availible. Depending on the settings of the stream it can happen that you never get a EOF and the process just blocks until the stream is closed.
CodePudding user response:
So from thinking about things people said in the comments and reading a recommended question this post about buffer reading I made it work pretty much as I was trying for days
I used this time flags where BUF_LEN is defined constant of the max possible buffer received What I don't like about this solution is that it is load depended but it is what it is.
tty.c_cc[VTIME] = 2; // Wait for up to 0.2s (2 deciseconds), returning as soon as any data is received.
tty.c_cc[VMIN] = BUF_LEN;