利用BL0942计量芯片获取精准计量数据

目录

  • 概述
  • 主要特点
  • 系统框图
  • 封装与管脚描述
  • 大致寄存器说明
  • 硬件实现和计量数据转换公式
  • 通讯接口-SPI
  • 代码实现
  • 概述

    BL0942 是一颗内置时钟免校准电能计量芯片。
    BL0942 能够测量电流、电压有效值、有功功率、有功电能量等参数。

    主要特点

    1. 两路独立的 Sigma-Delta ADC,一路电流和一路电压
    2. 电流有效值范围(10mA~30A)@1mohm
    3. 有功电能(1w~6600w)@1mohm@220V
    4. 可输出电流、电压有效值,快速电流有效值,有功功率
    5. 批次出厂增益误差小于 1%,外围元件满足一定条件下可以免校准
    6. SPI(最快速率支持 900KHz)/UART(4800-38400bps)通信方式(TSSOP14L 封装支持最多 4 片级联
      Uart 通信)
    7. 电源掉电监测,低于 2.7V 时,芯片进入复位状态
    8. 内置 1.218V 参考电压源
    9. 芯片单工作电源 3.3V,低功耗 10mW(典型值)

    系统框图

    封装与管脚描述


    大致寄存器说明


    硬件实现和计量数据转换公式

    通讯接口-SPI

    1. 工作在从模式
    2. 半双工通讯,通讯率可配,最大通讯速率 900Khz
    3. 固定一种时钟极性/相位(CPOL=0,CPHA=1)
    4. 帧结构:
      在通信模式下,先发送 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, &regData))
    		Meter_Rece_Voltage = regData*6.612/100000;
    	if(BL09_Read_Reg(R_I_RMS, &regData))
    		Meter_Rece_Current = regData*1.206/1000000;			
    	if(BL09_Read_Reg(R_CF_CNT, &regData))
    	{
    		tampElec = regData*5.947/100000;					
    		Meter_Rece_Elec += tampElec;
    	}	
    }
    
    物联沃分享整理
    物联沃-IOTWORD物联网 » 利用BL0942计量芯片获取精准计量数据

    发表评论