无法从ds18b20读取温度

时间:2019-09-14 14:15:26

标签: stm32

我正在使用stm32读取具有HAL库的ds18b20

我认为init正确,但是读写不正确

任何人都可以告诉我为什么它不对吗?

写,这是代码

if ((data & (1 << i)) != 0)
        {
            MX_GPIO_Set(1);
            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
            delay_ms(1);

            MX_GPIO_Set(0);
            delay_ms(60);
        }
        else
        {
            MX_GPIO_Set(1);
            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
            delay_ms(60);

            MX_GPIO_Set(0);
        }

是写一位数据。

,并读取代码

MX_GPIO_Set(1);

        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
        delay_ms(2);

        MX_GPIO_Set(0);
        if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == GPIO_PIN_SET)
        {
            value |= 1 << i;
        }
        delay_ms(60);

MX_GPIO_Set(1)表示设置GPIO输出

哪里错了?

请不要告诉我在github中使用库或代码。我想自己编写代码,这样我才能理解ds18b20。

2 个答案:

答案 0 :(得分:0)

DS18B20使用单线协议。 https://en.wikipedia.org/wiki/1-Wire

每个位大约需要60微秒来传输。 在大多数传输过程中,1为高电平,而在大多数传输过程中,0为低电平。下一位的开始用脉冲表示。

对我来说突出的一件事是,当您可能想使用delay_us(微秒)时,您正在使用delay_ms(毫秒)。

此外,您还需要精确地确定钻头的时间(可能不会)。相反,您的计时要基于脉冲。


这要复杂得多。 读取时,您需要不断检查引脚的值并解释其含义,而不是设置延迟并希望时序匹配。

我尚未测试此代码,但代码不完整。 这只是为了说明一种技术。

首先,我们将输出设置为LOW并等待 传感器至少要保持低电平200us。 (理想情况下,我们的最低要求是500us。200us。) 这是“ RESET”序列,告诉我们新数据即将开始。

const int SleepIntervalMircoseconds = 5;

// Start off by setting our output to LOW (aka GPIO_PIN_RESET).
MX_GPIO_Set(1);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);

// Switch back to reading mode.
MX_GPIO_Set(0);

const int ResetRequiredMiroseconds = 200;

int pinState = GPIO_PIN_SET;
int resetElapsedMicroseconds = 0;
while (pinState != GPIO_PIN_RESET || resetElapsedMicroseconds < ResetRequiredMiroseconds) {
  pinState = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1);
  if (pinState != GPIO_PIN_RESET) {
    resetElapsedMicroseconds = 0;
    continue;
  }

  delay_us(SleepIntervalMircoseconds);

  // Note that the elapsed microseconds is really an estimate here.
  // The actual elapsed time will be 5us + the amount of time it took to execute the code.
  resetElapsedMicroseconds += SleepIntervalMircoseconds;
}

这只会让我们开始。 收到重置信号后,您需要通过在一段时间内将值设置为HIGH来指示另一边已收到重置信号。

答案 1 :(得分:0)

我无法对您的代码发表评论,因为缺少GPIO设置等重要部分以及所调用功能的源代码。但是,如果位时序给您带来麻烦,则可以尝试这样做。

Using a UART to Implement a 1-Wire Bus Master

那么,除了计算UART波特率之外,您无需处理任何延迟和时序。

所有STM32 UART通过开漏GPIO引脚支持单线操作。将设备的I / O引脚连接到UART TX引脚。将引脚配置为漏极开路备用功能输出,并使用UART的备用功能编号(如果适用)。在控制寄存器中启用UART并将其设置为单线操作。

将UART波特率设置为7407,然后发送0xF0,这是复位脉冲。等待RXNE并读取UART数据寄存器。如果不是0xF0,则表明设备正在应答一个应答脉冲。

将UART波特率设置为133333,就可以开始通信了。要发送0位,请将0x00写入UART数据寄存器。要发送1位,请将0xFF写入UART数据寄存器。要接收一点,请写0xFF,等待RXNE,然后读取数据寄存器。如果读取的字节为0xFF,则为1,否则(读取的任何其他值)为0