高精密库仑计DS2740驱动程序

7 篇文章 1 订阅
2 篇文章 0 订阅

环境

单片机:STM32F030F4P6,@48MHz
编译环境:KEIL+STM32CUBEMX

代码

1、头文件:

/***********************
DS2740BU:6.250uV/Rsns,13bit+sign resolution,0.875s conversion period;
DS2740U:1.5625uV/Rsns,15bit+sign resolution,3.500s conversion period;
Full-scale magnitude: ±51.2mV;

电流寄存器格式:
MSB(addr) = 0x0e
MSB---------------------------------->LSB
S  S  S  2(12) 2(11) 2(10) 2(9) 2(9)
LSB(addr) = 0x0F
MSB---------------------------------->LSB
2(7) 2(6) 2(5) 2(4) 2(3) 2(2) 2(1)	2(0)

存储器映射
地址		功能								读写
00			reserve								--
01			status 	register					R/W
02-07		reserve								--
08			special feature						R/W
09-0D		reserve								--
0e			current register MSB				R
0f			current register LSB				R
10			accumulated current register MSB	R
11			accumulated current register LSB	R
12-ff		reserve								--	
-------------------------------------------------------------
状态寄存器(01h)
BIT7	BIT6	BIT5	BIT4	BIT3	BIT2	BIT1	BIT0
X		SMOD	X		RNAOP	X		X		X		X
SMOD:休眠模式使能,该位值为1时,允许DS2740在DQ被拉低的时间超过2秒后进入休眠模式,
值为0时,禁止与DQ相关的休眠模式转换。上电默认0;
RNAOP:读取网络地址操作码。该位为0时,设置读网络地址命令的操作码为33h,
值为1时,操作码为39h。上电默认0;
-------------------------------------------------------------
特殊功能寄存器(08h)
BIT7	BIT6	BIT5	BIT4	BIT3	BIT2	BIT1	BIT0
X		PIO		X		X		X		X		X		X
PIO:PIO引脚检测和控制。该位可读写。PIO位写0时,将使能PIO漏极开路输出驱动器,拉低PIO引脚;
PIO位写1时,将禁止输出驱动器,允许PIO引脚拉高或用作输入。
读PIO位将返回PIO引脚的逻辑电平;
初始上电、DS2740进入休眠模式或DQ为低的时间超过tSLEEP时,PIO复位至1;

*****************************/
/******
采样电阻:5mΩ
芯片:DS2740B(13BIT)
1.25mA/LSB
********/

#ifndef __DS2740_H
#define __DS2740_H

#include "main.h"



#define DS2740_Set()	HAL_GPIO_WritePin(DS2740_DQ_GPIO_Port,DS2740_DQ_Pin,GPIO_PIN_SET)
#define DS2740_Clr()	HAL_GPIO_WritePin(DS2740_DQ_GPIO_Port,DS2740_DQ_Pin,GPIO_PIN_RESET)
#define DS2740_GetDQ()	HAL_GPIO_ReadPin(DS2740_DQ_GPIO_Port,DS2740_DQ_Pin)

void DS2740_ResetAccCurrent(void);
void DS2740_GetCurrent(uint16_t *pCurr,uint16_t *pAccCurr);/*获取DS2740的电流和累计电流数据*/

#endif

2、C文件:

#include "ds2740.h"

void DS2740_ModeOut(void);
void DS2740_ModeIn(void);
void DS2740_Rst(void);
void DS2740_WriteByte(uint8_t dat);

