【问题标题】:How to read temp from DS18B20 using UART board如何使用 UART 板从 DS​​18B20 读取温度
【发布时间】:2018-10-28 03:21:57
【问题描述】:

我买了这样的板 现在我想将温度传感器连接到这块板上。 如何从 C 或 C++ 中的传感器读取温度? 我试图写一些代码,但它不会工作。我将 DS18B20 数据线直接连接到 TXD 和 RXD 引脚。

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <cstring>
#include <inttypes.h>
#include <errno.h>

int
set_interface_attribs (int fd, int speed, int parity)
{
    struct termios tty;
    memset (&tty, 0, sizeof tty);
    if (tcgetattr (fd, &tty) != 0)
    {
            std::cout<<"error "<<errno<<" from tcgetattr";
            return -1;
    }

    cfsetospeed (&tty, speed);
    cfsetispeed (&tty, speed);

    tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;     // 8-bit chars
    // disable IGNBRK for mismatched speed tests; otherwise receive break
    // as \000 chars
    tty.c_iflag &= ~IGNBRK;         // ignore break signal
    tty.c_lflag = 0;                // no signaling chars, no echo,
                                    // no canonical processing
    tty.c_oflag = 0;                // no remapping, no delays
    tty.c_cc[VMIN]  = 0;            // read doesn't block
    tty.c_cc[VTIME] = 5;            // 0.5 seconds read timeout

    tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl

    tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
                                    // enable reading
    tty.c_cflag &= ~(PARENB | PARODD);      // shut off parity
    tty.c_cflag |= parity;
    tty.c_cflag &= ~CSTOPB;
    tty.c_cflag &= ~CRTSCTS;

    if (tcsetattr (fd, TCSANOW, &tty) != 0)
    {
        std::cout<<"error "<<errno<<" from tcsetattr";
            return -1;
    }
    return 0;
}

void
set_blocking (int fd, int should_block)
{
    struct termios tty;
    memset (&tty, 0, sizeof tty);
    if (tcgetattr (fd, &tty) != 0)
    {
        std::cout<<"error "<<errno<<" from tggetattr";
            return;
    }
    tty.c_cc[VMIN]  = should_block ? 1 : 0;
    tty.c_cc[VTIME] = 5;            // 0.5 seconds read timeout

    if (tcsetattr (fd, TCSANOW, &tty) != 0)
            std::cout<<"error "<<errno<<" setting term attributes";
}

int main()
{
        char *portname = "/dev/ttyUSB0";
        int tty_fd = open (portname, O_RDWR | O_NOCTTY | O_SYNC);
        if (tty_fd < 0)
        {
            std::cout<<"error "<<errno<<" opening "<<portname<<": "<< strerror (errno);
                return -1;
        }

        set_interface_attribs (tty_fd, B9600, 0);  // set speed to 115,200 bps, 8n1 (no parity)
        set_blocking (tty_fd, true);

        unsigned char c = 0xCC;
        if(!write(tty_fd, &c, sizeof(c)))
            std::cout<<"Write error";

        sleep(2);

        unsigned char buffer[8];
        int size;
        if((size = read(tty_fd, &buffer, 8)) < 0)
                std::cout<<"Error";
        else
            std::cout<<"CC("<<size<<")='"<<buffer<<"'";

        std::cout<<"\n";

        c = 0x44;
        if(!write(tty_fd, &c, sizeof(c)))
            std::cout<<"Write error2";

        c = 0xBE;
        if(!write(tty_fd, &c, sizeof(c)))
            std::cout<<"Write error2";

        sleep(2);

        if((size = read(tty_fd, &buffer, 8)) < 0)
                std::cout<<"Error";
        else
            std::cout<<"BE("<<size<<")='"<<buffer<<"'";

        std::cout<<"\n######################\n";

        close(tty_fd);
}

我明白了:

CC(1)='Č@'
BE(2)='@ž@'
######################
CC(1)='Č@'
BE(2)='@ž@'
######################
CC(1)='Č@'
BE(2)='@ž@'
######################

你能帮帮我吗?

