arduino Wemos D 1HT7038调试笔记

 HT7038核心板原理图

电压互感器接口板原理图

按上述原理图,我分别制作了HT7038模块板和互感器接口板。

原有51的程序可以正常读出HT7038电压数据,此次我把KEIL C51的程序移植到arduino WEMOS D1平台,

开始wemos D1可以读取 rDeviceID和rChipID数据,我就以为大功告成。可是当我读电压数据时没有任何返回数据。几经周折发现是往HT7038写命令时没有给命令最高位置1.

 实际SPI写寄存器命令

现在回想调试HT7038大概步骤应该是:

1实现读取rDeviceID和rChipID数据,如果能读取到,则表明SPI通讯正常。

2向w_ModeCfg写入数据,然后再读取该寄存器的数据,看是否和写入的数据一致,如果返回的是默认值0x89AA,则表明写入不成功。

写入前应开启校表寄存器写入,

ht7038.Write7038(0xC9,0x00005A);   //设置可以写入校表寄存器的参数

然后写入数据

ht7038.Write7038(w_ModeCfg,0xF954);//开启电压通道ADC ,更新速率为慢速0xF9FE

禁止校表寄存器写入

ht7038.Write7038(0xC9,0x0000FF);  //关闭写校表寄存器

开启读取校表寄存器

ht7038.Write7038(0xC6,0x00005A); //设置可以读校表寄存器的参数

读取校表寄存器

Serial.println(ht7038.Read7038(w_ModeCfg),HEX);//读取校表w_ModeCfg寄存器,并返回给串口输出

具体解释见官方表格

如果写入校表寄存器成功,则读取电压电流功率等数据不成问题。

下面是arduino代码:

//2ma/2ma互感器按220V 2ma设置
#include <SPI.h>
#include "HT7038.h"
#include <BlynkSimpleEsp8266.h>
HT7038 ht7038;
BlynkTimer timer;
//#define  _DEBUG;
typedef union
{
  unsigned long Long_Data;
  byte da[4];
  }DWord;
DWord  rData;
union UN_RMS{
//       unsigned char   volChar[4]; //电压字节数组
       unsigned long   volFloat;  //电压浮点数
      
    };
union UN_RMS U_rms; 
  float  Uab;
  float  Ubc;
  float  Uac;
void SPIsendData()
{
    #ifdef _DEBUG
      Serial.print("rDeviceID=0x");
      Serial.println(ht7038.Read7038(rDeviceID),HEX);  
      Serial.print("  rChipID=0x");
      Serial.println(ht7038.Read7038(rChipID),HEX);
    #endif

    
    rData.Long_Data = ht7038.Read7038(rUaRms);    //读取Uab电压 
    U_rms.volFloat=rData.Long_Data ;
    Uab=(float)U_rms.volFloat/8192;
    
    rData.Long_Data = ht7038.Read7038(rUbRms);    //读取Uac电压 内部计算得出
    U_rms.volFloat=rData.Long_Data ;

    Uac=(float)U_rms.volFloat/8192;  //长整型强制转换成浮点型,否者液晶显示数据为0
    
    rData.Long_Data = ht7038.Read7038(rUcRms);    //读取Ubc电压
    U_rms.volFloat=rData.Long_Data ;
    
    Ubc=(float)U_rms.volFloat/8192;
    
    Serial.print("Uab=");
    Serial.print(Uab);
    Serial.println("V");
    Serial.print("Ubc=");
    Serial.print(Ubc);
    Serial.println("V");
    Serial.print("Uac=");
    Serial.print(Uac);
    Serial.println("V");
    Serial.println("-------------------");
  }
void setup() 
{
   Serial.begin(230400);
   ht7038.HT7038_begin();
   
   ht7038.HT7038_init();
   delay(20);
   ht7038.Write7038(0xC9,0x00005A);   //设置可以写入校表寄存器的参数
   ht7038.Write7038(w_ModeCfg,0xF954);//开启电压通道ADC ,更新速率为慢速0xF9FE
   ht7038.Write7038(w_EMCfg,0x0003);//设置三相三线模式0x0111
   ht7038.Write7038(w_EMUIE,0xFFFF);
   ht7038.Write7038(w_ModuleCFG,0x3404);//0x3404
   ht7038.Write7038(w_PGACtrl,0x0000); //ADC增益配置为三相电压通道ADC增益放大2倍 bit09和bit08为设置电压通道增益位
   
   ht7038.Write7038(w_EMUCfg,0x0201); //EMU模块配置寄存器0x0201

   ht7038.Write7038(w_UgainA,0x022E);//Uab电压增益
   ht7038.Write7038(w_UgainC,0x022E);//Ubc电压增益
   ht7038.Write7038(w_UgainB,0x022E);//Uac相电压增益需单独计算,不与A相C相相同
 
   ht7038.Write7038(0xC9,0x0000FF);  //关闭写校表寄存器
   ht7038.Write7038(0xC6,0x000000); //设置可以读计量寄存器的参数

   
   timer.setInterval(1000L, SPIsendData);
}

