DS2781驱动程序源码开源

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**************************************/

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值