简体   繁体   中英

Serial interface via UDP sockets in C

I am new to serial interfacing and my company has asked me to design an API that configures a gyroscope -connected to a WIFI chip- using a C code, by sending the hex commands over a UDP socket to the WIFI chip. I made sure to adhere to the format provided by the manufacturer's manual but it seems that i am missing something when it comes to the serial interfacing aspect. I am using this code to do so:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include "port.h"
#include <time.h>

void waitFor (unsigned int );

unsigned char head1 = 0xff; //head
unsigned char head2 = 0xaa;  //head2
unsigned char saveadd = 0x00; //saveconfig address
unsigned char savevalue = 0x00; //save config  0x01 is factory reset
unsigned char endd = 0x00; //end

int
main(int argc, char **argv)
{
    struct sockaddr_in myaddr;  /* our address */
    struct sockaddr_in remaddr; /* remote address */
    remaddr.sin_addr.s_addr = inet_addr("192.168.1.1");
    remaddr.sin_port = htons(8889);
    socklen_t addrlen = sizeof(remaddr);        /* length of addresses */
    int recvlen;            /* # bytes received */
    int fd;             /* our socket */
    int msgcnt = 0;         /* count # of messages we received */
    remaddr.sin_family = AF_INET;

    /* create a UDP socket */

    if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        perror("cannot create socket\n");
        return 0;
    }

    /* bind the socket to any valid IP address and a specific port */

    memset((char *)&myaddr, 0, sizeof(myaddr));
    myaddr.sin_family = AF_INET;
    myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    myaddr.sin_port = htons(SERVICE_PORT);

    if (bind(fd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) {
        perror("bind failed");
        return 0;
    }



        printf("waiting on port %d\n", SERVICE_PORT);


        // Hex command that turns a builtin LED on
        unsigned char comPart1 =    0xFF;
        unsigned char comPart2 =    0xAA;
        unsigned char comPart3 =    0x1b;
        unsigned char comPart4 =    0x00;
        unsigned char comPart5 =    0x00;

        unsigned char commands [5]; /* unsigned char array to hold command */
        commands [0] = comPart1;
        commands [1] = comPart2;
        commands [2] = comPart3;
        commands [3] = comPart4;
        commands [4] = comPart5;




        unsigned char temp_buf [2]; /*buffer used to send hex command*/
        temp_buf [0]= (unsigned char) 0x00;
        temp_buf [1]= '\0';



        for (int i = 0; i < 5 ; i++) 
        {
           temp_buf [0] = commands[i];

        if (sendto(fd, temp_buf, sizeof (temp_buf), 0, (struct sockaddr *)&remaddr, addrlen) < 0)
            perror("sendto");
       }

        waitFor (0.5); /*delay specified by user manual*/



        printf ("%s \n", "Now saving the configration");
        //save commands as specified by user manual 
        unsigned char saveConfig [5];

        saveConfig [0] = head1;
        saveConfig [1] = head2;
        saveConfig [2] = saveadd;
        saveConfig [3] = savevalue;
        saveConfig [4] = endd;

        for (int i = 0; i < 5 ; i++)
        {

        temp_buf [0] = saveConfig [i];

        if (sendto(fd, temp_buf, sizeof (temp_buf), 0, (struct sockaddr *)&remaddr, addrlen) < 0)
            perror("sendto");
            waitFor (0.05);
       }
       waitFor (0.45);



}

void waitFor (unsigned int secs) {
    unsigned int retTime = time(0) + secs;   // Get finishing time.
    while (time(0) < retTime);               // Loop until it arrives.
}

I was able to configure the gyroscope serially (if disconnected from the WIFI chip and connected to a USB-TTL) using CuteCom . So i know that the hardware works. What am I missing when it comes to serial interfaces. How would one go about achieving such a task?

you said/asked in the comments

I am essentially trying to send the following: 0xff 0xaa 0x1b 0x00 0x00 one byte at a time. Do you think the NULL (byte of zeros) are causing the issue? How would I indicate the end of the buffer if I am not to use it?

From your code, however, you are sending a NULL byte in-between each of these data bytes. temp_buf contains 2 bytes, you are hard-coding the second byte to \\0 and setting the first byte to the data byte. Then the sendto(fd, temp_buf, sizeof (temp_buf), 0, (struct sockaddr *)&remaddr, addrlen line sends the contents of this buffer. If you trapped your network traffic in wireshark, you would see that you are sending 0xff 0x00 0xaa 0x00 0x1b 0x00 0x00 0x00 0x00 0x00 rather than what you intended to send.

To answer your questions, c strings aside, there is nothing universal about a NULL byte terminator for a buffer. Valid data bytes can be 0x00 all the time. If I email someone a black picture, I'll be sending a whole stream of 0x00 bytes. Your gyroscope must have some kind of protocol that should be described in its documentation. In my experience, this has been a fixed message length, a start/end sequence of "magic" bytes, or even an application-defined header. In your comments, you indicate the gyroscope simply wants one byte at a time, so there you go, just send it one byte at a time! I imagine you changed your code to something like the following:

// really no need for temp_buf
for (int i = 0; i < 5 ; i++)
{
  if (sendto(fd, &saveConfig[i] /* or saveConfig+i */, sizeof(char), 0, (struct sockaddr *)&remaddr, addrlen) < 0)
  {
    perror("sendto");
    // I'm guessing from your indentation you want this wait inside the if-statement. Note that in the code you posted, the if-statement doesn't have any brackets so this will execute each time through the loop whether there is an error or not
    waitFor (0.05);
  }
  waitFor (0.45);
}

In general, any time you're dealing with network problems like this, I would strongly recommend using wireshark (or equivalent) to see exactly what you are sending,, it is extremely helpful!

saveConfig is binary data but you need to send the hex representation so:

temp_buf [0] = saveConfig [i]

will not work.

What you need is something like:

unsigned int
gethex(unsigned int val,int shf)
{

    val >>= shf;
    val &= 0x0F;
    val = "0123456789ABCDEF"[val];

    return val;
}

temp_buf[0] = gethex(saveConfig[i],4);
temp_buf[1] = gethex(saveConfig[i],0);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM