write_noncanonical
unknown
c_cpp
2 years ago
5.9 kB
8
Indexable
// Write to serial port in non-canonical mode #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <termios.h> #include <unistd.h> #include <signal.h> // Baudrate settings are defined in <asm/termbits.h>, which is // included by <termios.h> #define BAUDRATE B38400 #define _POSIX_SOURCE 1 // POSIX compliant source #define FALSE 0 #define TRUE 1 #define FLAG 0x7e #define ADDRESS 0x03 #define SET 0x03 #define UA 0x07 #define BUF_SIZE 256 typedef enum{ START, FLAG_RCV, A_RCV, C_RCV, BCC_OK, STOP, } STATE; int alarmEnabled = FALSE; int alarmCount = 0; // Alarm function handler void alarmHandler(int signal) { alarmEnabled = FALSE; alarmCount++; printf("Alarm #%d\n", alarmCount); } // Inital State STATE state = START; int main(int argc, char *argv[]) { int fd; char set_buf[5], ua_buf[5]; // Program usage: Uses either COM1 or COM2 const char *serialPortName = argv[1]; if (argc < 2) { printf("Incorrect program usage\n" "Usage: %s <SerialPort>\n" "Example: %s /dev/ttyS1\n", argv[0], argv[0]); exit(1); } // Open serial port device for reading and writing, and not as controlling tty // because we don't want to get killed if linenoise sends CTRL-C. fd = open(serialPortName, O_RDWR | O_NOCTTY); if (fd < 0) { perror(serialPortName); exit(-1); } struct termios oldtio; struct termios newtio; // Save current port settings if (tcgetattr(fd, &oldtio) == -1) { perror("tcgetattr"); exit(-1); } // Clear struct for new port settings memset(&newtio, 0, sizeof(newtio)); newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD; newtio.c_iflag = IGNPAR; newtio.c_oflag = 0; // Set input mode (non-canonical, no echo,...) newtio.c_lflag = 0; newtio.c_cc[VTIME] = 0; // Inter-character timer unused newtio.c_cc[VMIN] = 1; // Blocking read until 5 chars received // VTIME e VMIN should be changed in order to protect with a // timeout the reception of the following character(s) // Now clean the line and activate the settings for the port // tcflush() discards data written to the object referred to // by fd but not transmitted, or data received but not read, // depending on the value of queue_selector: // TCIFLUSH - flushes data received but not read. tcflush(fd, TCIOFLUSH); // Set new port settings if (tcsetattr(fd, TCSANOW, &newtio) == -1) { perror("tcsetattr"); exit(-1); } printf("New termios structure set\n"); // Create SET Buffer to send set_buf[0] = FLAG; set_buf[1] = ADDRESS; set_buf[2] = SET; set_buf[3] = set_buf[1]^set_buf[2]; set_buf[4] = FLAG; // Set alarm function handler (void)signal(SIGALRM, alarmHandler); while(state != STOP && alarmCount < 4) { printf("While start\n"); if (alarmEnabled == FALSE) { if( (write(fd, set_buf, 5)) <= 0) return -1; alarm(3); // Set alarm to be triggered in 3s alarmEnabled = TRUE; } if (read(fd,ua_buf,1) <= 0) return -1; switch(state) { case START: if (ua_buf[0] == FLAG) { state = FLAG_RCV; printf("UA: FLAG received\n"); } else { state = START; } break; case FLAG_RCV: if (ua_buf[0] == ADDRESS) { state = A_RCV; printf("UA: A received\n"); } else if (ua_buf[0] == FLAG){ state = FLAG_RCV; printf("UA: FLAG received repeated\n"); } else { state = START; } break; case A_RCV: if (ua_buf[0] == UA) { state = C_RCV; printf("UA: C received\n"); } else if (ua_buf[0] == FLAG){ state = FLAG_RCV; } else { state = START; } break; case C_RCV: if (ua_buf[0] == (ADDRESS^UA)) { state = BCC_OK; printf("UA: BCC OK\n"); } else if (ua_buf[0] == FLAG){ state = FLAG_RCV; } else { state = START; } break; case BCC_OK: if (ua_buf[0] == FLAG) { state = STOP; printf("UA: FLAG #2 received\n"); alarm(0); alarmEnabled = TRUE; printf("alarm stopped\n"); } else { state = START; } break; default: state = START; break; } printf("end of loop, state -> %d, alarmEnabled -> %d\n", state, alarmEnabled); } // Wait until all bytes have been written to the serial port sleep(1); // Restore the old port settings if (tcsetattr(fd, TCSANOW, &oldtio) == -1) { perror("tcsetattr"); exit(-1); } close(fd); return 0; }
Editor is loading...