关于串口通信读取BL0942芯片电压电流的使用

概述:

  通过串口通信来获取BL0942芯片采集到的电压电流,采用的芯片为10引脚类型,电压采样为电阻采样,电流采样为互感器采样。

芯片功能特点:

  1. 两路独立的Sigma-Delta ADC,一路电流和一路电压。

  2. 电流有效值范围(10mA~35A)@1mohm  有功电能(1w~7700w)@1mohm

  3. 可测量电流电压有效值,快速电流有效值,有功功率,电流电压波形

  4. 批次出厂增益误差小于1%,外围元件满足一定条件下可以免校准

  5. 电流通道具备过流监控功能,监控阈值及响应时间可设置

  6. 电压/电流过零信号输出  内置波形寄存器,可输出波形数据用于负载类型分析

  7. 集成SPI(最快速率支持900KHz)/UART(4800-38400bps)通信方式

  8. 电源掉电监测,低于2.7V时,芯片进入复位状态

  9. 内置1.218V参考电压源  内置振荡电路,时钟约4MHz

  10. 芯片单工作电源3.3V,低功耗10mW(典型值)

 封装与管脚描述:

  采用的10引脚封装芯片

寄存器说明:

通过串口向BL0942发送指令,根据寄存器地址我们可以读取到相应数据。

 

特殊寄存器说明: 

电压采样电路及说明:

 电压采样使用的方法为电阻采样,由芯片管脚描述中所说VP为电压信号输入端,可以看到图中电压通道通过R2(390K*5)+R1(0.51K)电阻分压把交流220V电压降到mV级信号给VP管脚;根据提供的公式:

V = \frac{V_eff * V_ref * (R1 + R2)}{ 73989 * R1 * 1000}

其中,V_eff 表示电压有效值,V_ref 表示典型值1.218V。

我们就可以算出实际的电压值,不同个体芯片会有些许误差,可以通过自定义系数来校正。

下图为芯片应用指南的电阻电路图:

电流采样电路及说明: 

  电流采样使用的方法为电流互感器采样,由芯片管脚描述中所说IP,IN为电流模拟输入端;我们只需看图中IP1,IN1引脚。假设电流互感器CT1的变比为Rt=2000(2000:1),负载电阻R5(3.3欧),根据提供的公式:

I=\frac{I_eff*V_ref}{305978*(R5*1000)/Rt}

其中,I_eff 表示电流有效值,V_ref 表示典型值1.218V。

我们就可以算出实际电流值。

 下图为芯片应用指南的互感电路图:

串口通信说明: 

  该芯片有两种通信方式,SPI和串口通信,我使用的是串口通信方式。

  波特率配置:4800bps和9600bps通过硬件连接选择,19200bps和38400bps通过发送指令选择,我在这直接使用的4800bps。下图为波特率配置:

注意A2,A1为器件地址,即每个串口可以同时与4个芯片通信,默认为00,下图为写入时序:

读取时序:

 

获取电压,电流数据方式: 

  直接发送读取电压电流寄存器的指令,芯片会直接返回相应的原始值,我使用的另一种方法,通过发送读取全包指令,芯片会返回一系列数据,其中包括电压电流,并且数据有包头HEAD,方便代码逻辑编写。下图为全包数据格式:

代码实现: 

1.发送命令实现

//发送命令
uint32_t BL0942_ReadRegister1(uint8_t reg_addr) {
    uint8_t cmd = 0x58;
    uint8_t addr = reg_addr;
   
    //uint8_t checksum = ~((cmd + addr) & 0xFF);
    
    // 使用固定大小的数组
    uint8_t send_data[2];

    // 手动填充数组
    send_data[0] = cmd;
    send_data[1] = addr;
  

    // 发送读命令
    UartWrite1(send_data, sizeof(send_data));

}
void UartWrite1(unsigned char *data,int length)//串口1写数据   数据指针  数据长度
{
	unsigned int i=0;
	USART_ClearFlag(USART1,USART_FLAG_TC);
	for(i=0;i<length;i++)
	{
		USART_SendData(USART1,*(data++));
		while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
		{
			 __NOP(); 
		}
	}
    USART_ClearFlag(USART1,USART_FLAG_TC);
    
}

2.接收数据及处理 

void Date_Count1(u8 buf)//在串口中断中不断接收信息
{
    if(buf==0x55)//判断包头,确认无误继续接收
    {
        USART_rBuffer1[0] = buf;
		USART_RXD_Counter = 1;
    }
    else if((USART_RXD_Counter > 0) && (USART_RXD_Counter < 23))//接收全包数据
    {
        USART_rBuffer1[USART_RXD_Counter++] = buf;
    }
    else USART_RXD_Counter=0;
    if(USART_RXD_Counter==23)//和校验
    {
        int i;
        uint32_t v_rms_raw;
        uint32_t a_rms_raw;
        uint32_t p_rms_raw;
        uint8_t checksum;
        checksum=0x58;
        for ( i = 0; i < 22; i++) 
        {
            checksum += USART_rBuffer1[i];
        }
        checksum= checksum  & 0xFF;
        checksum= ~checksum;
        if(checksum==USART_rBuffer1[22])//和校验无误,数据处理
        {
            v_rms_raw= (USART_rBuffer1[6] << 16) | (USART_rBuffer1[5] << 8) | USART_rBuffer1[4]; 
            voltage_AC_IN = (v_rms_raw * 1.218*3.824) / 73989;//3.824=(R1+R2)/R1*1000
            a_rms_raw= (USART_rBuffer1[3] << 16) | (USART_rBuffer1[2] << 8) | USART_rBuffer1[1]; 
            current_OUT1 =  (a_rms_raw * 1.218) / 305978;
            current_OUT1 = current_OUT1/1.65;//1.65=(R5*1000)/Rt
            
        }
    }
    
}

3.主函数

int main(void)
 {	
    uint32_t current_rms ;    
    SystemInit();//系统初始化 
    SysTick_Init();
	SysTick_Config(36000);
	initio();
	initdat();
	uart1_init1(4800); 
    BL0942_Init();
    while(1)
	{   

        Date_Read++;
        if(Date_Read>1000)
        {
           BL0942_ReadRegister1(0xAA);
           del(600);
           printf("电压:%0.1f",voltage_AC_IN);
           printf("电流:%0.1f",current_OUT);
           Date_Read=0;
        }
	}	 
}

作者:柒樂葉

物联沃分享整理
物联沃-IOTWORD物联网 » 关于串口通信读取BL0942芯片电压电流的使用

发表回复