237 lines
6.6 KiB
C
237 lines
6.6 KiB
C
#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;
|
||
}
|
||
|
||
|