利用BL0942计量芯片获取精准计量数据
目录
概述
BL0942 是一颗内置时钟免校准电能计量芯片。
BL0942 能够测量电流、电压有效值、有功功率、有功电能量等参数。
主要特点
- 两路独立的 Sigma-Delta ADC,一路电流和一路电压
- 电流有效值范围(10mA~30A)@1mohm
- 有功电能(1w~6600w)@1mohm@220V
- 可输出电流、电压有效值,快速电流有效值,有功功率
- 批次出厂增益误差小于 1%,外围元件满足一定条件下可以免校准
- SPI(最快速率支持 900KHz)/UART(4800-38400bps)通信方式(TSSOP14L 封装支持最多 4 片级联
Uart 通信) - 电源掉电监测,低于 2.7V 时,芯片进入复位状态
- 内置 1.218V 参考电压源
- 芯片单工作电源 3.3V,低功耗 10mW(典型值)
系统框图
封装与管脚描述
大致寄存器说明
硬件实现和计量数据转换公式
通讯接口-SPI
- 工作在从模式
- 半双工通讯,通讯率可配,最大通讯速率 900Khz
- 固定一种时钟极性/相位(CPOL=0,CPHA=1)
- 帧结构:
在通信模式下,先发送 8bit 识别字节(0x58) 或(0xA8),(0x58)是读操作识别字节,(0xA8)是写操作
识别字节,然后再发送寄存器地址字节,决定访问寄存器的地址(请参见 BL0942 寄存器列表)。
下图分别示出读出和写入操作的数据传送顺序。一帧数据传送完成,BL0942 重新进入通信模式。每次读/写操作所需的 SCLK 的脉冲个数均为 48 位。
代码实现
1.SPI通信–HAL库发送接收接口
SPI 使用硬件SPI软控制CS
//延时函数,一个计数1US
void Bl09_Delay(u8 count);
//发送:
HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout);
//接收:
HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size, uint32_t Timeout);
2.
#define R_I_RMS 0x03 //电流有效值寄存器,无符号
#define R_V_RMS 0x04 //电压有效值寄存器,无符号
#define R_WATT 0x06 //有功功率寄存器,有符号
#define R_CF_CNT 0x07 //有功电能脉冲计数寄存器,无符号
#define R_MODE 0x19 //用户模式选择寄存器
#define R_SOFT_RESET 0x1c //写入 0x5A5A5A 时,用户区寄存器复位
#define R_USR_WRPROT 0x1D //用户写保护设置寄存器
volatile float Meter_Rece_Voltage = 0;
volatile float Meter_Rece_Current = 0;
volatile float Meter_Rece_Elec = 0;
/*******************************************************************************
功能描述:对BL0942的寄存器写
输入参数: addr:寄存器地址
temp:寄存器值
*******************************************************************************/
void BL09_Write_Reg(uint8 addr, uint32 temp)
{
u8 sendData[6] = {0};
sendData[0] = 0XA8; //写操作识别字节
sendData[1] = addr; //地址
sendData[2] = (u8)((temp&0x00ff0000)>>16);
sendData[3] = (u8)((temp&0x0000ff00)>>8);
sendData[4] = (u8)((temp&0x000000ff));
//检验和数据
sendData[5] = ((sendData[0]+sendData[1]+sendData[2]+sendData[3]+sendData[4]) & 0xff);
sendData[5] = ~sendData[5];
//拉高CS
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_SET);
Bl09_Delay(10);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET);
Bl09_Delay(5);
HAL_SPI_Transmit(&hspi2, sendData, 6 ,1000);
Bl09_Delay(5);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_SET);
}
/*******************************************************************************
功能描述:对BL0942的寄存器读
输入参数: addr:寄存器地址
data:
返回值: 0:读取失败
1:读取成功
*******************************************************************************/
uint8 BL09_Read_Reg(uint8 addr, uint32 *data)
{
u8 sendData[6] = {0};
u8 recvData[6] = {0};
u8 checkSum;
sendData[0] = 0x58; //读操作识别字节
sendData[1] = addr; //寄存器地址
//拉高CS
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_SET);
Bl09_Delay(10);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET);
Bl09_Delay(5);
HAL_SPI_TransmitReceive(&hspi2, sendData, recvData, 6, 1000);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_SET);
//校验和计算
checkSum = (sendData[0]+sendData[1]+recvData[2]+recvData[3]+recvData[4]) & 0xff;
checkSum = ~checkSum;
if(checkSum != recvData[5])
return 0;
*data = (recvData[2]<<16) + (recvData[3]<<8) + recvData[4];
return 1;
}
//BL0942初始化
void BL09_Init(void)
{
u32 writeData = 0;
u32 readData = 0;
OS_ERR err;
writeData = 0x5a5a5a; //用户去寄存器复位,使用
BL09_Write_Reg(R_SOFT_RESET, writeData);
Bl09_Delay(250);Bl09_Delay(250);
while(1)
{
writeData = 0x55; //关闭写保护
BL09_Write_Reg(R_USR_WRPROT, writeData);
writeData = 0;
if(BL09_Read_Reg(R_MODE, &readData))
{
writeData = (readData|(0x01<<6));
BL09_Write_Reg(R_MODE, writeData);
}
if(BL09_Read_Reg(R_MODE, &readData))
{
if(readData == writeData)
break;
}
OSTimeDly ((OS_TICK )100,
(OS_OPT )OS_OPT_TIME_DLY,
(OS_ERR *)&err);
}
writeData = 0xaa; //开启写保护
BL09_Write_Reg(R_USR_WRPROT, writeData);
}
//BLO942电表数据采集
//这里用的是CT1=1000的电流互感器
void BL09_Meter_Scan(void)
{
float tampElec = 0;
if(BL09_Read_Reg(R_V_RMS, ®Data))
Meter_Rece_Voltage = regData*6.612/100000;
if(BL09_Read_Reg(R_I_RMS, ®Data))
Meter_Rece_Current = regData*1.206/1000000;
if(BL09_Read_Reg(R_CF_CNT, ®Data))
{
tampElec = regData*5.947/100000;
Meter_Rece_Elec += tampElec;
}
}