ds2781.c 文件:
/*
***********************************************************************************
* 文 件:DS2781.c
* 描 述:DS2781测量可充电电池的电压、温度和电流,并估算其剩余电量
* 版 本:V0.0
* 平 台:Keil uVision5 STM32CubeMx
* 备 注:用于STM32F系列
* 程序员:贾工
* 日 期:2022-08-25
***********************************************************************************
*/
#include "ds2781.h"
/**
* @brief 微妙延时
* @param us 延时值
* @retval no
*/
void Delay_us(uint16_t us)
{
while(us--)
{
for(uint8_t j=0;j<12;j++);
}
}
/**
* @brief 复位单总线
* @param t_RSTL = 480 ~ 960 us
* t_RSTH = 480 ~ --- us
* t_PDH = 15 ~ 60 us
* t_PDL = 60 ~ 240 us
* @retval no
* |<--------RSTH---------------->|
* ___ |___ ______________| _ _ _ pack+
* |<-----RSTL----->|PDH|<----PDL-->| | DQ
* |________________| |___________| |____ _ _ _ pack-
*/
void lWire_Reset(void)
{
uint16_t cnt=0;
DQ_L();
Delay_us(480); // RSTL
DQ_H();
Delay_us(35); // PDH
while (DQ_IN == 0 && cnt<60) { cnt++; Delay_us(1); }
while (DQ_IN == 1 && cnt<300) { cnt++; Delay_us(1); } // PDL
}
/**
* @brief 向单总线上的设备写一个字节
* @param dat 要写入的字节
* write 0 write 1
* |<------t_SLOT------->|<------t_SLOT-------->|
* ____| ___| _________________| _ _ V-PULLUP
* |<----t_LOW0----->|REC|LOW1| |
* |_________________| |____| | _ _GND
*
* t_SLOT = 60 ~ 120 us
* t_LOW0 = 60 ~ 120 us
* t_LOW1 = 1 ~ 15 us
* t_REC = 1 ~ --- us
*/
void lWire_WriteByte(uint8_t dat)
{
uint8_t tmp;
for (uint8_t i=0; i<8; i++)
{
tmp = dat & 0x01;
dat = dat>>1;
if (tmp) // Write 1
{
DQ_L();
Delay_us(2);
DQ_H();
Delay_us(60); // 写时隙t_LOW1 = 60~120us
}
else // Write 0
{
DQ_L();
Delay_us(60);
DQ_H();
Delay_us(2);
}
}
}
/**
* @brief 单总线上的设备读取一个字节
* @retval 读到的数据
*/
uint8_t lWire_ReadByte(void)
{
uint8_t i,j,dat=0;
for (i=1;i<=8;i++)
{
DQ_L();
Delay_us(2);
DQ_H();
Delay_us(12);
if(DQ_IN) j = 1;
else j = 0;
Delay_us(50);
dat=(j<<7)|(dat>>1);
}
return dat;
}
/**
* @brief DS2781获得电池电压,测量范围0V~9.9902V,分辨率为9.76mV。
* @retval vol 电压(V)
* @note 只读寄存器
*/
float DS2781_Voltage(void)
{
float vol;
uint8_t msb,lsb;
lWire_Reset();
lWire_WriteByte(SEND_FUN);
lWire_WriteByte(READ);
lWire_WriteByte(REG_VOLT_MSB);
msb = lWire_ReadByte();
lsb = lWire_ReadByte();
vol = ((msb<<8|lsb)>>5)*0.00976;
return vol;
}
/**
* @brief DS2781读取温度,分辨率为0.125℃。
* @retval temp:温度(℃)
* @note 只读寄存器
*/
float DS2781_Temp(void)
{
float temp;
uint8_t msb,lsb;
lWire_Reset();
lWire_WriteByte(SEND_FUN);
lWire_WriteByte(READ);
lWire_WriteByte(REG_TEMP_MSB);
msb=lWire_ReadByte();
lsb=lWire_ReadByte();
temp = ((msb<<8|lsb)>>5)*0.125;
return temp;
}
/**
* @brief DS2781检测电阻值读取,该值长度为1个字节.以电导形式存储。位于EEPROM
* 阻值范围:1 ~ 0.003922R。
* 电导范围:1 ~ 255西门子
* @retval 电阻值(欧姆)
*/
float DS2781_ResValue(void)
{
uint8_t lsp;
float res;
lWire_Reset();
lWire_WriteByte(SEND_FUN);
lWire_WriteByte(READ);
lWire_WriteByte(REG_RSNSP);
lsp = lWire_ReadByte();
res = 1 / (float)lsp;
return res;
}
/**
* @brief DS2781取样电阻改写
* @param res 阻值范围:1 ~ 0.003922R。
* @retval
*/
void DS2781_Write_Res(float res)
{
uint8_t temp;
temp = 1 / res; // 转换电导形式
lWire_Reset();
lWire_WriteByte(SEND_FUN);
lWire_WriteByte(WRITE);
lWire_WriteByte(REG_RSNSP);
lWire_WriteByte(temp);
lWire_Reset();
lWire_WriteByte(SEND_FUN);
lWire_WriteByte(COPY);
lWire_WriteByte(REG_RSNSP);
}
/**
* @brief 平均电流寄存器给出前28s内的平均电流值。
* 每28s更新一次,它是电流寄存器前面8个更新值的平均值。
* 充电电流值大于最大寄存器值时,则报告最大寄存器值 (7FFFh =+51.2mV)。
* 放电电流超过最小寄存器值时, 则报告最小寄存器值 (8000h =-51.2mV)。
* @param res: 阻值范围:1 ~ 0.003922R。
* @retval cur: 电流单位A
* @note 只读寄存器
*/
float DS2781_Iavg(float res)
{
float cur;
uint8_t msb,lsb;
lWire_Reset();
lWire_WriteByte(SEND_FUN);
lWire_WriteByte(READ);
lWire_WriteByte(REG_IAVG_MSB);
msb=lWire_ReadByte();
lsb=lWire_ReadByte();
cur = ((msb<<8|lsb)>>5)*0.0015625/res;
return cur;
}
/**
* @brief 剩余相对有效电量 (RARC) [%]
* 有效空电量放电速率(IAE)放电到有效空电量点时的可用电量.
* @retval cap 电量
* @note 只读寄存器采用百分比表示。RARC为8位。
*/
uint8_t DS2781_Read_RARC(void)
{
uint8_t cap;
lWire_Reset();
lWire_WriteByte(SEND_FUN);
lWire_WriteByte(READ);
lWire_WriteByte(REG_RARC);
cap=lWire_ReadByte();
return cap;
}
/***************************************END**ds2781.c**********************************/
ds2781.h头文件:
/*
***********************************************************************************
* 文 件:DS2781.h
* 描 述:DS2781测量可充电电池的电压、温度和电流,并估算其剩余电量
* 版 本:V0.0
* 平 台:Keil uVision5 STM32CubeMx
* 备 注:用于STM32F系列
* 程序员:贾工
* 日 期:2022-08-25
***********************************************************************************
*/
#ifndef _DS2781_H
#define _DS2781_H
#include "main.h"
/**ds2781命令*********************************************************************/
#define SEND_FUN 0XCC // 单个设备发送功能命令
#define WRITE 0X6C // 写命令
#define READ 0X69 // 读命令
#define COPY 0X48 // 该命令映射RAM的内容复制到EEPROM模块
/**ds2781寄存器*******************************************************************/
#define REG_STATUS 0X01 // 状态寄存器 R/W
#define REG_RAAC_MSB 0X02 // 剩余绝对有效电量高字节 R
#define REG_RAAC_LSB 0X03 // 剩余绝对有效电量低字节 R
#define REG_RSAC_MSB 0X04 // 剩余绝对待机电量高字节 R
#define REG_RSAC_LSB 0X05 // 剩余绝对待机电量低字节 R
#define REG_RARC 0X06 // 剩余相对有效电量% R
#define REG_RSRC 0X07 // 剩余相对待机电量% R
#define REG_IAVG_MSB 0X08 // Average Current Register MSB R
#define REG_IAVG_LSB 0X09 // Average Current Register LSB R
#define REG_TEMP_MSB 0X0A // Temperature Register MSB R
#define REG_TEMP_LSB 0X0B // Temperature Register LSB R
#define REG_VOLT_MSB 0X0C // Voltage Register MSB R
#define REG_VOLT_LSB 0X0D // Voltage Register LSB R
#define REG_CURRENT_MSB 0X0E // Current Register MSB R
#define REG_CURRENT_LSB 0X0F // Current Register LSB R
#define REG_ACR_MSB 0X10 // Accumulated Current Register MSB R/W
#define REG_ACR_LSB 0X11 // Accumulated Current Register LSB R/W
#define REG_ACRL_MSB 0X12 // Low Accumulated Current Register MSB R
#define REG_ACRL_LSB 0X13 // Low Accumulated Current Register LSB R
#define REG_AS 0X14 // Age Scalar R/W
#define REG_SFR 0X15 // Special Feature Register R/W
#define REG_FULL_MSB 0X16 // Full Capacity MSB R
#define REG_FULL_LSB 0X17 // Full Capacity LSB R
#define REG_AE_MSB 0X18 // Active Empty MSB R
#define REG_AE_LSB 0X19 // Active Empty LSB R
#define REG_SE_MSB 0X1A // Standby Empty MSB R
#define REG_SE_LSB 0X1B // Standby Empty LSB R
#define REG_CONTROL 0X60 // Control Register 控制寄存器
#define REG_AB 0X61 // 电流累计偏置寄存器
#define REG_AC_MSB 0X62 // 老化容量用来存放额定电池容量 高字节
#define REG_AC_LSB 0X63 // 老化容量用来存放额定电池容量 低字节
#define REG_VCHG 0X64 // 充电电压门限值寄存器
#define REG_IMIN 0X65 // 充电电流门限值寄存器
#define REG_VAE 0X66 // 有效空电压寄存器
#define REG_IAE 0X67 // 有效空电流寄存器
#define REG_AE_40 0X68 // Active Empty 40
#define REG_RSNSP 0X69 // 存储检测电阻的值寄存器
#define REG_FULL_40_MSB 0X6A
#define REG_FULL_40_LSB 0X6B
#define REG_FULL_SEGMENT_4 0X6C // Full Segment 4 Slope
#define REG_FULL_SEGMENT_3 0X6D // Full Segment 3 Slope
#define REG_FULL_SEGMENT_2 0X6E // Full Segment 2 Slope
#define REG_FULL_SEGMENT_1 0X6F // Full Segment 1 Slope
#define REG_AE_SEGMENT_4 0X70 // AE Segment 4 Slope
#define REG_AE_SEGMENT_3 0X71 // AE Segment 3 Slope
#define REG_AE_SEGMENT_2 0X72 // AE Segment 2 Slope
#define REG_AE_SEGMENT_1 0X73 // AE Segment 1 Slope
#define REG_SE_SEGMENT_4 0X74 // SE Segment 4 Slope
#define REG_SE_SEGMENT_3 0X75 // SE Segment 3 Slope
#define REG_SE_SEGMENT_2 0X76 // SE Segment 2 Slope
#define REG_SE_SEGMENT_1 0X77 // SE Segment 1 Slope
#define REG_RSGAIN_MSB 0X78 // Sense Resigtor Gain MSB
#define REG_RSGAIN_LSB 0X79 // Sense Resigtor Gain LSB
#define REG_RSTC 0X7A // Sense Resistor Temp.Coeff
#define REG_COB 0X7B // Current Offset Bias
#define REG_TBP34 0X7C //
#define REG_TBP23 0X7D //
#define REG_TBP12 0X7E //
/**单总IO操作********************************************************************/
#define DQ_H() HAL_GPIO_WritePin(DQ_GPIO_Port,DQ_Pin,GPIO_PIN_SET)
#define DQ_L() HAL_GPIO_WritePin(DQ_GPIO_Port,DQ_Pin,GPIO_PIN_RESET)
#define DQ_IN HAL_GPIO_ReadPin(DQ_GPIO_Port,DQ_Pin)
/**供外部调用的函数声明**********************************************************/
float DS2781_Voltage(void); // 读取电池电压
float DS2781_Temp(void); // 读取温度
float DS2781_ResValue(void); // 读取取样电阻值
void DS2781_Write_Res(float res); // 修改取样电阻值
float DS2781_Iavg(float res); // 读取电流
uint8_t DS2781_Read_RSRC(void); // 读取电量
#endif
/***************************** END ds2781.H**************************************/