void loop() {
 timer.run();
}

头文件代码:

#ifndef __HT7038_H__
#define __HT7038_H__
//导入Arduino核心头文件
#include"Arduino.h" 
#include <SPI.h>
#define HT7038_CS  D8    //针对自制的HT7038接口板

//===================================================
//      定义HT7038的数据寄存器 
//===================================================
#define rDeviceID 0x00  //7038 Device ID
#define rPa     0x01  //A相有功功率
#define rPb     0x02  //B相有功功率
#define rPc     0x03  //C相有功功率
#define rPt     0x04  //合相有功功率

#define rQa     0x05  //A相无功功率
#define rQb     0x06  //B相无功功率
#define rQc     0x07  //C相无功功率
#define rQt     0x08  //合相无功功率

#define rSa     0x09  //A相视在功率
#define rSb     0x0A  //B相视在功率
#define rSc     0x0B  //C相视在功率
#define rSt     0x0C  //合相视在功率

#define rUaRms      0x0D  //A相电压有效值
#define rUbRms      0x0E  //B相电压有效值
#define rUcRms      0x0F  //C相电压有效值

#define rIaRms      0x10  //A相电流有效值
#define rIbRms      0x11  //B相电流有效值
#define rIcRms      0x12  //C相电流有效值
#define rItRms      0x13  //ABC相电流矢量和的有效值

#define rPfa    0x14  //A相功率因数
#define rPfb    0x15  //B相功率因数
#define rPfc    0x16  //C相功率因数
#define rPft    0x17  //合相功率因数

#define rPga    0x18  //A相电流与电压相角
#define rPgb    0x19  //B相电流与电压相角功率因数
#define rPgc    0x1a  //C相电流与电压相角

#define rINTFlag  0x1b  //中断标志,读后清零 ☆

#define rFreq   0x1C  //线频率
#define rEFlag  0x1d  //电能寄存器的工作状态,读后清零☆

#define rEpa    0x1e  //A相有功电能
#define rEpb    0x1f  //B相有功电能
#define rEpc    0x20  //C相有功电能
#define rEpt    0x21  //合相有功电能

#define rEqa    0x22  //A相无功电能
#define rEqb    0x23  //B相无功电能
#define rEqc    0x24  //C相无功电能
#define rEqt    0x25  //合相无功电能

#define rYUaUb    0x26  //Ua与Ub的电压夹角            ☆
#define rYUaUc    0x27  //Ua与Uc的电压夹角            ☆
#define rYUbUc    0x28  //Ub与Uc的电压夹角            ☆

#define rTPSD   0x2a  //温度传感器的输出
#define rURmst    0x2b  //ABC电压矢量和的有效值

#define rS_Flag   0x2c  //存放断相、相序、SIG信号的有效值

#define rBackReg    0x2d  //通讯数据备份寄存器☆
#define rComChksum  0x2e  //通讯校验和寄存器☆
#define rSampleIA   0x2f  //A相电流通道ADC采样数据☆
#define rSampleIB   0x30  //B相电流通道ADC采样数据☆
#define rSampleIC   0x31  //C相电流通道ADC采样数据☆

#define rSampleUA   0x32  //A相电压通道ADC采样数据☆
#define rSampleUB   0x33  //B相电压通道ADC采样数据☆
#define rSampleUC   0x34  //C相电压通道ADC采样数据☆

#define rEsa  0x35  //A相视在电能☆
#define rEsb  0x36  //B相视在电能☆
#define rEsc  0x37  //C相视在电能☆
#define rEst  0x38  //合相视在电能☆

