Reading from serial port in C - serial-port

I'm trying to read from Arduino (who's sending char '4' constantly) with XBee.
I have tried writing from the PC to Arduino, and it works, so the connection is correct.
When I execute de following code, the terminal doesn't show anything and don't finish the program, so it gets stuck on reading.
#include <stdio.h> // Standard input / output functions
#include <stdlib.h>
#include <string.h> // String function definitions
#include <unistd.h> // UNIX standard function definitions
#include <fcntl.h> // File control definitions
#include <errno.h> // Error number definitions
#include <termios.h> // POSIX terminal control definitions
#define XBEE "/dev/ttyUSB0"
#define BAUDRATE B9600
int main(int argc,char** argv)
{
struct termios tio;
struct termios stdio;
struct termios old_stdio;
int tty_fd = open(XBEE , O_RDWR| O_NOCTTY);
cfsetospeed(&tio,BAUDRATE);
cfsetispeed(&tio,BAUDRATE); // Baudrate is declared above
tcsetattr(tty_fd,TCSANOW,&tio);
// for(i;i<5;i++){
// write(tty_fd,&c,1); //If new data is available on the console, send it to the serial port
// write(tty_fd,&o,1); //If new data is available on the console, send it to the serial port
// }
int n=0;
char buf = '\0';
/* Whole response*/
do
{
n = read( tty_fd, &buf, sizeof(char) );
}
while( n > 0);
if (n < 0)
{
printf("ERROR READING");
}
else if (n == 0)
{
printf("Read nothing!");
}
else
{
printf("Response: %c",buf);
}
close(tty_fd);
tcsetattr(STDOUT_FILENO,TCSANOW,&old_stdio);
return EXIT_SUCCESS;
}
How do I solve this?
UPDATE
I tried this other code and receive a warning: turning off output flushing and then the terminal froze.
#include <stdio.h> // Standard input / output functions
#include <stdlib.h>
#include <string.h> // String function definitions
#include <unistd.h> // UNIX standard function definitions
#include <fcntl.h> // File control definitions
#include <errno.h> // Error number definitions
#include <termios.h> // POSIX terminal control definitions
#define XBEE "/dev/ttyUSB0"
#define BAUDRATE B9600
int main(int argc,char** argv)
{
struct termios tio;
struct termios stdio;
struct termios old_stdio;
struct termios options;
int tty_fd = open(XBEE , O_RDWR | O_NOCTTY | O_NDELAY);
cfsetospeed(&tio,BAUDRATE);
cfsetispeed(&tio,BAUDRATE); // Baudrate is declared above
tcsetattr(tty_fd,TCSANOW,&tio);
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
// for(i;i<5;i++){
// write(tty_fd,&c,1);//if new data is available on the console, send it to serial port
// write(tty_fd,&o,1);//if new data is available on the console, send it to serial port
// }
int n=0;
char buf = '1';
int i = 1;
/* Whole response*/
while(i==1){
n = read( tty_fd, &buf, sizeof(char) );
if (n < 0)
{
printf("ERROR READING");
}
else if (n == 0)
{
printf("Read nothing!");
}
else
{
printf("Response: %c",buf);
close(tty_fd);
break;
}
}
tcsetattr(STDOUT_FILENO,TCSANOW,&old_stdio);
return EXIT_SUCCESS;
}

If you're going to be using C to communicate with XBee modules, you might want to check out this Open Source XBee Host library. You could just use the serial driver from it in your code, or take a look at the xbee_term sample program as a simple terminal.

If you are printing data, why are you using printf? You must use the Serial.print() syntax w.r.t the Arduino IDE.

Related

How to send unprocessed output over linux serial port?

