Thread: Ascii data to be modified to Hexadecimal data - "C" program to be modified

  1. #1
    Registered User
    Join Date
    May 2019
    Posts
    4

    Ascii data to be modified to Hexadecimal data - "C" program to be modified

    Hi,

    I try to run this little program in "C" (but I'm a beginner).
    This is a read project of a value that arrives on the RS232 port.
    This value is copied to a temporary file before it is erased after reading by the macro that uses it.

    It works with a string of numeric values, but not with a string of Hexadecimal characters.

    How to modify this program "C" so that it accepts to send as such the hexadecimal chain?

    Small example:

    If the test string received on the RS232 port is "FF",
    the characters received in the temporary file are a small square with O1 inside and Y surmounted by 2 points.

    I want to receive plain text without decoding "FF"

    Code:
    #include <stdio.h>
    #include <string.h>
    #include <fcntl.h>
    #include <errno.h>
    #include <termios.h>
    #include <unistd.h>
    #include <sys/ioctl.h>
    
    #define RX_MSG_MAX_LEN       512
    #define RX_DATA_FILE_MAX_LEN 512
    #define RX_LOCK_FILE_MAX_LEN 512
    
    static void CreateRxDataFile(char *FileName, char *Data);
    static int  LockFileExists(char *FileName);
    static void CreateLockFile(char *FileName);
    
    int main(int argc,char** argv)
    {
      struct termios tio;
      struct termios stdio;
      struct termios old_stdio;
      int tty_fd, Idx = 0, Ret, ExitVal = 1;
      char RxMsg[RX_MSG_MAX_LEN + 1];
      char RxDataFile[RX_DATA_FILE_MAX_LEN + 1];
      char RxLockFile[RX_DATA_FILE_MAX_LEN + 1];
      unsigned char c = 'D';
    
      if(argc < 5)
      {
        printf("Please start with %s /dev/ttyS1 19200 rxdata.txt lock.txt (for example)\n", argv[0]);
      }
      else
      {
        strncpy(RxDataFile, argv[3], RX_DATA_FILE_MAX_LEN);
        printf("RxDataFile=%s\n", RxDataFile);
        strncpy(RxLockFile, argv[4], RX_LOCK_FILE_MAX_LEN);
        printf("RxLockFile=%s\n", RxLockFile);
        tcgetattr(STDOUT_FILENO, &old_stdio);
        memset(&stdio, 0, sizeof(stdio));
        stdio.c_iflag = 0;
        stdio.c_oflag = 0;
        stdio.c_cflag = 0;
        stdio.c_lflag = 0;
        stdio.c_cc[VMIN] = 1;
        stdio.c_cc[VTIME] = 0;
        tcsetattr(STDOUT_FILENO, TCSANOW, &stdio);
        tcsetattr(STDOUT_FILENO, TCSAFLUSH, &stdio);
        fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);       /* make the reads non-blocking */
    
        memset(&tio, 0, sizeof(tio));
        tio.c_iflag = 0;
        tio.c_oflag = 0;
        tio.c_cflag = CS8 | CREAD | CLOCAL;           /* 8n1, see termios.h for more information */
        tio.c_lflag = 0;
        tio.c_cc[VMIN] = 1;
        tio.c_cc[VTIME] = 5;
    
        tty_fd=open(argv[1], O_RDWR | O_NONBLOCK);
        if(!strcmp(argv[2], "115200"))
        {
          cfsetospeed(&tio, B115200);            /* 115200 baud */
          cfsetispeed(&tio, B115200);            /* 115200 baud */
        }
        else if(!strcmp(argv[2], "57600"))
        {
          cfsetospeed(&tio, B57600);            /* 57600 baud */
          cfsetispeed(&tio, B57600);            /* 57600 baud */
        }
        else if(!strcmp(argv[2], "38400"))
        {
          cfsetospeed(&tio, B38400);            /* 38400 baud */
          cfsetispeed(&tio, B38400);            /* 38400 baud */
        }
        else if(!strcmp(argv[2], "19200"))
        {
          cfsetospeed(&tio, B19200);            /* 19200 baud */
          cfsetispeed(&tio, B19200);            /* 19200 baud */
        }
        else if(!strcmp(argv[2], "9600"))
        {
          cfsetospeed(&tio, B9600);            /* 9600 baud */
          cfsetispeed(&tio, B9600);            /* 9600 baud */
        }
        else if(!strcmp(argv[2], "4800"))
        {
          cfsetospeed(&tio, B4800);            /* 4800 baud */
          cfsetispeed(&tio, B4800);            /* 4800 baud */
        }
        else if(!strcmp(argv[2], "2400"))
        {
          cfsetospeed(&tio, B2400);            /* 2400 baud */
          cfsetispeed(&tio, B2400);            /* 2400 baud */
        }
        else if(!strcmp(argv[2], "1200"))
        {
          cfsetospeed(&tio, B1200);            /* 1200 baud */
          cfsetispeed(&tio, B1200);            /* 1200 baud */
        }
        else
        {
          /* default is 115200 */
          cfsetospeed(&tio, B115200);            /* 115200 baud */
          cfsetispeed(&tio, B115200);            /* 115200 baud */
        }
        tcsetattr(tty_fd, TCSANOW, &tio);
        while (c != 'q')
        {
      /*    if (read(tty_fd,&c,1)>0)        write(STDOUT_FILENO,&c,1);  if new data is available on the serial port, print it out */
          Ret = 0;
          if (read(tty_fd, &c, 1) > 0)
          {
        if( ((c == 10) && Idx) || ((c == 13) && Idx) || (Idx >= RX_MSG_MAX_LEN))
        {
          RxMsg[Idx] = 0;
          Idx = 0;
          Ret = 1;
        }
        else
        {
          if((c != 10) && (c != 13))
          {
            RxMsg[Idx] = c;
            Idx++;
          }
        }
          }
          if(Ret)
          {
        Ret = 0;
        printf("Rx: '%s'\n\r", RxMsg);
            while(LockFileExists(RxLockFile))
        {
          usleep(5);/* Wait until calc reads the data.txt file and removes the lock.txt file. */
    #if 1
          if(read(STDIN_FILENO, &c, 1) > 0) /* Allow to quit with q in the console */
          {
            if(c == '&') break;
          }
    #endif
        }
        CreateRxDataFile(RxDataFile, RxMsg);
            CreateLockFile(RxLockFile);
          }
          usleep(5);
          if (read(STDIN_FILENO, &c, 1) > 0) Ret = write(tty_fd,&c,1);        /* if new data is available on the console, send it to the serial port */
        }
        close(tty_fd);
        tcsetattr(STDOUT_FILENO, TCSANOW, &old_stdio);
        ExitVal = 0;
      }
      return ExitVal;/* EXIT_SUCCESS; */
    }
    
    static void CreateRxDataFile(char *FileName, char *Data)
    {
      FILE *f;
      
      f = fopen(FileName, "w");
      if (f == NULL)
      {
          printf("Error opening file!\n");
          return;
      }
      /* print some text */
      fprintf(f, "%s\n", Data);
      /* Do not forget to close the file */
      fclose(f);
    }
    
    static void CreateLockFile(char *FileName)
    {
      FILE *f;
      
      f = fopen(FileName, "w");
      if (f == NULL)
      {
          printf("Error opening lock file!\n");
          return;
      }
      /* print some text */
      fprintf(f, "%s\n", "DataAvailable");
      /* Do not forget to clode the file */
      fclose(f);
    }
    
    static int LockFileExists(char *FileName)
    {
      FILE *fp;
      int Exists = 1;
      
      fp = fopen(FileName, "r");
      if (fp == NULL) {
        Exists = 0;
      }
      else
      fclose(fp);
      
      return(Exists);
    }
    I specify that I am on Ubuntu and that the macro is realized in Basic LibreOffice or OpenOffice.


    Thank you for the one who would like to help me.

  2. #2
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,688
    So, you want a string with characters FF to be read as a hexadecimal number 0xFF (255), right?

    sscanf will do that

  3. #3
    Registered User
    Join Date
    May 2019
    Posts
    4
    Yes, correct, but I'm a newbies...
    Where place sscanf into the code ?

  4. #4
    Registered User
    Join Date
    Feb 2019
    Posts
    296
    One tip not related to your code: Opening a file will not make it 'locked'. Here's a simple test:
    Code:
    #include <stdlib.h>
    #include <stdio.h>
    #include <unistd.h>
    
    static void write1( FILE **f );
    static void write2( FILE **f );
    
    int main( void )
    {
      FILE *f;
    
      switch ( fork() )
      {
        case 0:
          write2(&f); break;
        case -1:
          fputs( "\033[31,1mERROR\033[m: cannot fork()!\n", stderr );
          return EXIT_FAILURE;
        default:
          write1(&f);
      }
    
      printf( "Waiting 3 seconds: PID=%d\n", getpid() );
      sleep(3); // waits 3 seconds!
    
      fclose(f);
    
      return EXIT_SUCCESS;
    }
    
    static void write1( FILE **f )
    {
      if ( ! ( *f = fopen( "test.txt", "a" ) ) )
      {
        fputs( "\033[33,1mWARNING\033[m: Cannot open file to append (primary process).\n", stderr );
        return;
      }
    
      fprintf( *f, "primary PID: %d\n", getpid() );
    }
    
    static void write2( FILE **f )
    {
      if ( ! ( *f = fopen( "test.txt", "a" ) ) )
      {
        fputs( "\033[33,1mWARNING\033[m: Cannot open file to append (secondary process).\n", stderr );
        return;
      }
    
      fprintf( *f, "secondary PID: %d\n", getpid() );
    }
    You'll notice that both processes will write to the file (and both processes will open the SAME file for appending).

  5. #5
    Registered User
    Join Date
    May 2019
    Posts
    4
    Thank you for your advice,

    but the code works well with numeric characters (I have no problem).
    I'm just trying to use it with a Hexadecimal entry.

  6. #6
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,688
    Code:
     
    if(sscanf(banana, "%x", &apple) == 1)
     ...

  7. #7
    Registered User
    Join Date
    May 2019
    Posts
    4
    Hi Click_here,

    for me, it's more like clicking there , I'm newbie and cannot understand what you answer.
    Can you explain me in more detail in the code?

  8. #8
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,688
    If you don't know anything about the sscanf function, then there is a lot to go through!

    Firstly, you can learn it as an extention the scanf function (one 's').

    "scanf" gets input from the user and parse it into various variables such as ints/floats/charactor arrays/... - It does that by getting information from something called stdin. This is usually formed by what the user types into their keyboard.

    Here is a basic "how to" - Scanf - The Basics of C Programming | HowStuffWorks - Open a new project and go through the example.

    There are a lot of different things that you can have your scanf look for, such as %d (signed int), %c (character), %f (float), and others... But the one that you're interested in is %x - It looks for a hex number. (There are other things that you can do, but I suggest that you look at them after you have got your example working).

    This is like a mini computer language and I suggest that you get familiar with it, because it is a favourite at job interviews. "printf" uses the same syntax.

    "sscanf" does the same thing: However, instead of looking at stdin, it will look at a string ('\0' terminated charater array) - The way that we tell the compiler what string we want it to look at is that we put it in as the first argument.

    And finally, the return value..
    ISO/IEC 9899:1999
    7.19.6.4
    3
    The scanf function returns the value of the macro EOF if an input failure occurs before any conversion. Otherwise, the scanf function returns the number of input items assigned, which can be fewer than provided for, or even zero, in the event of an early matching failure.
    ... that is why I checked to see if the return value was 1 - I wanted to see if one conversion successfully occurred.


    One example of using sscanf from my code recently was to check if an IP4 address was entered correctly...
    Code:
    if ( 4 == sscanf(ip4AddressInputBuffer, "%u.%u.%u.%u", 
            &ipNumber[3], &ipNumber[2], &ipNumber[1], &ipNumber[0]))
    {
      /* More code checking the range of inputs... */
    }
    ... notice that I put '.' in there


    Another thing that I will point out is that in this code we use yoda notation - It has a place with some compilers that won't warn you if you do this by accident...
    Code:
    if (apple = 4)   //apple isn't compared to 4, it is assigned the value 4
    
    
    // instead of...
    if (apple == 4)
    
    
    /*
        If there is a typo where the second
        '=' is missing it becomes an error
    */
    if (4 = apple) // Got-cha!

    More reading...
    https://linux.die.net/man/3/sscanf

    https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/sscanf-sscanf-l-swscanf-swscanf-l?view=vs-2019


    scanf format string - Wikipedia
    Last edited by Click_here; 1 Week Ago at 04:46 PM.
    Fact - Beethoven wrote his first symphony in C

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 15
    Last Post: 07-20-2018, 10:19 PM
  2. Replies: 1
    Last Post: 07-28-2016, 02:47 AM
  3. Replies: 7
    Last Post: 12-04-2014, 09:28 PM
  4. Replies: 4
    Last Post: 01-08-2013, 04:07 PM
  5. "Data Fork"/"Alternate Data Streams"
    By phantomotap in forum Tech Board
    Replies: 3
    Last Post: 08-06-2010, 11:01 AM

Tags for this Thread