#define rFstCntA    0x39  //A相快速脉冲计数☆
#define rFstCntB    0x40  //B相快速脉冲计数☆
#define rFstCntC    0x40  //C相快速脉冲计数☆
#define rFstCntT    0x41  //合相快速脉冲计数☆

#define rPFlag    0x3d  //有功和无功功率方向,正向为0,负向为1

#define rChkSum 0x3e  //校表数据校验寄存器(三相四线模式下是0x01D4CD;三相三线模式下是0x01E0CD;)


#define rVrefgain   0x5c  //Vref自动补偿系数
#define rChipID     0x5d  //芯片版本指示器0X7026E0
#define rChkSum1    0x5e  //新增校表寄存器校验和

//==================================================================
//          HT7038校表寄存器定义
//==================================================================
#define w_ModeCfg       0X01  //模式相关控制 
#define w_PGACtrl       0X02  //ADC增益选择 
#define w_EMUCfg        0X03  //EMU模块配置寄存器 
#define w_PgainA        0X04  //A相有功功率增益 
#define w_PgainB        0X05  //B相有功功率增益 
#define w_PgainC        0X06  //C相有功功率增益 
#define w_QgainA        0X07  //A相无功功率增益 
#define w_QgainB        0X08  //B相无功功率增益 
#define w_QgainC        0X09  //C相无功功率增益 
#define w_SgainA        0X0A  //A相视在功率增益 
#define w_SgainB        0X0B  //B相视在功率增益 
#define w_SgainC        0X0C  //C相视在功率增益 
#define w_PhSregApq0    0X0D  //A相相位校正0 
#define w_PhSregBpq0    0X0E  //B相相位校正0 
#define w_PhSregCpq0    0X0F  //C相相位校正0 
#define w_PhSregApq1    0X10  //A相相位校正1 
#define w_PhSregBpq1    0X11  //B相相位校正1 
#define w_PhSregCpq1    0X12  //C相相位校正1 
#define w_PoffsetA      0X13  //A相有功功率offset校正 
#define w_PoffsetB      0X14  //B相有功功率offset校正 
#define w_PoffsetC      0X15  //C相有功功率offset校正 
#define w_QPhscal       0X16  //无功相位校正 
#define w_UgainA        0X17  //A相电压增益 
#define w_UgainB        0X18  //B相电压增益 
#define w_UgainC        0X19  //C相电压增益 
#define w_IgainA        0X1A  //A相电流增益 
#define w_IgainB        0X1B  //B相电流增益 
#define w_IgainC        0X1C  //C相电流增益 
#define w_Istarup       0X1D  //起动电流阈值设置 
#define w_Hfconst       0X1E  //高频脉冲输出设置 
#define w_FailVoltage   0X1F  //失压阈值设置

#define w_QoffsetA      0X21  //A相无功功率offset校正 
#define w_QoffsetB      0X22  //B相无功功率offset校正 
#define w_QoffsetC      0X23  //C相无功功率offset校正 
#define w_UaRmsoffse    0X24  //A相电压有效值offset校正 
#define w_UbRmsoffse    0X25  //B相电压有效值offset校正 
#define w_UcRmsoffse    0X26  //C相电压有效值offset校正 
#define w_IaRmsoffse    0X27  //A相电流有效值offset校正 
#define w_IbRmsoffse    0X28  //B相电流有效值offset校正 
#define w_IcRmsoffse    0X29  //C相电流有效值offset校正 
#define w_UoffsetA      0X2A  //A相电压通道ADC offset校正 
#define w_UoffsetB      0X2B  //B相电压通道ADC offset校正 
#define w_UoffsetC      0X2C  //C相电压通道ADC offset校正 
#define w_IoffsetA      0X2D  //A相电流通道ADC offset校正 
#define w_IoffsetB      0X2E  //B相电流通道ADC offset校正 
#define w_IoffsetC      0X2F  //C相电流通道ADC offset校正 
#define w_EMUIE         0X30  //中断使能 
#define w_ModuleCFG     0X31  //电路模块配置寄存器 
#define w_AllGain       0X32  //全通道增益,用于校正ref自校正
#define w_HFDouble      0X33  //脉冲常数加倍选择 
#define w_LineGain      0X34  //基波增益校正 
#define w_PinCtrl       0X35  //数字pin上下拉电阻选择控制 
#define w_Pstartup      0X36  //起动功率阈值设置 
#define w_Iregion0      0X37  //相位补偿区域设置寄存器 
#define w_Iregion1      0X60  //相位补偿区域设置寄存器1 
#define w_PhSregApq2    0X61  //A相相位校正2 
#define w_PhSregBpq2    0X62  //B相相位校正2 
#define w_PhSregCpq2    0X63  //C相相位校正2 
#define w_PoffsetAL     0X64  //A相有功功率offset校正低字节 
#define w_PoffsetBL     0X65  //B相有功功率offset校正低字节 
#define w_PoffsetCL     0X66  //C相有功功率offset校正低字节 
#define w_QoffsetAL     0X67  //A相无功功率offset校正低字节 
#define w_QoffsetBL     0X68  //B相无功功率offset校正低字节 
#define w_QoffsetCL     0X69  //C相无功功率offset校正低字节 
#define w_ItRmsoffset   0X6A  //电流矢量和offset校正寄存器 
#define w_TPSoffset     0X6B  //TPS初值校正寄存器 
#define w_TPSgain       0X6C  //TPS斜率校正寄存器 
#define w_TCcoffA       0X6D  //Vrefgain的二次系数
#define w_TCcoffB       0X6E  //Vrefgain的一次系数
#define w_TCcoffC       0X6F  //Vrefgain的常数项 
#define w_EMCfg         0X70  //新增算法控制寄存器