I did everything. I shutoff the bits to disable the output processing in the termios structure, properly set the baud rate and character size and disabled parity, flush the output and input buffers before sending. Even after all this linux serial still doesn't work the way I want it to. Canonical mode is not even on in the first place, everything is raw bytes. Btw I am using arch linux connected to an arduino nano with an usb cable which will receive the bytes from PC and display them on a lcd. When I send a byte from PC, e.g char 'A', it apears to get corrupted during the transmisson process, and arduino displays the corrupted byte. Everytime I send character 'A' it shows ascii value 254 on the lcd which is clearly wrong. How do I solve this problem?
My C code on pc:
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <unistd.h>
int main(int argc, char **argv)
{
int serial_port = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);
getchar();
struct termios old_tty;
struct termios new_tty;
if (tcgetattr(serial_port, &new_tty) != 0) {
printf("Error %i from tcgetattr: %s\n", errno, strerror(errno));
return 1;
}
old_tty = new_tty;
new_tty.c_cflag &= ~(CSTOPB | CSIZE | PARENB);
new_tty.c_cflag |= CS8;
new_tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
new_tty.c_oflag &= ~OPOST;
new_tty.c_iflag &= ~(IXON | IXOFF | IXANY | INPCK | ISTRIP);
//new_tty.c_cc[VMIN] = 0;
//new_tty.c_cc[VTIME] = 0;
cfsetispeed(&new_tty, B9600);
cfsetospeed(&new_tty, B9600);
if (tcsetattr(serial_port, TCSANOW, &new_tty) != 0) {
printf("Error %i from tcsetattr: %s\n", errno, strerror(errno));
return 1;
}
tcflush(serial_port, TCIOFLUSH);
unsigned char val = 'A';
write(serial_port, &val, sizeof(val));
getchar();
tcsetattr(serial_port, TCSANOW | TCSADRAIN, &old_tty);
close(serial_port);
return 0;
}
Code on Arduino:
void setup() {
lcd.begin(16, 2); // begins connection to the LCD module
lcd.backlight(); // turns on the backlight
lcd.clear();
lcd.setCursor(0, 0);
Serial.begin(9600);
lcd.print("Init done");
}
void loop() {
if (Serial.available() > 0) {
uint8_t x = Serial.read();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("I received: ");
lcd.setCursor(0, 1);
lcd.print(x);
}
}

Raspberry Pi UART program in C using termios receives garbage (Rx and Tx are connected directly)

I have a simple program written in C which uses termios to send a basic string to the Raspberry Pi UART and attempts to read and output the response. The Rx and Tx pins on the Raspberry Pi are connected with a jumper so whatever is sent should be immediately received.
Despite the program outputting that it successfully sent and received 5 characters for the chosen string ('Hello'), trying to print the contents of the buffer just produces one or two garbage characters.
The program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
int main(int argc, char* argv[]) {
struct termios serial;
char* str = "Hello";
char buffer[10];
if (argc == 1) {
printf("Usage: %s [device]\n\n", argv[0]);
return -1;
}
printf("Opening %s\n", argv[1]);
int fd = open(argv[1], O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1) {
perror(argv[1]);
return -1;
}
if (tcgetattr(fd, &serial) < 0) {
perror("Getting configuration");
return -1;
}
// Set up Serial Configuration
serial.c_iflag = 0;
serial.c_oflag = 0;
serial.c_lflag = 0;
serial.c_cflag = 0;
serial.c_cc[VMIN] = 0;
serial.c_cc[VTIME] = 0;
serial.c_cflag = B115200 | CS8 | CREAD;
tcsetattr(fd, TCSANOW, &serial); // Apply configuration
// Attempt to send and receive
printf("Sending: %s\n", str);
int wcount = write(fd, &str, strlen(str));
if (wcount < 0) {
perror("Write");
return -1;
}
else {
printf("Sent %d characters\n", wcount);
}
int rcount = read(fd, &buffer, sizeof(buffer));
if (rcount < 0) {
perror("Read");
return -1;
}
else {
printf("Received %d characters\n", rcount);
}
buffer[rcount] = '\0';
printf("Received: %s\n", buffer);
close(fd);
}
Outputs:
Opening /dev/ttyAMA0
Sending: Hello
Sent 5 characters
Received 5 characters
Received: [garbage]
I can't see any major problem with the code myself, but I might be wrong. I can successfully send and receive characters using PuTTY connected with the same settings, so it can't really be a hardware problem. Although I haven't tried it in PuTTY, trying to connect with anything less than 115200 baud with this program will result in nothing being received.
Where am I going wrong?
int wcount = write(fd, &str, strlen(str));
int rcount = read(fd, &buffer, sizeof(buffer));
In these lines, buffer/str are already pointers. You are passing a pointer to a pointer.
The lines should be:
int wcount = write(fd, str, strlen(str));
int rcount = read(fd, buffer, sizeof(buffer));

