0

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;
youna
  • 39
  • 6
  • 2
    "*How can I write a write function with a hexadecimal value other than String*". Hexadecimal is not a data format. That is just a data representation. If you mean send binary data instead of text data then something like: `int val = 0x91; write(fd, &val, sizeof(val));`. But really it's not that clear what you are asking. – kaylum Sep 24 '21 at 05:48
  • If you mention hexadecimal numbers, are you talking about strings? Do you want to send the **string** `"x90"` to the device or do you want to send the **value** `0x90` which is identical to `0220` or `144` to the device? "Hexadecimal" does not have any meaning if you just talking about the value. – Gerhardh Sep 24 '21 at 06:55
  • Your termios initialization is unreliable. See [Setting Terminal Modes Properly](https://www.gnu.org/software/libc/manual/html_node/Setting-Modes.html) and for sample code: https://stackoverflow.com/questions/12437593/how-to-read-a-binary-data-over-serial-terminal-in-c-program – sawdust Sep 28 '21 at 20:45
  • If you want to display an array of bytes as hexadecimal values, then you would have to individually convert each byte. There is no single **printf()** specifier to do that for you. See https://stackoverflow.com/questions/6947413/how-to-open-read-and-write-from-serial-port-in-c/38318768#38318768 – sawdust Sep 29 '21 at 05:25

2 Answers2

1

If you want to send the 0x90 value like it's int value 144 you should use the

unsigned char hex = 0x90

with this you can send value 144

  • I tried to compile the source code after modifying it with reference to the relevant information, but an error occurred. Please refer to the above answer. I'm a beginner, so I'm sorry I'm clumsy. – youna Sep 29 '21 at 01:01
1

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
ChrisBD
  • 9,104
  • 3
  • 22
  • 35
  • Thank you for your kind answer. I modified the code as in the answer, but the print at write is only printed in space and the read function result returns only a5... Can I ask you to check what's wrong? I'm sorry I'm a beginner. – youna Sep 30 '21 at 03:08
  • while(1){ memset(buffer, 0, sizeof(buffer)); write(fd, str, sizeof(str)/sizeof(str[0])); for (int i=0; i< sizeof(str)/str[0]; i++) { printf("%x",(int)str[i]); } printf("\n"); bytes_read = read(fd,buffer,sizeof(buffer)); if (bytes_read > 0) { buffer[bytes_read]=0; for (int j=0; j< sizeof(buffer)/buffer[0]; j++) { printf("%x",(int)buffer[j]); } printf("\n"); } usleep(100000); } – youna Sep 30 '21 at 03:09
  • Hi - I see that `for (int i=0; i< sizeof(str)/str[0]; i++)` should be `for (int i=0; i< sizeof(str)/sizeof(str[0]); i++)` and `for (int j=0; j< sizeof(buffer)/buffer[0]; j++)` should be `for (int j=0; j< sizeof(buffer)/sizeof(buffer[0]); j++)` – ChrisBD Sep 30 '21 at 07:18
  • I see that I made an error in my last bit of code, although it was correct earlier - I've now corrected it. – ChrisBD Sep 30 '21 at 07:22