//===================================================================================
class HT7038
{
  private:
    byte pin;        //CS引脚
  public:
     HT7038(byte p=HT7038_CS,bool state=HIGH );
    ~HT7038();
     void HT7038_begin();
     void HT7038_init();
     void disattach();
     unsigned long Read7038(unsigned char rCmd);
     void Write7038(unsigned char wCmd,unsigned long Dat);
};
//====================================================================================

#endif

 CPP实现文件:

#include "HT7038.h" 

HT7038::HT7038(byte p,bool state):pin(p)
{
   pinMode(pin,OUTPUT);
   digitalWrite(pin, HIGH);
}
HT7038::~HT7038()
{
  disattach();
}
void HT7038::HT7038_begin()
{
  SPI.begin();
  digitalWrite(pin, HIGH);
  SPI.setDataMode(SPI_MODE1);
  SPI.setClockDivider(SPI_CLOCK_DIV32);
  SPI.setBitOrder(MSBFIRST);
}

void HT7038::HT7038_init()
{
  Write7038(0xD3,0X000000);//软件复位
}


unsigned long HT7038:: Read7038(unsigned char rCmd)
{
  unsigned long buffer=0;
  unsigned char dataLength=3;
  unsigned char byteIndex=0 ;
  unsigned char receiveBuffer = 0;
  digitalWrite(pin, LOW);
  SPI.transfer(rCmd); //发送命令
    //接收从站返回数据,SPI.transfer(0)一次带回1个byte数据
    while(byteIndex < dataLength)
    {
      receiveBuffer = SPI.transfer(0);
      buffer = (buffer << 8) + receiveBuffer;
      byteIndex++;
    }
  digitalWrite(pin, HIGH);
   
  return buffer;
}
void HT7038::Write7038(unsigned char wCmd,unsigned long Dat)
{
  long send;
  unsigned char data[3];
  typedef union
{
  unsigned long Long_Data;
  unsigned char da[4];
 }DWord;
 DWord  rData;
  wCmd = wCmd | 0x80;   //最高位置位,表示为写操作 这句很重要
  //32大端转小端原理
  send = ((Dat>>24)&0xff) | // move byte 3 to byte 0
         ((Dat<<8)&0xff0000) | // move byte 1 to byte 2
         ((Dat>>8)&0xff00) | // move byte 2 to byte 1
         ((Dat<<24)&0xff000000); // byte 0 to byte 3
   rData.Long_Data=send;
   data[0]=rData.da[1];
   data[1]=rData.da[2];
   data[2]=rData.da[3];
   
   digitalWrite(pin, LOW);       
  SPI.transfer(wCmd); 
  SPI.transfer(&data,3);
  digitalWrite(pin, HIGH);
}
void HT7038::disattach()        //引脚回收,恢复到上电状态
{
    digitalWrite(pin,LOW);
    pinMode(pin,INPUT);
}
发布了20 篇原创文章 · 获赞 6 · 访问量 7496

猜你喜欢

转载自blog.csdn.net/armcsdn/article/details/103294388
今日推荐