环境
单片机: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的精度。
实例