Porta seriale in C linux
Ciao a tutti, sto realizzando un esempio di comunicazione con un micro tramite porta seriale, in pratica il micro riceve byte per byte e dopo il timeout dell'ultimo carattere invia indietro la stringa, cercando su internet ho trovato diversi siti che spiegano come scrivere del codice per far funzionare una porta seriale e così ho scritto una prima bozza di programma:
Il codice funziona, però se tolgo lo sleep(1) legge soltanto il primo carattere, non posso impostare il VMIN perché la lunghezza dei dati trasmessi può variare e a parte questo la funzione read ritorna al raggiungimento dei caratteri impostati, non aspetta la fine del timeout che indica la fine della stringa, in pratica dovrei affidarmi al VTIME che dovrebbe essere il parametro di attesa dall'ultimo carattere ricevuto che però sembra non funzionare, ho provato anche con valori più alti ma la stringa si ferma sempre al primo carattere. Nel programma che devo realizzare lo sleep(1) non posso usarlo... Manca qualcosa?
- Codice: Seleziona tutto
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <unistd.h>
#include <sys/ioctl.h>
// /dev/ttyUSB0
int main(){
int serial_port = open("/dev/ttyUSB0", O_RDWR);
struct termios tty;
if(tcgetattr(serial_port, &tty) != 0) {
printf("Error from tcgetattr\n");
return 1;
}
tty.c_cflag &= ~PARENB; // Clear parity bit, disabling parity
tty.c_cflag &= ~CSTOPB; // Clear stop field, only one stop bit used in communication
tty.c_cflag &= ~CSIZE; // Clear all bits that set the data size
tty.c_cflag |= CS8; // 8 bits per byte
tty.c_cflag &= ~CRTSCTS; // Disable RTS/CTS hardware flow control
tty.c_cflag |= CREAD | CLOCAL; // Turn on READ & ignore ctrl lines (CLOCAL = 1)
tty.c_lflag &= ~ICANON;
tty.c_lflag &= ~ECHO; // Disable echo
tty.c_lflag &= ~ECHOE; // Disable erasure
tty.c_lflag &= ~ECHONL; // Disable new-line echo
tty.c_lflag &= ~ISIG; // Disable interpretation of INTR, QUIT and SUSP
tty.c_iflag &= ~(IXON | IXOFF | IXANY); // Turn off s/w flow ctrl
tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL); // Disable any special handling of received bytes
tty.c_oflag &= ~OPOST; // Prevent special interpretation of output bytes ( newline chars)
tty.c_oflag &= ~ONLCR; // Prevent conversion of newline to carriage return/line feed
tty.c_cc[VTIME] = 10; // Wait for up to 1s (10 deciseconds), returning as soon as any data is received.
tty.c_cc[VMIN] = 0;
// Set baud rate 9600/*
cfsetispeed(&tty, B9600);
cfsetospeed(&tty, B9600);
// Save tty settings
if (tcsetattr(serial_port, TCSANOW, &tty) != 0) {
printf("Error from tcsetattr\n");
return 1;
}
// Write to serial port
unsigned char messaggio[] = { 'H', 'e', 'l', 'l', 'o', '\r' };
write(serial_port, messaggio, sizeof(messaggio));
// Allocate memory for read buffer, set size according to your needs
char read_buf [256];
memset(read_buf, '\0', sizeof(read_buf));
sleep(1);
//int bytes;
//ioctl(serial_port, FIONREAD, &bytes);
//printf("Bytes %d\n",bytes);
//sleep(1);
// Read bytes. The behaviour of read() (e.g. does it block?,
// how long does it block for?) depends on the configuration
// settings above, specifically VMIN and VTIME
int num_bytes = read(serial_port, &read_buf, sizeof(read_buf));
// n is the number of bytes read. n may be 0 if no bytes were received, and can also be -1 to signal an error.
if (num_bytes < 0) {
printf("Error reading");
return 1;
}
printf("Read %d bytes. Received message: %s\n", num_bytes, read_buf);
close(serial_port);
return 0;
}
Il codice funziona, però se tolgo lo sleep(1) legge soltanto il primo carattere, non posso impostare il VMIN perché la lunghezza dei dati trasmessi può variare e a parte questo la funzione read ritorna al raggiungimento dei caratteri impostati, non aspetta la fine del timeout che indica la fine della stringa, in pratica dovrei affidarmi al VTIME che dovrebbe essere il parametro di attesa dall'ultimo carattere ricevuto che però sembra non funzionare, ho provato anche con valori più alti ma la stringa si ferma sempre al primo carattere. Nel programma che devo realizzare lo sleep(1) non posso usarlo... Manca qualcosa?