将模块配置为 115kbps,然后系统将端口重置为 9600 波特

标签 c linux serial-port reset baud-rate

我正在开发一个在 Linux 环境中对 HM-TRP radio 模块进行编程的 C 程序,因为稍后我将对其中的大约 40 个进行编程,我不想每次都输入单独的编程代码是时候对每一个进行编程了。

在我的机器上,我设置了三个终端窗口。一个是编译程序并运行它。一种用于向串口发送数据(用于测试),一种用于接收 radio 模块的响应。

这是我逐步解决问题的过程。

  1. 运行程序。并收到预期的消息:

    HM-TRP模块配置

    第一次设置 HM-TRP... 使用 115kbps 配置完成

  2. 切换到新窗口(我将其称为#2)并执行“stty -aF/dev/ttyS0”以查看已设置的设置。结果(显示)向我表明我的 C 程序运行正常:

     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. 为 115k 速度启动带有参数“/dev/ttyS0 115200”的“屏幕”程序。

  4. 打开一个新窗口(我将其称为#3)并向模块执行如下有效命令:

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

这里的问题是“屏幕”在应该打印“OK”时没有报告任何内容。那么我继续...

  1. 我重新访问窗口 #2 以终止屏幕程序,然后我再次使用“/dev/ttyS0 9600”以 9600 波特率重新启动屏幕,只是为了看看发生了什么。我再次重复第 4 步,这次出现“确定”。

但奇怪的是,当我让屏幕程序以 9600 波特率运行并执行我的 C 程序时,屏幕报告“OK”和(如我所料)一行垃圾提示我最后的命令序列到 radio 模块:

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

实际上确实显示了波特率的变化,只是从垃圾结果来看。

那么问题来了,为什么速率会自行重置为 9600bps?即使我在新窗口中验证了正确的速率,波特率值是否虚拟化或在应用程序之间隔离?还是我还缺少其他东西?

我的意思是,如果我只是在 unix 命令行上用 echo 语句吐出每个长代码,那么我设置模块没有问题,但我想在 C 中创建程序。

这是代码,对于参数,我使用 /dev/ttyS0 0,其中/dev/ttyS0 是我的串行端口 (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;
  }

我做错了什么?

最佳答案

在一些发现之后,事实证明我需要在发送命令后添加延迟,因为 radio 模块只是半双工的,因此它实际上忽略了我的一半命令,导致无法识别速度指令。每次 outs 函数调用后的 usleep(100000) 对我来说是个窍门。

关于将模块配置为 115kbps,然后系统将端口重置为 9600 波特,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47240487/

相关文章:

c - 每次阅读我都必须重新打开/dev/urandom 吗?

linux - ARM 嵌入式 Linux 工具链

php - 大量用户的 Cron 作业管理

linux - 有没有办法改变vim的默认模式

c - C 中 Raspberry PI 串行通信中的奇偶校验设置问题

serial-port - 防止在串行监视器连接上重置?

c - 练习指点,请问如何去掉这个警告?

c - C 中整数数组中字符串的 ASCII 值的存储

c - 程序以代码 0320 退出?

c# - 在连接打开时更改串行端口波特率