/******************************
	*函数:delay_us
	*功能:延时us函数,STM32F030,系统时钟48MHz
	*输入:无
	*输出:无
******************************/
void delay_us(uint32_t value)
{
    uint32_t i;
    i=value*7;
    while(i--);
}
/******************************
	*函数:DS2740_ModeOut
	*功能:切换引脚到输出模式
	*输入:无
	*输出:无
******************************/
void DS2740_ModeOut(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.Pin =DS2740_DQ_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(DS2740_DQ_GPIO_Port, &GPIO_InitStruct);
}
/******************************
	*函数:DS2740_ModeIn
	*功能:切换引脚到输入模式
	*输入:无
	*输出:无
******************************/
void DS2740_ModeIn(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.Pin =DS2740_DQ_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(DS2740_DQ_GPIO_Port, &GPIO_InitStruct);
}
/******************************
	*函数:DS2740_Rst
	*功能:DS2740复位,启动1-wire通讯前准备
	*输入:无
	*输出:无
******************************/
void DS2740_Rst(void)
{
    uint8_t pulse_time=0;

    DS2740_ModeOut();//配置输出模式
    DS2740_Clr();//拉低
    delay_us(520);/*480-960us*/
    DS2740_ModeIn();//配置为输入模式
    while(DS2740_GetDQ()&&(pulse_time<6))/*15-60us*/
    {
        pulse_time++;
        delay_us(10);
    }
    while(!(DS2740_GetDQ())&&pulse_time<23)/*60-240*/
    {
        pulse_time++;
        delay_us(10);
    }
}
/******************************
	*函数:DS2740_WriteByte
	*功能:写一个字节到DS2740
	*输入:dat
	*输出:无
******************************/
void DS2740_WriteByte(uint8_t dat)
{
    uint8_t j,testb;
    DS2740_ModeOut();//配置输出模式
    for(j=8; j>0; j--)
    {
        testb=dat&0x01;
        dat=dat>>1;
        if(testb)
        {
            DS2740_Clr();
            delay_us(10);
            DS2740_Set();
            delay_us(90);
        }
        else
        {
            DS2740_Clr();
            delay_us(90);
            DS2740_Set();
			delay_us(10);
        }
        delay_us(1);
    }
}
/******************************
	*函数:DS2740_Read_Bit
	*功能:从DS2740读取1位数据
	*输入:无
	*输出:0,1电平
******************************/
uint8_t DS2740_Read_Bit(void)
{
    uint8_t data1;
    DS2740_ModeOut();//配置输出模式
    DS2740_Clr();   //拉低DQ
//delay_us(1);
    DS2740_ModeIn();//配置为输入模式
    delay_us(7);
    if(DS2740_GetDQ()==0)
        data1=0;
    else data1=1;
    delay_us(70);
    return data1;
}
/******************************
	*函数:DS2740_ReadByte
	*功能:从DS2740读取1字节数据
	*输入:无
	*输出:读取到的数据
******************************/
uint8_t DS2740_ReadByte(void)
{
    uint8_t i,j,dat;
    dat=0;
    for (i=0; i<8; i++)
    {
        j=DS2740_Read_Bit();
        dat=(dat)|(j<<i);
    }
    return dat;
}
/******************************
	*函数:DS2740_ResetAccCurrent
	*功能:将DS2740的累计电流寄存器清零
	*输入:无
	*输出:无
******************************/
void DS2740_ResetAccCurrent(void)
{
	DS2740_Rst();
	DS2740_WriteByte(0Xcc);//写入网络命令,总线上只有一个DS2740
	DS2740_WriteByte(0X6c);//写入读数据功能命令			
	DS2740_WriteByte(0X10);//从0x10处开始写入数据
	DS2740_WriteByte(0X00);
	DS2740_WriteByte(0X00);
}
/******************************
	*函数:DS2740_GetCurrent
	*功能:读取DS2740的电流和累计电流寄存器
	*输入:pCurr:电流数据存入指针
			pAccCurr:累计电流数据存入指针
	*输出:无
******************************/
void DS2740_GetCurrent(uint16_t *pCurr,uint16_t *pAccCurr)
{
	uint8_t AL=0,AH=0,ACRL,ACRH;	 
	DS2740_Rst();
	DS2740_WriteByte(0Xcc);//写入网络命令,总线上只有一个DS2740,0XCC-跳过网络地址命令
	DS2740_WriteByte(0X69);//写入读数据功能命令
	DS2740_WriteByte(0X0e);//从0x0e处开始读取数据
	AH = DS2740_ReadByte();//读取电流寄存器高位数据
	AL = DS2740_ReadByte();//读取电流寄存器低位数据
	ACRH = DS2740_ReadByte();//读取电流累计寄存器高位数据
	ACRL = DS2740_ReadByte();//读取电流累计寄存器低位数据

	*pCurr = (AH<<8) | AL;	
	*pAccCurr = (ACRH<<8)|ACRL;
}
//

使用方法:

直接使用DS2740_GetCurrent函数获取芯片的原始数据。
然后再根据外围使用的采样电阻计算电流和累计电流即可,注意标志位处理。
例如:


            DS2740_GetCurrent(&ds2740RawDataCurr,&ds2740RawDataCap);
            if(ds2740RawDataCurr >= 0xE000)/*前3位为标志位*/
            {
                ds2740RawDataCurr = ~ds2740RawDataCurr;
                /*****此处插入功能代码*******/
            }
            if(ds2740RawDataCap >= 0x8000)
            {
               ds2740RawDataCap = ~ds2740RawDataCap;
               /*****此处插入功能代码*******/
            }

注意

1、DS2740使用1-wire通讯,对时序有要求,如果改变单片机的频率,需要确认里面的阻塞延时函数delay_us的精度。

实例

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值