【问题讨论】:

  • 两个可能的问题:你确定你得到的数据是文本吗?如果你这样做了,你确定数据是零终止的吗?
  • 您确定使用了正确的设备文件。如果我插入一个 Arduino UNO。我应该连接到/dev/ttyACM0
  • 我将 UART 连接到笔记本电脑。当我运行应用程序时,TXD 和 RXD LED 闪烁。
  • 您是否还有代码可以演示您如何通过设备编写代码?

标签: c++ c uart


【解决方案1】:

任何软件都无法做到这一点。 DS18B20 与您拥有的电路板在电气上不兼容。该传感器使用 1 线、集电极开路通信方案,该方案与该板通常使用的串行协议完全不同。您可能很难对 RTS/CTS 信号进行一些 bit-banging,但您需要将它们组合成双向集电极开路信号的电路。

【讨论】:

  • 似乎不太可能。使用Maxim 1-wire协议的是芯片本身。该板似乎将其分解为标准串行端口信号。 1-wire 协议没有空间用于 RTS 和 CTS :) 而且他实际上正在取回数据。
  • 那么用这块板子从DS18B20读取数据会非常困难吗?如何从笔记本电脑上的传感器读取温度?
  • @HansPassant 如果没有电路板的数据表,从外观和标签FT232 来看,它真的更像一个 FTDI USB 转串口板,它不支持 1-wire。跨度>
  • 那么如何将此传感器连接到笔记本电脑?
  • @HansPassant 电路板对连接上的某种电气活动做出响应这一事实并不意味着“他实际上正在获取数据”。 Maxim 1-wire 协议与普通的 UART 串​​行协议完全不同。它根本无法与“标准串行端口信号”一起使用。
【解决方案2】:

您可以破解 UART 以使用 1 线协议进行通信。 将 Rx 连接到 Tx 并添加 4.7 上拉电阻 请参阅 maxim 的应用说明:

http://www.maximintegrated.com/en/app-notes/index.mvp/id/214

【讨论】:

    【解决方案3】:

    正如用户 3804701 所指出的,使用 UART 接口与 1-Wire 设备进行通信确实是可能的,https://www.maximintegrated.com/en/app-notes/index.mvp/id/214 的应用说明包含使其工作所需的所有信息。 但是 OP 的代码需要几个修复:

    • 与 DS18B20 的每个事务都由 3 个步骤组成:初始化(也称为复位)、ROM 命令和功能命令,随后可选地进行数据交换
    • 初始化或复位步骤是通过将 UART 配置为 9600 bps 波特率、发送 0x0F 并接收一个虚拟字节来执行的;然后,必须将波特率设置为 115200 bps 才能执行后续步骤
    • 在复位步骤之后,数据被发送到 DS18B20,方法是将每个数据位设置为 1 的 0xFF 字节和设置为 0 的每个位的 0x00 字节写入 UART,从最低有效位开始;例如,要发送 0xAB(即 10101011),可以将序列写入 UART(FF FF 00 FF 00 FF 00 FF);对于写入 UART 的每个字节,都有一个需要从 UART 读取并丢弃的“返回字节”
    • 通过按照上一个要点中的规则发送 0xFF 字节从 DS18B20 接收数据,但不是丢弃从 UART 读取的“返回字节”,每个数据位从最低有效位开始读取一个字节: 0xFF值表示位值为1,否则位值为0;例如,从UART读取的序列(00 FF FF 00 FF 00 00 FF)表示DS18B20发送了0x96(即10010110)
    • 如果只有一个 DS18B20 连接到 1-Wire 总线,所有事务都可以使用“skip ROM”(字节值 0xCC)作为 ROM 命令
    • 要执行的第一个事务是从 DS18B20 触发温度转换的事务,功能命令为 0x44
    • 等待转换完成后(最多可能需要 750 毫秒),主机可以执行第二次事务以读取 DS18B20 暂存器存储器(功能命令 0xBE);暂存器存储器长 9 个字节,其中包含温度值

    所以总的来说,从 DS18B20 获取温度样本所需的步骤是:复位、写入 0xCC、写入 0x44、等待转换、复位、写入 0xCC、写入 0xBE、读取 9 个字节。

    https://github.com/dword1511/onewire-over-uart 上提供了实现这些东西的示例代码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-15
      • 2018-10-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多