1.HT7017芯片介绍
1.1芯片简介
HT7017 是一颗带 UART 通讯接口的高精度单相多功能计量芯片。
芯片支持宽电压,工作电压范围是 3.0 ~5.5V。
工作晶振为 6MHz
1.2芯片特性
三路 19 bits Sigma-Delta ADC;
支持 8000:1 的动态范围;
比 5000:1 版本芯片更好的小信号精度表现
可以同时得到两路计量通道的有功功率、无功功率;
支持有功、无功、视在功率和有功电能脉冲输出;
能够同时得到三路 ADC 通道的有效值,及电压通道的频率;
支持 UART 通讯方式;
中断支持:过零中断,采样中断,电能脉冲中断,校表中断等;
NORMAL 全速运行时功耗<4mA;
电源监测功能
支持电压跌落(SAG)和峰值检测(PEAK)功能;
新增计量可靠性机制
支持锰铜掉火线检测功能
提供校表参数的 CRC 校验
提供 128 点的 ADC 波形缓存功能
芯片封装:SSOP 16
1.3.整体框图
1.4.引脚定义
2.NUC980编程
2.1.定义计量信息结构体
typedef struct
{
uint8_t State; //状态
uint32_t Totalelc; //电量值
uint32_t RawTotalelc; //寄存器电量值
uint32_t Vol; //电压值
uint32_t RawVol; //寄存器电压值
uint32_t Cur; //电流值
uint32_t RawCur; //寄存器电流值
uint32_t Kw; //功率
uint32_t RawKw; //寄存器功率
}ELMINFO;
2.2.定义计量参数寄存器
#define HEAD 0x6A
#define MPREG_SPLI1 0x00
#define MPREG_SPLI2 0x01
#define MPREG_SPLU 0x02
#define MPREG_IDC 0x03
#define MPREG_UDC 0x04
#define MPREG_RMSI1 0x06
#define MPREG_RMSI2 0x07
#define MPREG_RMSU 0x08
#define MPREG_FREQU 0x09
#define MPREG_POWERP1 0x0A
#define MPREG_POWERQ1 0x0B
#define MPREG_POWERS 0x0C
#define MPREG_ENERGYP 0x0D
#define MPREG_ENERGYQ 0x0E
#define MPREG_UDETCNT 0x0F
#define MPREG_POWERP2 0x10
#define MPREG_POWERQ2 0x11
#define MPREG_MAXUWAVE 0x12
#define MPREG_CRCCHECKSUM 0x15
#define MPREG_BACKUPDATA 0x16
#define MPREG_COMCHECKSUM 0x17
#define MPREG_SUMCHECKSUM 0x18
#define MPREG_EMUSR 0x19
#define MPREG_SYSSTA 0x1A
#define MPREG_CHIPID 0x1B
#define MPREG_DEVICEID 0x1C
2.3.定义电表较表参数寄存器
#define ECADR_EMUIE 0x30
#define ECADR_EMUIF 0x31
#define ECADR_WPREG 0x32
#define ECADR_SRST 0x33
#define ECADR_EMUCFG 0x40
#define ECADR_FREGCFG 0x41
#define ECADR_MODULEEN 0x42
#define ECADR_ANAEN 0x43
#define ECADR_IOCFG 0x45
#define ECADR_GP1 0x50
#define ECADR_GQ1 0x51
#define ECADR_GS1 0x52
#define ECADR_GP2 0x54
#define ECADR_GQ2 0x55
#define ECADR_GS2 0x56
#define ECADR_QPHSCAL 0x58
#define ECADR_ADCCON 0x59
#define ECADR_I2GAIN 0x5B
#define ECADR_I1OFF 0x5C
#define ECADR_I2OFF 0x5D
#define ECADR_UOFF 0x5E
#define ECADR_PQSTART 0x5F
#define ECADR_HFCONST 0x61
#define ECADR_DEC_SHIFT 0x64
#define ECADR_P1OFFSETH 0x65
#define ECADR_P2OFFSETH 0x66
#define ECADR_Q1OFFSETH 0x67
#define ECADR_Q2OFFSETH 0x68
#define ECADR_I1RMSOFFSET 0x69
#define ECADR_I2RMSOFFSET 0x6A
#define ECADR_URMSOFFSET 0x6B
#define ECADR_ZCROSSCURRENT 0x6C
#define ECADR_GPHS1 0x6D
#define ECADR_GPHS2 0x6E
#define ECADR_PFCNT 0x6F
#define ECADR_QFCNT 0x70
#define ECADR_ANACON 0x72
#define ECADR_SUMCHECKL 0x73
#define ECADR_SUMCHECKH 0x74
#define ECADR_MODECFG 0x75
#define ECADR_P1OFFSETL 0x76
#define ECADR_P2OFFSETL 0x77
#define ECADR_Q1OFFSETL 0x78
#define ECADR_Q2OFFSETL 0x79
#define ECADR_UPEAKLV1 0x7A
#define ECADR_USAGLV1 0x7B
#define ECADR_UCYLEN 0x7C
2.4. HT7017写地址数据
void HT7017_UART_Write(uint8_t address, uint16_t data)
{
uint8_t buf[256];
uint8_t checksum=0;
uint8_t dat8;
uint8_t tmplen;
uint16_t i;
buf[0]= HEAD;
buf[1]=address|0x80;
buf[2]=data>>8;
buf[3]=data &0xff;
for(i=0;i<4;i++)
{
checksum += buf
;
}
buf[4]=~checksum;
UartFlush(DEV_UART5);
UartWrite(DEV_UART5, buf, 5);
for (i=0;i<1000;i++){
rt_thread_mdelay(5);
tmplen=UartRead(DEV_UART5,&dat8,1);
if (tmplen != 0){
if (dat8 == 0x54){
break;
}
}
}
if(i == 1000){
ErrRecvtimes++;
if(ErrRecvTimes >= 20){
ElmInfo.State = 1;
ErrRecvTimes = 20;
}
}else{
ElmInfo.State = 0;
ErrRecvTimes = 0;
}
}
2.5. HT7017读地址数据
uint32_t HT7017_UART_Read(uint8_t address)
{
uint8_t buf[10];
uint8_t checksum=0;
uint8_t data[4];
uint16_t j;
uint32_t regdata=0;
uint8_t tmpbuf[64]={0};
uint16_t tmplen=0;
uint8_t rcvbuf[64]={0};
uint16_t rcvlen=0;
buf[0]=HEAD;
buf[1]=address&0x7F;//R+Address
UartFlush(DEV_UART5);
UartWrite(DEV_UART5, buf, 2);
for (j=0;j<1000;j++){
rt_thread_mdelay(5);
tmplen=UartRead(DEV_UART5, tmpbuf, 100);
if (tmplen != 0){
if (rcvlen+tmplen >= 64){
return 0;
}
memcpy(rcvbuf+rcvlen,tmpbuf,tmplen);
rcvlen += tmplen;
if(rcvlen >= 4){
memcpy(data,rcvbuf,4);
break;
}
}
}
if(j == 1000){
ErrRecvTimes++;
if(ErrRecvTimes >= 20){
ElmInfo.State = 1;
ErrRecvTimes = 20;
}
}else{
ElmInfo.State = 0;
ErrRecvTimes = 0;
}
checksum =~(buf[0]+buf[1]+data[0]+data[1]+data[2]);
regdata = 0xFFFFFFFF;
if(checksum == data[3])
regdata = ((data[0]<<16)|(data[1]<<8)|data[2]) ;
return regdata;
}
2.6.读取芯片电压
static uint32_t HT7017_ReadUrms(void)
{
static uint8_t i;
uint8_t j;
uint32_t TotalVol = 0;
uint32_t Temp;
static uint32_t rawvol[5];
Temp = HT7017_UART_Read(MPREG_RMSU);
if( Temp != 0xFFFFFFFF ){
rawvol[ i % 5 ] = Temp;
i++;
if(i == 5)
i = 0;
for(j = 0; j < 5; j++ ){
TotalVol += rawvol[j];
}
ElmInfo.RawVol = TotalVol / 5;
ElmInfo.Vol = ElmInfo.RawVol / ParaGetVolFactor();
return ElmInfo.RawVol;
}
return ElmInfo.RawVol;
}
2.7.读取芯片电流
static uint32_t HT7017_ReadI1rms(void)
{
static uint32_t rawcur[5];
static uint8_t i;
uint8_t j;
uint32_t TotalCur = 0;
uint32_t Temp;
Temp = HT7017_UART_Read(MPREG_RMSI1);
if( Temp != 0xFFFFFFFF ){
rawcur[ i % 5 ] = Temp;
i++;
if(i == 5)
i = 0;
for(j = 0; j < 5; j++ ){
TotalCur += rawcur[j];
}
ElmInfo.RawCur = TotalCur / 5;
ElmInfo.Cur = ElmInfo.RawCur /ParaGetCurFactor();
return ElmInfo.RawCur;
}
return ElmInfo.RawCur;
}
2.8.读取芯片功率
uint32_t HT7017_ReadPower(void)
{
ElmInfo.RawKw = HT7017_UART_Read(MPREG_POWERP1);
ElmInfo.Kw = ElmInfo.RawKw;
return ElmInfo.RawKw;
}
2.9.读取芯片电量
uint32_t HT7017_ReadEnergp(void)
{
uint32_t Temp = HT7017_UART_Read(MPREG_ENERGYP);
if(Temp != 0xFFFFFFFF){
ElmInfo.RawTotalelc = Temp;
}
return ElmInfo.RawTotalelc;
}
3.0.HT7017初始化
static void ElmInit(void)
{
HT7017_UART_Write(ECADR_SRST, 0x55);
rt_thread_mdelay(20);
HT7017_UART_Write(ECADR_WPREG, 0xA6);
rt_thread_mdelay(20);
HT7017_UART_Write(ECADR_HFCONST, 0xA6);
rt_thread_mdelay(20);
HT7017_UART_Write(ECADR_ADCCON, 0x00);
rt_thread_mdelay(20);
}
3.1.0.创建NUC980线程
static rt_thread_t meterid = RT_NULL;
#define THREAD_PRIORITY 20
#define THREAD_STACK_SIZE 512
#define THREAD_TIMESLICE 5
/* 线程1的入口函数 */
static void merter_entry(void * param)
{
rt_kprintf("meterthread started!:%d
");
ElmInit();
while(1)
{
HT7017_ReadUrms();
rt_thread_mdelay(500);
HT7017_ReadI1rms();
rt_thread_mdelay(500);
HT7017_ReadEnergp();
rt_thread_mdelay(500);
}
}
int meter_sample(void)
{
meterid= rt_thread_create("meter",
merter_entry,
RT_NULL,
THREAD_STACK_SIZE,
THREAD_PRIORITY,
THREAD_TIMESLICE);
if(meterid!= RT_NULL)
{
rt_thread_startup(meterid);
}
return 0;
}
3.2.0.导入 msh 命令列表中
MSH_CMD_EXPORT(meter_sample,meter thread sample);
原作者:Wogee