NETworking with UDP

what happens when a UDP packet is sent to a host using sendto().
all the bits i am sending are sent(known from the return value).immediately i use a recvfrom() which does not output anything but program do not exit(i.e no return value).
I think that the program must exit if no reply is recieved.
what will the replies for a UDP packet from a port.
is this packet blocked by firewall?? if yes then why is the return value of sendto is non-negative.
recvfrom() will block until a message is received unless you set the socket to non-blocking.
The interfaces you want to look for are
ioctl() with FIONBIO or O_NONBLOCK (depending your platform),
select() to wait for data to arrive, or timeout after a while
Also remember that the address and port number for sendto() usually be network-byte order, so look into ntohl and ntohs.
you must have some error in your client or server. try localhost first, so you avoid firewall problems
this is an example of nonblocking udp client/server I was using for my tests, it uses ioctl() to check if there is data to read on the socket, however if you want to do some serious application using epoll would be more efficient also you can specify timeout to wait in microseconds:
[null#localhost tests]$ cat udpserv.c
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <string.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <errno.h>
#define BUFLEN 512
#define NPACK 15
#define PORT 9930
void diep(char *s)
{
printf("erno=%d errstr=%s\n",errno,strerror(errno));
perror(s);
exit(1);
}
int main(void)
{
struct sockaddr_in si_me, si_other;
int s,ret,nbytes, i, slen=sizeof(si_other);
char buf[BUFLEN];
if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
diep("socket");
memset((char *) &si_me, 0, sizeof(si_me));
si_me.sin_family = AF_INET;
si_me.sin_port = htons(PORT);
si_me.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(s, (struct sockaddr*) &si_me, sizeof(si_me))==-1)
diep("bind");
fcntl(s, F_SETFL, fcntl(s, F_GETFL, 0) | O_NONBLOCK);
sleep(10);
for (i=0; i<NPACK; i++) {
ret=ioctl(s,FIONREAD,&nbytes);
if (ret==-1) {
printf("error on FIONREAD\n");
} else {
printf("nbytes=%d\n",nbytes);
}
if (recvfrom(s, buf, BUFLEN, 0, (struct sockaddr*) &si_other, &slen)==-1)
diep("recvfrom()");
printf("Received first half of packet from %s:%d\nData: %s\n\n",
inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port), buf);
}
close(s);
return 0;
}
[null#localhost tests]$ cat udpclient.c
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#define SRV_IP "127.0.0.1"
#define BUFLEN 200
#define NPACK 10
#define PORT 9930
/* diep(), #includes and #defines like in the server */
void diep(char *s)
{
perror(s);
exit(1);
}
int main(void)
{
struct sockaddr_in si_other;
int s, i, slen=sizeof(si_other);
char buf[BUFLEN];
if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
diep("socket");
memset((char *) &si_other, 0, sizeof(si_other));
si_other.sin_family = AF_INET;
si_other.sin_port = htons(PORT);
if (inet_aton(SRV_IP, &si_other.sin_addr)==0) {
fprintf(stderr, "inet_aton() failed\n");
exit(1);
}
for (i=0; i<NPACK; i++) {
printf("Sending packet %d\n", i);
sprintf(buf, "This is packet %d\n", i);
if (sendto(s, buf, BUFLEN, 0, (struct sockaddr*) &si_other, slen)==-1)
diep("sendto()");
}
close(s);
return 0;
}
the sendto() is non negative because it returns number of bytes sent. check the man page for sendto

UDP Server not receiving in Unix (Cygwin)

So I've looked around and noticed some others having a similar problem to mine. However I have yet to find a solution. I've created a client and server in Unix (Cygwin) using UDP. When I try to use sendto() in order to send a message to the server from the client, the server doesn't seem to be receiving the the packet. I've done error checking and it seems like the client isn't having a problem sending the packet, yet still the server cannot receive it correctly. The server just seems to be dead for the most part. I'm using my machine to host the client and the server and I'm attempting to connect to the server on my home address (127.0.0.1) and a random port. Any suggestions at this point would be much appreciated.
Server Code:
#include <stdio.h> /* standard C i/o facilities */
#include <stdlib.h> /* needed for atoi() / atof() */
#include <unistd.h> /* Unix System Calls */
#include <sys/types.h> /* system data type definitions */
#include <sys/socket.h> /* socket specific definitions */
#include <netinet/in.h> /* INET constants and stuff */
#include <arpa/inet.h> /* IP address conversion stuff */
#include <string.h> /* String manipulation */
#include <time.h> /* Used to to measure process execution time */
/* Server main routine - this is an iterative server
1. create a socket
2. bind the socket and print out the port number assigned
3. do forever
get next connection
handle the connection
enddo
*/
int main(int argc, char **argv)
{
int sockfd;
struct sockaddr_in servaddr, cliaddr;
int n;
//Create UDP socket
if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("Problem creating socket\n");
exit(1);
}
//Setup the UDP server
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(0);
//Bind the UDP to the socket
if (bind(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr))<0)
{
perror("Error bind\n");
exit(1);
}
//Print the port for the UDP server
int length = sizeof( servaddr );
if (getsockname(sockfd, (struct sockaddr *) &servaddr, &length) < 0)
{
perror("Error getsockname\n");
exit(1);
}
printf("The Server passive socket port number is %d\n",ntohs(servaddr.sin_port));
//Send/Recv from client
char msg[100];
for(;;)
{
socklen_t len = sizeof(cliaddr);
if( recvfrom(sockfd, msg, 100, 0, (struct sockaddr*) &cliaddr, &len) < 0)
{
perror("Error on recv\n");
exit(1);
}
printf("Msg: %s\n", msg);
//read(sockfd, msg, 10);
//sendto(sockfd, msg, n, 0, (struct sockaddr*) &cliaddr, len);
}
close(sockfd);
return 0;
}
Client Code:
#include <stdio.h> /* standard C i/o facilities */
#include <stdlib.h> /* needed for atoi() */
#include <unistd.h> /* Unix System Calls */
#include <sys/types.h> /* system data type definitions */
#include <sys/socket.h> /* socket specific definitions */
#include <netinet/in.h> /* INET constants and stuff */
#include <arpa/inet.h> /* IP address conversion stuff */
#include <string.h>
/* client program:
The following must passed in on the command line:
name of the server (argv[1])
port number of the server (argv[2])
*/
int main( int argc, char **argv )
{
int sockfd;
struct sockaddr_in servaddr;
int n;
//Ensure we have full args
if (argc != 3)
{
printf("Usage: client <server name> <server port>\n");
exit(1);
}
//Setup the port number
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(atoi(argv[2]));
//Setup the client IP
//inet_pton(AF_INET, argv[1], &servaddr.sin_addr)) <= 0
if( inet_aton(argv[1], &servaddr.sin_addr) == 0)
{
perror("Error with server IP\n");
exit(1);
}
//Create socket
if( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("Error on socket\n");
exit(1);
}
/*if (connect(sockfd,(struct sockaddr *) &servaddr, sizeof(servaddr)) < 0 )
{
printf("Problem connecting socket\n");
exit(1);
}*/
//Send msg
char msg[10] = "123456789";
for(;;)
{
socklen_t len = sizeof(servaddr);
if( (sendto(sockfd, msg, strlen(msg), 0, (struct sockaddr*) &servaddr, len)) < 0 )
{
perror("Error on sendto():\n");
exit(1);
}
//write(sockfd, msg, strlen(msg));
//n = recvfrom(sockfd, msg2, 10, 0, NULL, NULL);
//printf("Msg: %s\n", msg2);
}
close(sockfd);
return 0;
}
First, your sender just sends data as fast as it possibly can, whether or not anyone or anything is listening. That's not a good thing to do.
Second, your receiver passes msg through to a %s printf specifier. But %s is only for C-style strings, and msg is not a C-style string (nothing puts a zero byte on the end of it). You also throw the return value of recvfrom away, so you can't convert it into a string because you have no idea how many of its bytes are valid.
Third, your server is creating a SOCK_STREAM socket!

