1

I'm working on a C program that programs an HM-TRP radio module in a Linux environment, because later I'll be programming about 40 of them and I don't want to type in the individual programming codes all the time to program each one.

On my machine I have three terminal windows setup. One is for compiling the program and running it. One is for sending data to the serial port (for testing) and one is for receiving responses from the radio module.

This is step-by-step how I reached the issue.

  1. Ran program. and received expected message:

    HM-TRP module config

    Setting up HM-TRP for first time... Using 115kbps Config Done

  2. Switched to new window (I'll call it #2) and executed "stty -aF /dev/ttyS0" to see settings were setup. Results (shown) suggests to me my C program functioned ok:

     speed 115200 baud; rows 0; columns 0; line = 0;
     intr = ^C; quit = ^\; erase = ^?; kill = ^H; eof = ^D; eol = <undef>; eol2 = <undef>;
     swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V;
     flush = ^O; min = 1; time = 0;
     parenb -parodd cs8 -hupcl -cstopb cread clocal -crtscts
     ignbrk -brkint ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany
     -imaxbel -iutf8
     -opost -olcuc -ocrnl -onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
     -isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase 
    -tostop -echoprt -echoctl
     -echoke
    
  3. Started the "screen" program with parameters "/dev/ttyS0 115200" for 115k speed.

  4. Opened a new window (I'll call it #3) and executed a valid command to the module as follows:

    echo -en "\xAA\xFA\x96\x07" > /dev/ttyS0
    

The problem here is that "screen" is reporting nothing when it should be printing "OK". So then I continue...

  1. I revisit window #2 to terminate the screen program then I restart screen again with "/dev/ttyS0 9600" for 9600 baud speed just to see what's going on. I repeat step 4 again and this time "OK" appeared.

But what's weird is that when i left the screen program running with 9600 baud and I executed my C program, the screen reported "OK" and (as I was expecting) a line of garbage which suggests to me that the final command sequence to the radio module of:

  \xAA\xFA\x1E\x00\x01\xC2\x00

actually did show change of baud rate, just from looking at a garbage result.

So the question then is, why is it that the rate just resets itself to 9600bps? Are baud rate values virtualized or something and isolated between applications even though I verified the correct rate in a new window? or is there something else I'm missing?

I mean I have no problem setting up the module if I just spit out each long code with echo statements on the unix command line but I want to create the program in C.

This is the code, and for the parameters, I use /dev/ttyS0 0 where /dev/ttyS0 is my serial port (COM1).

      #include <sys/stat.h>
  #include <sys/types.h>
  #include <sys/io.h>
  #include <unistd.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  #include <termios.h>
  #include <fcntl.h>

  void outs(int fd, char* n,unsigned int sz){
    char *d=n;
    unsigned int nwrt=0,x=0;
    for (x=0;x<sz;x++){ //send byte one by one
      while ((nwrt=write(fd,d,1))==0){
    usleep(10000); //waste CPU cycles passively until byte is sent
      };
      d++;
    }
  }

  int openser(speed_t speed,const char* dev){
    struct termios options;
    //open serial port
    int fd = open(dev, O_RDWR | O_NOCTTY | O_SYNC);if (fd < 0){printf("ERROR\n");return -1;}
    memset(&options,0,sizeof options);
    tcflush(fd,TCIOFLUSH);
    tcgetattr(fd,&options);
    //set baud rate
    cfsetispeed(&options, speed);
    cfsetospeed(&options, speed);
    options.c_iflag = IGNBRK | IGNPAR; //raw input
    options.c_cflag |= (TOSTOP|NOFLSH|CLOCAL|CREAD|CS8);//ignore modem + parity: 8N1 + no rtscts
    options.c_lflag=0; //raw input
    options.c_oflag=0;options.c_cc[VMIN]=1;options.c_cc[VTIME]=0; //raw output
    tcsetattr(fd, TCSANOW, &options);
    return fd;
  }

  int main(int argc,char* argv[]){
    printf("HM-TRP module config\n\n");
    int rd=0;
    setbuf(stdout,NULL);
    if (argc < 2){printf("serial device + function required as argument.\n");return -1;}
    //open serial port for 115kbps baud
    rd=openser(115200L,argv[1]);if (rd == 0){return -1;}
    // get function
    int funcn=strtol(argv[2],NULL,10);
    switch (funcn){
    case 0: //function 0. 1st time setup. set things up at 9600 baud then switch to 115kbps
    printf("Setting up HM-TRP for first time...\n");
    close(rd);rd=openser(9600L,argv[1]);if (rd == 0){return -1;}
    case 1:
    //set baud + wireless speed to 115kbps
    printf("Using 115kbps\n");
    outs(rd,"\xAA\xFA\xC3\x00\x01\xC2\x00",7);
    outs(rd,"\xAA\xFA\x1E\x00\x01\xC2\x00",7);
    break;
    default:
    //reset option in case something went wrong
    printf("Resetting HM-TRP to defaults - 9600bps\n");
    outs(rd,"\xAA\xFA\xF0",3);
    break;
    }
    close(rd);
    printf("Config Done\n");
    return 0;
  }

What am I doing wrong?

Mike -- No longer here
  • 2,064
  • 1
  • 15
  • 37

1 Answers1

1

After some discoveries, it turned out I needed to add a delay after sending a command since the radio module is only half-duplex and therefore it was literally ignoring half my commands which caused the speed instruction to not be recognized. A usleep(100000) after each outs function call did the trick for me.

Mike -- No longer here
  • 2,064
  • 1
  • 15
  • 37