From: Rostislav Lisovy Date: Wed, 23 Nov 2011 17:59:26 +0000 (+0100) Subject: Setting UART speed to custom value for sending break. X-Git-Url: http://rtime.felk.cvut.cz/gitweb/linux-lin.git/commitdiff_plain/ac6710155c90cd27d69bd0c930e81c1ce0738d33 Setting UART speed to custom value for sending break. Used with 19200 baud rate for data TX, break generated by sending 0x00 with 12800 baud rate. PCAN LIN converter configured as a slave does respond. --- diff --git a/misc/tty_lin_master/Makefile b/misc/tty_lin_master/Makefile index 6bf535a..06443ed 100644 --- a/misc/tty_lin_master/Makefile +++ b/misc/tty_lin_master/Makefile @@ -1,2 +1,2 @@ all: main.c - gcc main.c -std=gnu99 -Wall -pedantic -o main + gcc main.c -lrt -std=gnu99 -Wall -pedantic -o main diff --git a/misc/tty_lin_master/main.c b/misc/tty_lin_master/main.c index a61566c..dfad09a 100644 --- a/misc/tty_lin_master/main.c +++ b/misc/tty_lin_master/main.c @@ -9,22 +9,30 @@ #include #include #include - -#define UART_SPEED B2400 +#include +#include /* struct struct_serial */ +#include +#include +#include /* clock_nanosleep */ #define LIN_HDR_SIZE 2 #define LIN_PKT_MAX_SIZE 16 /* FIXME */ -struct termios term_attr; + +int lin_baudrate = B19200; +int lin_break_baud = 0; + +struct termios tattr_orig; +struct termios tattr; +struct serial_struct sattr; /* ------------------------------------------------------------------------ */ static void reset_input_mode(int tty) { - tcsetattr(tty, TCSANOW, &term_attr); + tcsetattr(tty, TCSANOW, &tattr_orig); } static void set_input_mode(int tty, speed_t speed) { int status; - struct termios tattr; /* Flush input and output queues. */ if (tcflush(tty, TCIOFLUSH) != 0) { @@ -39,19 +47,49 @@ static void set_input_mode(int tty, speed_t speed) } /* Save settings for later restoring */ - tcgetattr(tty, &term_attr); + tcgetattr(tty, &tattr_orig); + if (ioctl(tty, TIOCGSERIAL, &sattr) < 0) { + perror("ioctl()"); + } /* RAW mode */ tcgetattr(tty, &tattr); - tattr.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP - | INLCR | IGNCR | ICRNL | IXON); - tattr.c_oflag &= ~OPOST; - tattr.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); - tattr.c_cflag &= ~(CSIZE | PARENB); - tattr.c_cflag |= CS8; - - tattr.c_cc[VMIN] = 1; - tattr.c_cc[VTIME] = 0; +// tattr.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP +// | INLCR | IGNCR | ICRNL | IXON); +// tattr.c_oflag &= ~OPOST; +// tattr.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); +// tattr.c_cflag &= ~(CSIZE | PARENB); +// tattr.c_cflag |= CS8; + + /* Sets hardware control flags: */ + /* 8 data bits */ + /* Enable receiver */ + /* Ignore CD (local connection) */ + tattr.c_cflag = CS8 | CREAD | CLOCAL; + tattr.c_iflag = 0; + tattr.c_oflag = NL0 | CR0 | TAB0 | BS0 | VT0 | FF0; + tattr.c_lflag = 0; + +// tattr.c_cc[VMIN] = 1; +// tattr.c_cc[VTIME] = 0; + + tattr.c_cc[VINTR] = '\0'; + tattr.c_cc[VQUIT] = '\0'; + tattr.c_cc[VERASE] = '\0'; + tattr.c_cc[VKILL] = '\0'; + tattr.c_cc[VEOF] = '\0'; + tattr.c_cc[VTIME] = '\0'; + tattr.c_cc[VMIN] = 1; + tattr.c_cc[VSWTC] = '\0'; + tattr.c_cc[VSTART] = '\0'; + tattr.c_cc[VSTOP] = '\0'; + tattr.c_cc[VSUSP] = '\0'; + tattr.c_cc[VEOL] = '\0'; + tattr.c_cc[VREPRINT] = '\0'; + tattr.c_cc[VDISCARD] = '\0'; + tattr.c_cc[VWERASE] = '\0'; + tattr.c_cc[VLNEXT] = '\0'; + tattr.c_cc[VEOL2] = '\0'; /* Set TX, RX speed */ cfsetispeed(&tattr, speed); @@ -61,27 +99,69 @@ static void set_input_mode(int tty, speed_t speed) if (status == -1) perror("tcsetattr()"); + /* Baudrate for sending LIN break */ + //lin_break_baud = ((lin_baudrate * 2) / 3); + lin_break_baud = 12800; } int send_header(int tty) { - struct termios tattr; int buff[3]; buff[0] = 0x00; /* Sync byte */ buff[1] = 0x55; /* Sync byte */ buff[2] = 0xC1; /* LIN ID: 1 */ + printf("send_header() invoked\n"); + tcflush(tty, TCIOFLUSH); - /* Decrease speed to send BREAK (simulated with 0x00 data frame)*/ - tcgetattr(tty, &tattr); - cfsetospeed(&tattr, B1200); - tcsetattr(tty, TCSADRAIN, &tattr); + /* Decrease speed to send BREAK + * (simulated with 0x00 data frame) */ + + /* Set "non-standard" baudrate in serial_struct struct */ + sattr.flags &= (~ASYNC_SPD_MASK); + sattr.flags |= (ASYNC_SPD_CUST); + //sattr.custom_divisor = (115200/12800); + sattr.custom_divisor = ((sattr.baud_base)/12800); + if (ioctl(tty, TIOCSSERIAL, &sattr) < 0) + { + perror("ioctl()"); + } + cfsetospeed(&tattr, B38400); /* Should be set to this fixed value */ + cfsetispeed(&tattr, B38400); + if (tcsetattr(tty, TCSANOW, &tattr) == -1) { + perror("tcsetattr()"); + } - write(tty, &buff[0], 1); - cfsetospeed(&tattr, UART_SPEED); - tcsetattr(tty, TCSADRAIN, &tattr); + printf("Write break\n"); + write(tty, &buff[0], 1); /* Write "break" */ +#if 0 + read(tty, &buff[0], 1); + printf("Break read\n"); +#else + { + struct timespec sleep_time; + sleep_time.tv_sec = 0; + sleep_time.tv_nsec = ((1000000000ll * 11) / lin_break_baud); + clock_nanosleep(CLOCK_MONOTONIC, 0, &sleep_time, NULL); + } +#endif + + sattr.flags &= (~ASYNC_SPD_CUST); + sattr.flags |= (ASYNC_SPD_MASK); + if (ioctl(tty, TIOCSSERIAL, &sattr) < 0) + { + perror("ioctl()"); + } + + + /* Save "standard" baudrate to termios struct */ + cfsetospeed(&tattr, lin_baudrate); + cfsetispeed(&tattr, lin_baudrate); + if (tcsetattr(tty, TCSANOW, &tattr) == -1) { + perror("tcsetattr()"); + } //tcsendbreak(tty, 1); /* Break */ //usleep((useconds_t) 50); /* Break Delimiter */ @@ -151,13 +231,21 @@ int main(int argc, char* argv[]) return -4; } + fcntl(fileno(stdin), F_SETFL, O_NONBLOCK); + printf("Press enter to terminate.\n\n"); + /* Configure UART */ - set_input_mode(tty, UART_SPEED); + set_input_mode(tty, lin_baudrate); while(1) { + char c; + send_header(tty); sleep(1); - } + + if (read(fileno(stdin), &c, 1) > 0) + break; + } reset_input_mode(tty); close(tty);