cserial-portuartunistd.h

UART Communication In C language (Hex)


I want to send a hexadecimal value to the write function. (e.g., 0×90). This is because the device that needs to communicate receives commands in hexadecimal numbers. The unused variables appeared as they were tested and annotated to lose the hexadecimal value, and will be erased later. How can I write a write function with a hexadecimal value other than String?

For beginners, please tell us how to exchange hexadecimal values through read and write functions.

#include <termios.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <time.h>
#include <pthread.h>

int main(void)
{
    int fd;
    fd=open("/dev/ttyHSL6", O_RDWR|O_NOCTTY );
    struct termios newtio;

    char buffer[2000];
    int bytes_read=0;
    char *data;
    //int *a=0x90;

    char *a="0X90";
    const int *num1;
    
    if (fd == -1)
    {
        printf("Error! in opening port");
        exit(-100);
    }

    memset(&newtio, 0, sizeof(struct termios));
    newtio.c_cflag = B9600 | CS8 | CLOCAL | CREAD;

    newtio.c_iflag = IGNPAR;

    newtio.c_oflag = 0;
    newtio.c_lflag = 0;
    newtio.c_cc[VTIME] = 0; 
    newtio.c_cc[VMIN] = 1; 
    tcflush(fd, TCIFLUSH);

    tcsetattr(fd, TCSANOW, &newtio);
    data=malloc(sizeof(char)*140);
    while(1){
        const char *str ="0x91";
        
        //write(fd, str, strlen(str)+1);

        bytes_read = read(fd,buffer,sizeof(buffer));

        if (bytes_read > 0)
        {
            buffer[bytes_read]=0;
            printf("%s", buffer);
        }
        usleep(100000);

        
    }
    close(fd);
    return 0;
}

Current Progress:

I set up transmission and reception variables and compiled the code using unsigned char, but such an error occurs.

./serial.c:48:10: warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 2 has type ‘unsigned char *’ [-Wformat=]
   printf("%x\n",str);

If I use %p, there is no compilation error, but as you know, the address value is printed, so it is different from the result I want. I don't know how to do it because I'm a beginner.

The revised parts are as follows.

    while(1){
        //const char *str ="0x91";
        unsigned char str[13] = {0xA5,0x80,0x90,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBD};
        write(fd, str, strlen(str));
        printf("%x\n",str);
        bytes_read = read(fd,buffer,sizeof(buffer));

    //  printf("%x\n",*str);
        if (bytes_read > 0)
        {
            buffer[bytes_read]=0;
            

            printf("%p\n", buffer);
        }
        usleep(100000);

        //printf("%s\r\n",buffer);      

    }
    close(fd);
    return 0;

Solution

  • You're just wanting to send binary rather than text data, however, binary data can't be handled in the same way as a text string as 0 (0x00) is a legitimate binary value whereas it acts as a string terminator in C. This is why protocols for binary data normally have a length indicator in one byte, if messages can be of variable length, or specific message delimiters (unique values at the start and end of the message that can't be repeated in the message data).

    Pointers regarding your code: Always initialize values where possible, especially arrays into which you're going to store strings e.g. char buffer[2000] = {0} if the compiler allows otherwise memset(buffer, 0, sizeof(buffer); before using it.

        unsigned char str[13] = {0xA5,0x80,0x90,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBD};
    

    There is an implicit cast here from a signed int to an unsigned char for the values that you are initializing your array with e.g. 0x90 is an int by default.

        write(fd, str, strlen(str));
    

    As pointed out 0x00 (null) is a legitimate binary value, but happens to be a text string terminator in C, therefore strlen(str) will return 4 as it will take 0xA5, 0x80, 0x90, 0x08, 0x00 as your string, with 4 data bytes and one terminator. For arrays storing strings you must allow for an extra byte into which the null terminator is placed.

    Instead you should use something like:

    write(fd, str, sizeof(str)/sizeof(str[0]));
    

    This calculates the number of elements in the array. As sizeof will return the number of bytes (octets) of memory taken up by the item being sized we also need to divide that by the size of an array element to determine the number of elements.

    A char will return a size of 1, an int can return a size of 2 when compiled on a 16 bit processor, 4 if 32 bit etc.

    Finally, you will need to cast your value that is being printed, so try using: (edit: code correction made)

    unsigned char str[13] = {0xA5,0x80,0x90,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBD};
    
    for (int i=0; i< sizeof(str)/sizeof(str[0]); i++) 
    { 
        printf("%X",(int)str[i]); 
    } 
    printf("\n"); 
    

    will give

    A58090800000000BD