#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; }