pstd2/User/App/ds18b20.c

237 lines
6.6 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "ds18b20.h"
#include "string.h"
bus_port_t bus_port_A, bus_port_B;
ds18b20_t ds18b20_A, ds18b20_B;
static uint8_t ds18b20_check_cb(bus_port_t *bus_port);
static void ds18b20_write_cmd_cb(bus_port_t *bus_port, uint8_t cmd);
static uint8_t ds18b20_read_data_cb(bus_port_t *bus_port);
#define CPU_FREQUENCY_MHZ 84
void delay_us(__IO uint32_t delay)
{
int last, curr, val;
int temp;
while (delay != 0)
{
temp = delay > 900 ? 900 : delay;
last = SysTick->VAL;
curr = last - CPU_FREQUENCY_MHZ * temp;
if (curr >= 0)
{
do
{
val = SysTick->VAL;
} while ((val < last) && (val >= curr));
}
else
{
curr += CPU_FREQUENCY_MHZ * 1000;
do
{
val = SysTick->VAL;
} while ((val <= last) || (val > curr));
}
delay -= temp;
}
}
static uint8_t ds18b20_check_cb(bus_port_t *bus_port)
{
if (!bus_port)
return 0;
GPIO_TypeDef *TX_GPIOx = bus_port->TX_GPIOx;
uint16_t TX_GPIO_Pin = bus_port->TX_GPIO_Pin;
GPIO_TypeDef *RX_GPIOx = bus_port->RX_GPIOx;
uint16_t RX_GPIO_Pin = bus_port->RX_GPIO_Pin;
write_pin_cb_t write_pin_cb = bus_port->write_pin_cb;
read_pin_cb_t read_pin_cb = bus_port->read_pin_cb;
uint8_t ack = 0;
__disable_irq();
write_pin_cb(TX_GPIOx, TX_GPIO_Pin, GPIO_PIN_SET);
delay_us(10);
write_pin_cb(TX_GPIOx, TX_GPIO_Pin, GPIO_PIN_RESET);
delay_us(500); // 复位信号拉低480us以上
write_pin_cb(TX_GPIOx, TX_GPIO_Pin, GPIO_PIN_SET); // 释放总线
delay_us(50); // 维持15~60us,等待应答(低电平应答,维持60-240us
if (read_pin_cb(RX_GPIOx, RX_GPIO_Pin, GPIO_PIN_SET) == GPIO_PIN_SET)
{
ack = 1;
}
write_pin_cb(TX_GPIOx, TX_GPIO_Pin, GPIO_PIN_SET); // 释放总线
delay_us(240); // 保证时序完整
__enable_irq(); /* 使能全局中断 */
return ack;
}
static void ds18b20_write_cmd_cb(bus_port_t *bus_port, uint8_t cmd)
{
if (!bus_port)
return;
GPIO_TypeDef *TX_GPIOx = bus_port->TX_GPIOx;
uint16_t TX_GPIO_Pin = bus_port->TX_GPIO_Pin;
write_pin_cb_t write_pin_cb = bus_port->write_pin_cb;
uint8_t i;
__disable_irq();
for (i = 0; i < 8; i++)
{
write_pin_cb(TX_GPIOx, TX_GPIO_Pin, GPIO_PIN_RESET); // 拉低总线
delay_us(5);
if (cmd & 0x01)
{
write_pin_cb(TX_GPIOx, TX_GPIO_Pin, GPIO_PIN_SET);
}
else
{
write_pin_cb(TX_GPIOx, TX_GPIO_Pin, GPIO_PIN_RESET);
}
delay_us(70); // 继续维持至少15us 最多30us 电平
write_pin_cb(TX_GPIOx, TX_GPIO_Pin, GPIO_PIN_SET);
cmd >>= 1; // 右移一位
delay_us(5);
}
__enable_irq();
}
static uint8_t ds18b20_read_data_cb(bus_port_t *bus_port)
{
if (!bus_port)
return 0;
GPIO_TypeDef *TX_GPIOx = bus_port->TX_GPIOx;
uint16_t TX_GPIO_Pin = bus_port->TX_GPIO_Pin;
GPIO_TypeDef *RX_GPIOx = bus_port->RX_GPIOx;
uint16_t RX_GPIO_Pin = bus_port->RX_GPIO_Pin;
write_pin_cb_t write_pin_cb = bus_port->write_pin_cb;
read_pin_cb_t read_pin_cb = bus_port->read_pin_cb;
uint8_t i;
uint8_t data = 0;
__disable_irq();
for (i = 0; i < 8; i++)
{
write_pin_cb(TX_GPIOx, TX_GPIO_Pin, GPIO_PIN_RESET); // 拉低总线
delay_us(5); // 大于1us
write_pin_cb(TX_GPIOx, TX_GPIO_Pin, GPIO_PIN_SET); // 释放总线
delay_us(10); // 大于1us
data >>= 1;
if (read_pin_cb(RX_GPIOx, RX_GPIO_Pin, GPIO_PIN_SET) == GPIO_PIN_SET)
{
data |= 0x80;
}
delay_us(50);
write_pin_cb(TX_GPIOx, TX_GPIO_Pin, GPIO_PIN_SET); // 释放总线
delay_us(5);
}
__enable_irq();
return data;
}
void ds18b20_read_temperature_cb(bus_port_t *bus_port, ds18b20_t *ds18b20)
{
if (!bus_port)
return;
uint8_t reg_msb;
uint8_t reg_lsb;
BOOL signal;
uint32_t temp = 0;
if (ds18b20->check(bus_port) == 1) // DS18B20 初始化
{
ds18b20->temperature.f = 0.0f;
return; // 读取失败
}
ds18b20->write_cmd(bus_port, SKIP_ROM); // 跳过ROM
ds18b20->write_cmd(bus_port, TEMP_SWITCH); // 启动温度转换
ds18b20->check(bus_port); // DS18B20 初始化
ds18b20->write_cmd(bus_port, SKIP_ROM); // 跳过ROM
ds18b20->write_cmd(bus_port, READ_MEMORY); // 发送读暂存存储器指令
// D15 D14 D13 D12 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 16位数据 说明
//** 温度正负标志 ** ** 温度整数部分 ** **小数部分**
reg_lsb = ds18b20->read_data(bus_port); // 低字节
reg_msb = ds18b20->read_data(bus_port); // 高字节 高5位是正负标志 全为1 负 全为0 正
if (reg_msb > 7)
{
reg_msb = ~reg_msb;
reg_lsb = ~reg_lsb;
signal = 1;
}
else
signal = 0;
temp = reg_msb;
temp <<= 8;
temp += reg_lsb;
if ((temp == 0xffff) || (temp == 0) || temp >= (uint32_t)(100.0f / 0.0625f))
return;
ds18b20->temperature.f = temp * 0.0625;
if (signal)
ds18b20->temperature.f = -(temp * 0.0625);
else
ds18b20->temperature.f = temp * 0.0625;
}
void fun_ini_bus_port(bus_port_t *bus_port)
{
if (!bus_port)
return;
memset(bus_port, 0, sizeof(bus_port_t));
if (bus_port == &bus_port_A)
{
bus_port->TX_GPIO_Pin = TEMP_A_TXD_Pin;
bus_port->TX_GPIOx = TEMP_A_TXD_GPIO_Port;
bus_port->RX_GPIO_Pin = TEMP_A_RXD_Pin;
bus_port->RX_GPIOx = TEMP_A_RXD_GPIO_Port;
}
else if (bus_port == &bus_port_B)
{
bus_port->TX_GPIO_Pin = TEMP_B_TXD_Pin;
bus_port->TX_GPIOx = TEMP_B_TXD_GPIO_Port;
bus_port->RX_GPIO_Pin = TEMP_B_RXD_Pin;
bus_port->RX_GPIOx = TEMP_B_RXD_GPIO_Port;
}
bus_port->read_pin_cb = (read_pin_cb_t)HAL_GPIO_ReadPin;
bus_port->write_pin_cb = HAL_GPIO_WritePin;
}
void fun_ini_ds18b20(ds18b20_t *ds18b20)
{
if (!ds18b20)
return;
memset(ds18b20, 0, sizeof(ds18b20_t));
if (ds18b20 == &ds18b20_A)
ds18b20->index = 1;
else if (ds18b20 == &ds18b20_B)
ds18b20->index = 2;
ds18b20->check = ds18b20_check_cb;
ds18b20->write_cmd = ds18b20_write_cmd_cb;
ds18b20->read_data = ds18b20_read_data_cb;
}