I have a problem with my uart read (on raspberry pi). It works ok but it stops in a loop and waits on data...
I made an option O_NDELAY but is stops even so.
I use two terminal windows:
one is used for uart program
on the second i write:
echo '123445' > /dev/ttyAMA0
(raspberry Pi uart port)
Complete code is below.
#include <stdio.h>
#include <unistd.h> //Used for UART
#include <fcntl.h> //Used for UART
#include <termios.h> //Used for UART
int main(int argv, char * argc[])
{
// Setting Up The UART
//-------------------------
//----- SETUP USART 0 -----
//-------------------------
//At bootup, pins 8 and 10 are already set to UART0_TXD, UART0_RXD (ie the alt0 function) respectively
int uart0_filestream = -1;
//OPEN THE UART
//The flags (defined in fcntl.h):
// Access modes (use 1 of these):
// O_RDONLY - Open for reading only.
// O_RDWR - Open for reading and writing.
// O_WRONLY - Open for writing only.
//
// O_NDELAY / O_NONBLOCK (same function) - Enables nonblocking mode. When set read requests on the file can return immediately with a failure status
// if there is no input immediately available (instead of blocking). Likewise, write requests can also return
// immediately with a failure status if the output can't be written immediately.
//
// O_NOCTTY - When set and path identifies a terminal device, open() shall not cause the terminal device to become the controlling terminal for the process.
uart0_filestream = open("/dev/ttyAMA0", O_RDWR | O_NOCTTY | O_NDELAY); //Open in non blocking read/write mode
if (uart0_filestream == -1)
{
//ERROR - CAN'T OPEN SERIAL PORT
printf("Error - Unable to open UART. Ensure it is not in use by another application\n");
}
//CONFIGURE THE UART
//The flags (defined in termios.h - see http://pubs.opengroup.org/onlinepubs/007908799/xsh/termios.h.html):
// Baud rate:- B1200, B2400, B4800, B9600, B19200, B38400, B57600, B115200, B230400, B460800, B500000, B576000, B921600, B1000000, B1152000, B1500000, B2000000, B2500000, B3000000, B3500000, B4000000
// CSIZE:- CS5, CS6, CS7, CS8
// CLOCAL - Ignore modem status lines
// CREAD - Enable receiver
// IGNPAR = Ignore characters with parity errors
// ICRNL - Map CR to NL on input
// PARENB - Parity enable
// PARODD - Odd parity (else even)
struct termios cfg;
//get existing configuration setup
tcgetattr(uart0_filestream, &cfg);
//fcntl(deviceFD, F_SETFL, FNDELAY);
fcntl(uart0_filestream, F_SETFL, 0);
////set both incoming and outgoing baud rates...
cfsetispeed(&cfg, B115200);
cfsetospeed(&cfg, B115200);
cfg.c_cflag |= (CLOCAL | CREAD);
////8N1 (8 data bits, No parity, 1 stop bit)
cfg.c_cflag &= ~PARENB;
cfg.c_cflag &= ~CSTOPB;
cfg.c_cflag &= ~CSIZE;
cfg.c_cflag |= CS8;
cfg.c_cflag &= ~CRTSCTS; //~CNEW_RTSCTS; //disable hardware flow control
//use RAW unbuffered data mode (eg, not canonical mode)
cfg.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG | IGNBRK);
cfg.c_iflag &= ~(IGNPAR | IXON | IXOFF | IXANY);
//raw (unprocessed) output mode
cfg.c_oflag &= ~OPOST;
tcsetattr(uart0_filestream, TCSANOW, &cfg);
//Transmitting Bytes
//----- TX BYTES -----
unsigned char tx_buffer[20];
unsigned char *p_tx_buffer;
p_tx_buffer = &tx_buffer[0];
*p_tx_buffer++ = 'H';
*p_tx_buffer++ = 'e';
*p_tx_buffer++ = 'l';
*p_tx_buffer++ = 'l';
*p_tx_buffer++ = 'o';
if (uart0_filestream != -1)
{
int count = write(uart0_filestream, &tx_buffer[0], (p_tx_buffer - &tx_buffer[0])); //Filestream, bytes to write, number of bytes to write
if (count < 0)
{
printf("UART TX error\n");
}
}
//Receiving Bytes
//----- CHECK FOR ANY RX BYTES -----
while(1) {
printf("loop\n");
if (uart0_filestream != -1)
{
// Read up to 255 characters from the port if they are there
unsigned char rx_buffer[256];
int rx_length = read(uart0_filestream, (void*)rx_buffer, 255); //Filestream, buffer to store in, number of bytes to read (max)
if (rx_length < 0)
{
//An error occured
printf("UART RX error\n");
}
else if (rx_length == 0)
{
//No data waiting
printf("no data UART RX test commit\n");
}
else
{
//Bytes received
rx_buffer[rx_length] = '\0';
printf("%i bytes read : %s\n", rx_length, rx_buffer);
//break;
}
}
sleep(1);
}
//Closing the UART if no longer needed
//----- CLOSE THE UART -----
close(uart0_filestream);
return 0;
}
I used to have the same problem, and problem is not related with code and solution is just disable login on serial port,
there is a file at /etc/inittab
open this file with nano and find this line:
T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100
and put a # char at begining this line than save and reboot and it is working weirdly.
You can use O_NONBLOCK flag to make the read/write operation non blocking.
Related
Backstory: I recently got a Raspberry Pi 4 Model B and a Protoneer RPI CNC Hat, which it controls via the serial port (/dev/ttyAMA0). After I put it all together and it didn't work at all (either in Minicom or bCNC), I've been gradually trying to zero in on the source of the problem. My oscilloscope shows that I can control the relevant pins when using them as GPIOs, so I do not suspect a fundamental hardware problem. However, I am completely unable to provoke a response from the pins when using them as a serial port. I have written the below C program to characterize the issue as exactly as possible.
Problem: I have a serial port, /dev/ttyAMA0, and it doesn't work.
$ sudo cat /proc/tty/driver/ttyAMA
serinfo:1.0 driver revision:
0: uart:PL011 rev2 mmio:0xFE201000 irq:34 tx:59596 rx:3105 RTS|CTS|DTR
$ ls -l /dev/ttyAMA0
crw-rw---- 1 root dialout 204, 64 Jul 11 08:24 /dev/ttyAMA0
$ groups
pi adm dialout cdrom sudo audio video plugdev games users input netdev gpio i2c spi
$ dmesg | grep tty
[ 0.000258] console [tty0] enabled
[ 0.420424] fe201000.serial: ttyAMA0 at MMIO 0xfe201000 (irq = 34, base_baud = 0) is a PL011 rev2
[ 0.425685] fe215040.serial: ttyS0 at MMIO 0x0 (irq = 36, base_baud = 62500000) is a 16550
[ 1.857049] systemd[1]: Created slice system-getty.slice.
$ echo hello | cat - > /dev/ttyAMA0
cat: write error: No space left on device
I can successfully open() it, but when I use select() to wait for it to become writeable, it times out. When I attempt to write to it anyway, write() successfully writes 0 bytes.
/* Shamelessly stolen from Stack Overflow, and then modified (in the finest tradition).
* https://stackoverflow.com/questions/6947413/how-to-open-read-and-write-from-serial-port-in-c */
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
int set_interface_attribs(int fd, int speed)
{
struct termios tty;
if (tcgetattr(fd, &tty) < 0) {
printf("Error from tcgetattr: %s\n", strerror(errno));
return -1;
}
cfsetospeed(&tty, (speed_t)speed);
cfsetispeed(&tty, (speed_t)speed);
tty.c_cflag |= (CLOCAL | CREAD); /* ignore modem controls */
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8; /* 8-bit characters */
tty.c_cflag &= ~PARENB; /* no parity bit */
tty.c_cflag &= ~CSTOPB; /* only need 1 stop bit */
tty.c_cflag &= ~CRTSCTS; /* no hardware flowcontrol */
/* setup for non-canonical mode */
tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
tty.c_oflag &= ~OPOST;
/* fetch bytes as they become available */
tty.c_cc[VMIN] = 1;
tty.c_cc[VTIME] = 1;
if (tcsetattr(fd, TCSANOW, &tty) != 0) {
printf("Error from tcsetattr: %s\n", strerror(errno));
return -1;
}
return 0;
}
int main()
{
char *portname = "/dev/ttyAMA0";
int fd;
int wlen;
fd = open(portname, O_RDWR | O_NOCTTY | O_SYNC);
if (fd == -1) {
perror("open: error");
return -1;
}
/* baudrate 115200, 8 bits, no parity, 1 stop bit */
set_interface_attribs(fd, B115200);
/* select() on the serial port file descriptor to wait for it to be writeable.
* It never does become writeable. Removing this section does not change
* the behavior of the following call to write() */
fd_set wfds;
struct timeval tv;
int select_retval;
FD_ZERO(&wfds);
FD_SET(fd, &wfds);
tv.tv_sec = 5;
tv.tv_usec = 0;
select_retval = select(fd + 1, NULL, &wfds, NULL, &tv);
if (select_retval == -1)
{
perror("select: error");
return -1;
}
else if (select_retval)
{
printf("select: fd can be written now\n");
}
else
{
/* This is what happens */
printf("select: fd did not become writeable within 5 seconds\n");
}
/* Write some output. This returns 0 bytes written and no errors. */
wlen = write(fd, "Hello!\n", 7);
if (wlen == -1)
{
perror("write: error");
return -1;
}
printf("write: wrote %d bytes\n", wlen);
tcdrain(fd);
}
Output:
$ gcc -Wall -Werror -std=gnu17 -o serial-test serial-test.c
$ ./serial-test
select: fd did not become writeable within 5 seconds
write: wrote 0 bytes
I am not a serial port wizard. I'd be happy to perform any experiment you suggest. Please help me.
refering to How do I make serial work on the Raspberry Pi3 (or later model)
:
The miniUART is now available on /dev/ttyS0
so you have to write on /dev/ttyS0 rather than /dev/ttyAMA0
I am working on project which requires to send command in hex with device setting as follows :
Baud rate : 9600, Parity : None, Stop bits : 2 , data bits : 8 (9600, 8N2).
I have verified by sending data to device with minicom. I am able to see data on CRO. But when I am sending data via C code and unable to see data on CRO and getting program output as FFFFF always for read function.
Source code for serial read and write :
int32_t Read()
{
printf("Entering Read function \n");
int fd;
fd = open("/dev/ttyS1", O_RDWR | O_NOCTTY | O_NDELAY);
int j=0;
if (fd == -1)
{
perror("open_port: Unable to open /dev/ttyS1\n");
exit(1);
}
else
{
printf("Port /dev/ttyS1 opened successfully\n");
}
//---------- Setting the Attributes of the serial port using termios structure ---------
struct termios SerialPortSettings; // Create the structure
tcgetattr(fd, &SerialPortSettings); // Get the current attributes of the Serial port
cfsetispeed(&SerialPortSettings,B9600); // Set Read Speed as 9600
cfsetospeed(&SerialPortSettings,B9600); // Set Write Speed as 9600
SerialPortSettings.c_cflag &= ~PARENB; // Disables the Parity Enable bit(PARENB),So No Parity
SerialPortSettings.c_cflag &= ~PARODD; // added
SerialPortSettings.c_cflag |= CS8; // Set the data bits = 8
SerialPortSettings.c_cflag &= CSTOPB; // CSTOPB = 2 Stop bits
SerialPortSettings.c_cflag &= ~CSIZE; // Clears the mask for setting the data size
SerialPortSettings.c_cflag &= ~CRTSCTS; // No Hardware flow Control
SerialPortSettings.c_cflag |= (CREAD | CLOCAL); // Enable receiver,Ignore Modem Control lines
SerialPortSettings.c_lflag =0; /* RAW input */ // added
SerialPortSettings.c_iflag &= ~(IXON | IXOFF | IXANY); // Disable XON/XOFF flow control both i/p and o/p
SerialPortSettings.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG); // Non Cannonical mode
SerialPortSettings.c_cc[VMIN] = 0; // added for testing // added 1 sec
SerialPortSettings.c_cc[VTIME] = 5; // added for testing // added
SerialPortSettings.c_iflag = 0; /* SW flow control off, no parity checks etc */ // added
SerialPortSettings.c_oflag &= ~OPOST;// No Output Processing
if((tcsetattr(fd,TCSANOW,&SerialPortSettings)) != 0) // Set the attributes to the termios structure
printf("\n ERROR ! in Setting attributes");
else
printf("\n BaudRate = 9600 \n StopBits = 2 \n Parity = None\n");
//------------------------------- Write data to serial port -----------------------------
unsigned char write_buffer[] = {0x28,0x11,0xDF,0xBC}; // Buffer containing characters to write into port
int bytes_written = 0; // Value for storing the number of bytes written to the port
for(j=0;j<4;j++)
{
bytes_written = write(fd,write_buffer[j],sizeof(write_buffer));// use write() to send data to port
// "fd" - file descriptor pointing to the opened serial port
// "write_buffer" - address of the buffer containing data
// "sizeof(write_buffer)" - No of bytes to write
//
printf("Byte written : %x\n",write_buffer[j]);
printf("\n %d Bytes written to ttyS1", bytes_written);
printf("\n +----------------------------------+\n\n");
}
sleep(2);
//------------------------------- Read data from serial port -----------------------------
tcflush(fd, TCIFLUSH); // Discards old data in the rx buffer
unsigned char read_buffer[40]; // Buffer to store the data received
int bytes_read = 0; // Number of bytes read by the read() system call
int i = 0;
bytes_read = read(fd,&read_buffer,40); // Read the data
printf("\n\n Bytes Rxed -%x", bytes_read); // Print the number of bytes read
printf("\n\n ");
for(i=0;i<bytes_read;i++) //printing only the received characters
printf("%x",(int)(*(unsigned char*)(&read_buffer[i])));
printf("\n +----------------------------------+\n\n\n");
close(fd); // Close the serial port
printf("Exiting Read function \n");
}
Output :
Entering Read function
Port /dev/ttyS1 opened successfully
BaudRate = 9600
StopBits = 2
Parity = None
Byte written : 28
-1 Bytes written to ttyS1
+----------------------------------+
Byte written : 11
-1 Bytes written to ttyS1
+----------------------------------+
Byte written : df
-1 Bytes written to ttyS1
+----------------------------------+
Byte written : bc
-1 Bytes written to ttyS1
+----------------------------------+
Bytes Rxed -ffffffff
+----------------------------------+
Exiting Read function
1st of all add error checking to this call:
tcgetattr(fd, &SerialPortSettings);
like
if (0 > tcgetattr(fd, &SerialPortSettings))
{
/* log and handle error */
}
Then here
SerialPortSettings.c_cflag |= CS8;
you set the data bits.
Two lines below you clear it
SerialPortSettings.c_cflag &= ~CSIZE;
Do this the other way round.
Also this
SerialPortSettings.c_cflag &= CSTOPB;
unsets.
If you want to use 2 stop bits set it by doing
SerialPortSettings.c_cflag |= CSTOPB;
Instead of just doing
SerialPortSettings.c_oflag &= ~OPOST;
do
SerialPortSettings.c_oflag = 0;
The code calls write() wrongly. This
for(j=0;j<4;j++)
{
bytes_written = write(fd,write_buffer[j],sizeof(write_buffer));
ought to be
for(j=0;j<4;j++)
{
bytes_written = write(fd, &write_buffer[j], 1)
Or just drop the loop and do
bytes_written = write(fd, write_buffer, sizeof write_buffer);
The call to read() is wrong as well.
It should be
bytes_read = read(fd, read_buffer, ...
For some of those mistakes with write and read the compiler should have warned you about.
Please also note that read() and write() return ssize_t not int.
Last not least I doubt flushing the input buffer (tcflush(fd, TCIFLUSH);) before reading it makes sense.
I need to make a chat using serial ports. I emulate pty by socat:
socat -d -d PTY PTY
Next I wrote small demo. That's how I initialize termios structure:
int tty_fd = open(argv[1], O_RDWR | O_NONBLOCK);
struct termios tio;
bzero(&tio, sizeof(tio));
// Frame bus runs at 38,400 BAUD
const int BAUD_Rate = B38400;
cfsetispeed(&tio, BAUD_Rate);
cfsetospeed(&tio, BAUD_Rate);
// Initialize to raw mode. PARMRK and PARENB will be over-ridden before calling tcsetattr()
cfmakeraw(&tio);
// Ignore modem lines and enable receiver and set bit per byte
tio.c_cflag |= CLOCAL | CREAD | CS8;
// NOTE: The following block overrides PARMRK and PARENB bits cleared by cfmakeraw.
tio.c_cflag |= PARENB; // Enable even parity generation
tio.c_iflag |= INPCK; // Enable parity checking
tio.c_iflag |= PARMRK; // Enable in-band marking
tio.c_iflag &= ~IGNPAR; // Make sure input parity errors are not ignored
if (is_odd)
tio.c_cflag |= PARODD;
tcsetattr(tty_fd, TCSANOW, &tio);
Next my whole demo listing:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <string.h>
struct termios init(int);
int main(int argc,char** argv)
{
struct termios tio;
char c = 0;
int tty_fd = open(argv[1], O_RDWR | O_NONBLOCK);
tio = init(strcmp(argv[3], "odd"));
if (tcsetattr(tty_fd, TCSANOW, &tio) == -1)
{
printf("Failed to setup the port");
return -1;
}
if (strcmp(argv[2], "write") == 0)
{
while (c != 'q')
{
scanf("%c", &c);
write(tty_fd, &c, 1);
}
}
if (strcmp(argv[2], "read") == 0)
{
while (c != 'q')
{
if (read(tty_fd, &c, 1) > 0)
printf("%c", c);
}
}
close(tty_fd);
}
struct termios init(int is_odd)
{
struct termios tio;
bzero(&tio, sizeof(tio));
// Frame bus runs at 38,400 BAUD
const int BAUD_Rate = B38400;
cfsetispeed(&tio, BAUD_Rate);
cfsetospeed(&tio, BAUD_Rate);
// Initialize to raw mode. PARMRK and PARENB will be over-ridden before calling tcsetattr()
cfmakeraw(&tio);
// Ignore modem lines and enable receiver and set bit per byte
tio.c_cflag |= CLOCAL | CREAD | CS8;
// NOTE: The following block overrides PARMRK and PARENB bits cleared by cfmakeraw.
tio.c_cflag |= PARENB; // Enable even parity generation
tio.c_iflag |= INPCK; // Enable parity checking
tio.c_iflag |= PARMRK; // Enable in-band marking
tio.c_iflag &= ~IGNPAR; // Make sure input parity errors are not ignored
if (is_odd == 0)
tio.c_cflag |= PARODD;
return tio;
}
When I starte one application as reader, and other as writer with similar parity, all goes OK. But when I try to test parity bit setting, I start them with different partity, all goes OK too. All messages sends without any error.
Is that because of pseudo terminal use, instead of real COM-port?
Or maybe the way I create a pty?
Also my partner try to do the similar test using python, and has similar result too. I use Linux Mint 17.3.
Thanks for your replays.
I have read pty's man page and found that termios'es c_cflag flags dont supported by pseudo terminal at all.
Dear Colleagues.
I'm trying write C program for Linux to write serial port (Arduino) and wait for answer. I know, there was many Q about it on forum, but all I tried have the same problem - successfully write - but not read answer. For example, here and here.
I have found two separate files for write and for read.
I'm compile and run read file in one terminal window, and write file in other. Works great. But I can't merge them in one file to write and then wait for answer. The same problem - write, but not read.
Here is like I tried:
#include <stdio.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <errno.h>
void main(void)
{
int fd;
fd = open("/dev/ttyS0",O_RDWR | O_NOCTTY | O_SYNC);
if(fd == -1)
printf("\n Error! in Opening ttyUSB0 ");
else
printf("\n ttyS0 Opened Successfully ");
struct termios SerialPortSettings;
tcgetattr(fd, &SerialPortSettings);
cfsetispeed(&SerialPortSettings,B9600);
cfsetospeed(&SerialPortSettings,B9600);
/* 8N1 Mode */
SerialPortSettings.c_cflag &= ~PARENB;
SerialPortSettings.c_cflag &= ~CSTOPB;
SerialPortSettings.c_cflag &= ~CSIZE;
SerialPortSettings.c_cflag |= CS8;
SerialPortSettings.c_cflag &= ~CRTSCTS;
SerialPortSettings.c_cflag |= CREAD | CLOCAL;
SerialPortSettings.c_iflag &= ~(IXON | IXOFF | IXANY);
SerialPortSettings.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG);
SerialPortSettings.c_oflag &= ~OPOST;/*No Output Processing*/
/* Setting Time outs */
SerialPortSettings.c_cc[VMIN] = 10; /* Read at least 10 characters */
SerialPortSettings.c_cc[VTIME] = 0; /* Wait indefinetly */
if((tcsetattr(fd,TCSANOW,&SerialPortSettings)) != 0)
printf("\n ERROR ! in Setting attributes");
else
printf("\n BaudRate = 9600 \n StopBits = 1 \n Parity = none");
char write_buffer[] = "Hello/n";
int bytes_written = 0;
printf("\n %s written to ttyUSB0",write_buffer);
printf("\n %d Bytes written to ttyUSB0", bytes_written);
printf("\n +----------------------------------+\n\n");
//tcflush(fd, TCIFLUSH); /* Discards old data in the rx buffer */
char read_buffer[32];
int bytes_read = 0;
int i = 0;
write(fd,write_buffer,sizeof(write_buffer));/* use write() to send data to port */
usleep ((8 + 25) * 100); /* Delay */
read(fd,&read_buffer,32); /* Read the data */
printf("\n\n Bytes Rxed -%d", bytes_read); /* Print the number of bytes read */
printf("\n\n ");
for(i=0;i<bytes_read;i++) /*printing only the received characters*/
printf("%c",read_buffer[i]);
printf("\n +----------------------------------+\n\n\n");
close(fd); /* Close the serial port */
}
Thanks for your help, Have a nice day.
You have a variable called bytes_read that is initialized to 0. Nothing in the code changes that value.
– user3386109
The statement read(fd,&read_buffer,32) should be corrected to bytes_read = read(fd, read_buffer, 32) …
– sawdust
In my program I read from the serial device (Linux, 8N1) without any problem. But in the case I want to write out a single byte, I get nothing out on the interface. I assume that my serial output settings are wrong. But there aren't that many ways how to set c_oflag...
My code:
#define TTYDEVICE "/dev/ttyS0"
#define BAUDRATE B9600
int openSerialDevice(const char* devTTY, struct termios oldTio) {
//----< Open serial device >----------------------------------
int fileDescriptor;
// fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
fileDescriptor = open(devTTY, O_RDWR | O_NOCTTY);
//fileDescriptor = open(devTTY, O_RDWR | O_NOCTTY /*| OPOST*/);
if (fileDescriptor == -1) {
perror("Error while opening serial interface occurred!");
return -99;
}
// set new parameters to the serial device
struct termios newtio;
bzero(&newtio, sizeof(newtio));
newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
// set to 8N1
newtio.c_cflag &= ~PARENB;
newtio.c_cflag &= ~CSTOPB;
newtio.c_cflag &= ~CSIZE;
newtio.c_cflag |= CS8;
newtio.c_iflag = IGNPAR;
// output mode to
//newtio.c_oflag = 0;
newtio.c_oflag |= OPOST;
/* set input mode (non-canonical, no echo,...) */
newtio.c_lflag = 0;
newtio.c_cc[VTIME] = 10; /* inter-character timer 1 sec */
newtio.c_cc[VMIN] = 0; /* blocking read disabled */
tcflush(fileDescriptor, TCIFLUSH);
if (tcsetattr(fileDescriptor, TCSANOW, &newtio)) {
perror("could not set the serial settings!");
return -99;
}
//----< / Open serial device >----------------------------------
return fileDescriptor;
}
int ACK[1] = { 6 };
int main() {
// old termios to restablish
struct termios oldTIO;
// filedescriptor
int fd;
fd = openSerialDevice(TTYDEVICE, oldTIO);
if ((fd == -1) | (fd == -99)) {
perror("Could not open TTY-Device. Exit on failure!");
return EXIT_FAILURE;
}
write(fd, ACK, 1); // Problem !!
return 0:
}
Now, if I use
screen /dev/ttyS1 9600 8n1
to verify what's coming out on /dev/ttyS0. I can't see anything. Same if I sniff with Docklight 1.8.
Any suggestions? thanks
How do you verify nothing is coming out ?
You can try to drop the RTSCTS, and try again. Infact, if you want minimal interference from the tty layer, you should set your terminal to raw, using this :
cfmakeraw(&newtio);
You're giving write() the data argument of ACK, which is a pointer to int. This is probably not what you mean. Depending on the endianness of the computer you're on, this means write() will "see" a buffer containing the chars { 6, 0, 0, 0 } (little-endian) or { 0, 0, 0, 6 } (big-endian). This assumes that sizeof (int) == 4 is true, adjust for other sizes as needed, the problem remains.
You should very probably make the buffer unsigned char instead. Also, if you had made the call like this:
int wrote = write(fd, ACK, sizeof ACK);
printf("Wrote %d bytes\n", wrote);
You would have gotten direct feedback. You should test something like this, to see that the write actually succeeds.
The activated Hardware-Flow-Control (CRTSCTS) was the reason why write() blocked and finally nothing has appeared on the serial output.
thanks!
Code snap which works:
int openSerialDevice(const char* devTTY, struct termios oldTio) {
//----< Open serial device >----------------------------------
int fileDescriptor;
// fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
fileDescriptor = open(devTTY, O_RDWR | O_NOCTTY);
//fileDescriptor = open(devTTY, O_RDWR | O_NOCTTY /*| OPOST*/);
if (fileDescriptor == -1) {
perror("Error while opening serial interface occurred!");
return -99;
}
// set new parameters to the serial device
struct termios newtio;
fcntl(fileDescriptor, F_SETFL, 0);
// set everything to 0
bzero(&newtio, sizeof(newtio));
// again set everything to 0
bzero(&newtio, sizeof(newtio));
newtio.c_cflag |= BAUDRATE; // Set Baudrate first time
newtio.c_cflag |= CLOCAL; // Local line - do not change "owner" of port
newtio.c_cflag |= CREAD; // Enable receiver
newtio.c_cflag &= ~ECHO; // Disable echoing of input characters
newtio.c_cflag &= ~ECHOE;
// set to 8N1
newtio.c_cflag &= ~PARENB; // no parentybyte
newtio.c_cflag &= ~CSTOPB; // 1 stop bit
newtio.c_cflag &= ~CSIZE; // Mask the character size bits
newtio.c_cflag |= CS8; // 8 data bits
// output mode to
newtio.c_oflag = 0;
//newtio.c_oflag |= OPOST;
// Set teh baudrate for sure
cfsetispeed(&newtio, BAUDRATE);
cfsetospeed(&newtio, BAUDRATE);
newtio.c_cc[VTIME] = 10; /* inter-character timer */
newtio.c_cc[VMIN] = 0; /* blocking read until */
tcflush(fileDescriptor, TCIFLUSH); // flush pending data
// set the new defined settings
if (tcsetattr(fileDescriptor, TCSANOW, &newtio)) {
perror("could not set the serial settings!");
return -99;
}
//----< / Open serial device >----------------------------------
return fileDescriptor;
}