【问题标题】:Beaglebone Black unable to read from UART RX pin in C++Beaglebone Black 无法从 C++ 中的 UART RX 引脚读取
【发布时间】:2022-01-20 21:51:51
【问题描述】:

我目前正在尝试将串行数据从 ESP8266 NodeMCU 模块读取到 Beaglebone Black。本质上,我触发 NodeMCU 通过 UART 从 BBB 发送字符串并将字符串打印到 BBB 终端。以下是BBB上的代码:

#include<iostream>
#include<fstream>
#include<string>
#include<unistd.h>
#include<termios.h>
#include<stdio.h>
#include<fcntl.h>
using namespace std;

int main(){
   std::fstream fs;

   // Setup UART
   int file, count;
   if ((file = open("/dev/ttyO4", O_RDWR | O_NOCTTY | O_NDELAY))<0){
      perror("UART: Failed to open the file.\n");
      return -1;
   }
   struct termios options; // the termios structure is vital
   tcgetattr(file, &options); // sets the parameters associated with file
   // Set up the communications options:
   // 115200 baud, 8-bit, enable receiver, no modem control lines
   options.c_cflag = B115200 | CS8 | CREAD | CLOCAL;
   options.c_iflag = IGNPAR | ICRNL; // ignore partity errors, CR -> newline
   tcflush(file, TCIFLUSH); // discard file information not transmitted
   tcsetattr(file, TCSANOW, &options); // changes occur immmediately

   fs.open("/sys/class/gpio/export");
   fs << "48";
   fs.close();
   fs.open("/sys/class/gpio/gpio48/direction");
   fs << "out";
   fs.close();
   fs.open("/sys/class/gpio/gpio48/value");
   fs << "1"; // "0" for off
   fs.close();
   usleep(1000000);
   fs.open("/sys/class/gpio/gpio48/value");
   fs << "0";
   fs.close();

   unsigned char receive[1000]; // declare a buffer for receiving data
   int characters = read(file, (void*)receive, 1000);
   if (characters == -1){ // receive the data
      perror("Failed to read from the input\n");
      return -1;
   }
   if (characters==0) printf("There was no data available to read!\n");
   else {
      receive[characters] = 0;
      printf("%s\n",receive);
   }
   close(file);

   return 0;
}

NodeMCU上的代码如下:

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200, SERIAL_8N1);
  Serial.println();

  
  // Set D2 as input
  pinMode(4, INPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  if(digitalRead(4)==1){
    String msg = "Hola!";
    while(digitalRead(4)==1){
      
    }
    Serial.print(msg);
  }
}

当我运行 C 脚本时,我收到以下错误:

Failed to read from the input
: Resource temporarily unavailable

但是,我可以在 ttyO4 上的 BBB 上打开 Minicom 终端和“Hola!”字符串按预期打印一次。

我该如何克服这个错误?

【问题讨论】:

  • 您的 termios 初始化质量低且不完整。现在,您的琐碎任务可能就足够了。请参阅Setting Terminal Modes Properly BTW 您的程序没有从 "UART RX pin' 读取。您的 Linux 用户程序从硬件中移除了几层,并且 "reading" 意味着获取来自串行终端缓冲区的字节。
  • @sawdust 对,这对我的问题的描述很糟糕。我的终端每次执行只需要读取一次缓冲区,所以这可能就足够了,但我的问题源于不知道如何正确设置终端属性。我无法打开您发送的链接,您还有其他资源可以浏览吗?
  • “所以这可能就足够了” -- 意思是“我很懒,所以我打算使用一个有缺陷的程序。”看看当您尝试阅读更长的消息时会发生什么。 gnu.org 站点已备份,链接良好。

标签: c++ uart beagleboneblack nodemcu


【解决方案1】:

已修复:

我在打开 ttyO4 端口的 if 语句下插入了这一行:

fcntl(file, F_SETFL, 0);

我还将Serial.print(msg); 行放在了while 循环上方的NodeMCU 代码中。

【讨论】:

  • 您可能认为您“修复了它”,但您了解“修复”吗?
  • @sawdust 在一定程度上。我不完全理解“open()”和“fcntl()”调用中使用的参数,但我发现使用“O_NDELAY”会导致终端立即读取缓冲区,但是没有该行 BBB 不会初始化端口而不改变串行线路上的电压。答案中的那一行消除了“O_NDELAY”的影响。
  • 如果您几乎不了解函数及其参数的作用以及使用它们的原因,那几乎是货物崇拜编程。在这种情况下,区别在于非阻塞 I/O 与阻塞 I/O。见stackoverflow.com/questions/25996171/…
猜你喜欢
  • 2016-06-23
  • 2021-10-27
  • 2015-10-28
  • 1970-01-01
  • 2020-10-20
  • 1970-01-01
  • 2019-10-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多