How can I send a datagram with an Ethernet trailer?

How can I send a datagram with an Ethernet trailer? If I use SocketType.Raw, I'll have to send the whole IP header and I have no idea how to do that.
Something like this perhaps?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#include <sys/ioctl.h>
int s;
unsigned char buffer[513];
struct sockaddr_ll socket_address;
int main ( void )
{
unsigned char seq;
unsigned int ra;
int length;
struct ifreq ifr;
s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (s == -1)
{
printf("error creating socket\n");
return(1);
}
memset(&ifr,0, sizeof(struct ifreq));
strncpy(ifr.ifr_name,"eth0",IFNAMSIZ);
if(ioctl(s, SIOCGIFINDEX, &ifr) < 0)
{
perror("ioctl SIOCGIFINDEX");
exit(1);
}
printf("index %d\n",ifr.ifr_ifindex);
printf("socket created\n");
memset(&socket_address,0,sizeof(socket_address));
socket_address.sll_family = PF_PACKET;
socket_address.sll_protocol = htons(ETH_P_ALL);
socket_address.sll_ifindex = ifr.ifr_ifindex;
if (bind(s, (struct sockaddr *)(&socket_address), sizeof(socket_address)) < 0)
{
perror("bind error");
exit(1);
}
printf("bound\n");
length=27;
memset(buffer,0,sizeof(buffer));
//destination
buffer[ 0]=0xFF;
buffer[ 1]=0xFF;
buffer[ 2]=0xFF;
buffer[ 3]=0xFF;
buffer[ 4]=0xFF;
buffer[ 5]=0xFF;
//source
buffer[ 6]=0x00;
buffer[ 7]=0x19;
buffer[ 8]=0xd1;
buffer[ 9]=0x02;
buffer[10]=0xdc;
buffer[11]=0xb3;
//length
buffer[12]=((length-14)>>8)&0xFF;
buffer[13]=((length-14)>>0)&0xFF;
//payload
buffer[14]=0x12;
buffer[15]=0x34;
for(ra=0;ra<20;ra++)
{
buffer[16]=ra;
if(send(s,buffer,length,0) < 0 )
{
printf("sendto failed\n");
break;
}
else
{
printf("sent\n");
}
}
close(s);
return(1);
}
That should give a raw packet that you can see on wireshark. if you want to have the ip eader, or make it a udp or something like that you can use this method and build the header yourself (it is trivial look at the rfcs or just use wireshark to look at a bunch of other packet headers). Note that for udp you do not have to compute a checksum 0x0000 is a valid checksum that is supposed to pass on through.
If all you want is a udp packet with zeros at the end that is somewhat the same, probably easier, let me know.
That trailer is used to pad ethernet frames to their minimum length (46 bytes of payload). So send a small UDP packet - smaller than 18 bytes (as IP + UDP is normally 28 bytes)

Resources