用STM32进行交流电流电压的测量监控

本文介绍通过STM32和BL0942进行交流电流的测量和监控
能脉冲。
本文介绍如何通过STM32 以串口模式对BL0942进行配置读取,同时通过CF1监控过流,不多废话,直接上代码
**

1.宏定义

**


#define Addr_I_WAVE			0x01		 //电流通道波形			*
#define Addr_V_WAVE			0x02		//电压通道波形*
#define Addr_I_RMS			0x03		//电流有效值
#define Addr_V_RMS			0x04		//电压有效值
#define Addr_I_FAST_RMS		0x05		//电流快速有效值*
#define Addr_WATT			0x06		//有功功率
#define Addr_CF_CNT			0x07		//有功电能脉冲计数
#define	Addr_FREQ			0x08		//工频频率
#define Addr_STATUS			0x09		//状态
#define Addr_VERSION		0x0F		//版本
//用户操作寄存器
#define Addr_I_CHOS			0x11		//电流通道直流偏置校正
#define Addr_I_RMSOS		0x12		//电流通道有效值小信号校正
#define Addr_WA_CREEP		0x14		//有功功率防潜阈值
#define Addr_FAST_RMS_TH	0x15		//
#define Addr_FAST_RMS_CYC	0x16
#define Addr_FREQ_CYC		0x17
#define Addr_MASK			0x18
#define Addr_MODE			0x19
#define Addr_GAIN_CR		0x1A
#define Addr_SOFT_RESET		0x1C		//软复位
#define Addr_WRPROT			0x1D		//用户写保护设置

//注意 BL0940的读命令字节固定为0x58+ICAddr,写命令字节固定为0xA8+ICAddr;SOP10封装芯片的IC_Addr地址固定为0
//     BL0942 TSSOP14封装带地址选择管脚,需根据A1~A2地址选择管脚的电平配置命令字节,可以进行多机并联通信     
#define BL0942_Addr_R           0x58
#define BL0942_Addr_w           0xA8

//出厂校准芯片,增益控制1%以内,外围器件精度控制1%以内,采用同一系数,不用 EEPROM保存参数
// 电流采用1毫欧电阻采样,电压采用390K*5+0.51K进行分压,实际测试发现电阻存在偏差,进行微调
//BL0942评估版,立创直接贴片合金电阻(台湾厚声MS121WF100NT4E  ),实际测量比1毫欧偏小,约0.93毫欧					

#define Power_K			5798;//580;//		// 3537*1毫欧*0.51K*1000/(1.218*1.218)/(390K*5+0.51K)	功率转换系数
#define Current_K		23362;//233628;//23362	        // 305978*1毫欧/1.218																					电流转换系数
#define Voltage_K		15883; 		// 73989*0.51K*1000/1.218/(390K*5+0.51K)										电压转换系数		
#define Energy_K		4976;		// 3600000*Power_K/16384/256  电能转换系数,电能脉冲计数,对应于1度电的脉冲计数

//采用美隆0.001毫欧贴片合金电阻,实际比1毫欧偏大,约1.023毫欧
/*
#define Power_K			6378;	//	功率转换系数
#define Current_K		25699;	//	电流转换系数
#define Voltage_K		15883; 	//	电压转换系数		
#define Energy_K		5474;   //	
*/

2.寄存器读写驱动

/**
  * @brief Read Bl0942 register.
  * @note  the reslt will be stored in BL0942_Elect,the converted I/V Parameter will be stored in BL0942_Elect
  * @param ICAddr       Uart address of BL0942 .
  * @param Reg          Target register to read data from.
  * @param Timeout      Timeout duration.
  * @retval Flag_BL0942_R
  */
uint8_t BL0942_Uart1_R(uint8_t ICAddr,uint8_t Reg,uint32_t Timeout)
{
  uint8_t tmp_2,aTxBuffer[2] = {0},aRxBuffer[4] = {0};
  FourBytes_Type  tmp_D;
  tmp_2=huart1.Instance->RDR;//???  
  aTxBuffer[0]= ICAddr;
  aTxBuffer[1]= Reg;
  if(HAL_UART_Transmit(&huart1, (uint8_t*)aTxBuffer, 2, Timeout)!= HAL_OK)
  {
    Error_Handler(); 
  }
  if(HAL_UART_Receive(&huart1, (uint8_t *)aRxBuffer, 4, Timeout) != HAL_OK)
  {
    Error_Handler();  
  }
  tmp_D.uByte[0]=aRxBuffer[0];
  tmp_D.uByte[1]=aRxBuffer[1];
  tmp_D.uByte[2]=aRxBuffer[2];
  tmp_2 = aTxBuffer[0] + aTxBuffer[1] + aRxBuffer[0] + aRxBuffer[1] + aRxBuffer[2];
  tmp_2=~tmp_2;		//计算的校验和字节 
  if (aRxBuffer[3]==tmp_2)
  {
    Flag_BL0942_R = 1;
    switch (Reg)
    {
      case Addr_I_RMS:
           tmp_D.uLongs=tmp_D.uLongs*100/Current_K;
           BL0942_Elect.Current_Value=tmp_D.uLongs;
      break;              
      case Addr_V_RMS:	
           tmp_D.uLongs=tmp_D.uLongs*100/Voltage_K;
           BL0942_Elect.Voltage_Value=tmp_D.uLongs;                
      break;
      case Addr_WATT:	
           tmp_D.uLongs=tmp_D.uLongs*100/Power_K;
           BL0942_Elect.Power_Value=tmp_D.uLongs;
      break;  
      case Addr_FREQ:	
           tmp_D.uLongs=100000000/tmp_D.uLongs;		//转换为实际频率
           BL0942_Elect.Freq=tmp_D.uLongs;
      break;   
      case Addr_I_FAST_RMS:	                        //I_FAST_RMS
           tmp_D.uLongs=tmp_D.uLongs*100/Current_K;
           BL0942_Elect.F_Current_Value=tmp_D.uLongs;
      break;  
      case Addr_CF_CNT:	                                //电能脉冲计数	
           if (tmp_D.uLongs>=BL0942_Elect.Fir_CF_CNT)		
           {
             BL0942_Elect.Mid_CF_CNT+=(tmp_D.uLongs-BL0942_Elect.Fir_CF_CNT);
           }
           else		//电能脉冲计数累积满出现溢出情况
           {
             BL0942_Elect.Mid_CF_CNT+=(tmp_D.uLongs+(0xFFFFFF-BL0942_Elect.Fir_CF_CNT));
           }
           BL0942_Elect.Fir_CF_CNT=tmp_D.uLongs;
           //判断是否累积超过1度电的脉冲数,需要确保读取时间间隔内的电量不超过1度电,否则用整除
           tmp_D.uLongs=Energy_K;
           if (BL0942_Elect.Mid_CF_CNT>=tmp_D.uLongs)
           {
             BL0942_Elect.Energy_kwh++;
             BL0942_Elect.Mid_CF_CNT-=Energy_K;
           }
      break;                
      case Addr_WA_CREEP:
           if( tmp_D.uByte[0] == 11)
            {
              //communication success between WB55 and BL0942
            }
            else
            {
              //communication fail between WB55 and BL0942
            }
      break;
      case Addr_MASK:
           BL0942_Uart_Buffer[2] = tmp_D.uByte[0] |0x01;
      break;
      case Addr_MODE:
           BL0942_Uart_Buffer[2] = tmp_D.uByte[0];
           BL0942_Uart_Buffer[3] = tmp_D.uByte[1] | 0x03;                 
      break;              
      case Addr_FAST_RMS_TH:              
      break;              
      default:
      break;
    }                    		
  }
  else
  {
    Flag_BL0942_R = 0;
  }
  return Flag_BL0942_R;
}

/**
  * @brief Write  Bl0942 user configuraetion register.
  * @note  
  * @param PData[0]             Uart address of BL0942 .
  * @param PData[1]             Target register to be written.
  * @param PData[2...4]         the config data.
  * @param PData[5]             CHSUM.
  * @param Timeout              Timeout duration.
  * @retval 
  */

void BL0942_Uart1_W(uint8_t *pData,uint32_t Timeout)
{
  //send ICAddr & Reg address
  if(HAL_UART_Transmit(&huart1, (uint8_t*)pData, 6, Timeout)!= HAL_OK)
  {
    Error_Handler(); 
  }  
}

void USART1_BaudRate_Reconfig(uint32_t baud)
{
  huart1.Instance = USART1;
  huart1.Init.BaudRate = baud;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_8;
  huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
  huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
}

}

3.调用驱动进行串口波特率、过流阀值、CF1功能配置

/enable Reg modification
    BL0942_Uart_Buffer[1] = Addr_WRPROT;
    BL0942_Uart_Buffer[2] = 0x55;
    BL0942_Uart_Buffer[3] = 0x00;
    BL0942_Uart_Buffer[4] = 0x00;
    BL0942_Uart_Buffer[5] = ~( BL0942_Uart_Buffer[0] + BL0942_Uart_Buffer[1] + BL0942_Uart_Buffer[2] + BL0942_Uart_Buffer[3] + BL0942_Uart_Buffer[4]);
    BL0942_Uart1_W((uint8_t*)BL0942_Uart_Buffer,TIMEOUT); 
    //modify the Baudrate to 38400
    BL0942_Uart1_R(BL0942_Addr_R,Addr_MODE,TIMEOUT); //read the Mode_Reg
    BL0942_Uart_Buffer[1] = Addr_MODE;
    BL0942_Uart_Buffer[4] = 0x00;
    BL0942_Uart_Buffer[5] = ~( BL0942_Uart_Buffer[0] + BL0942_Uart_Buffer[1] + BL0942_Uart_Buffer[2] + BL0942_Uart_Buffer[3] + BL0942_Uart_Buffer[4]);
    BL0942_Uart1_W((uint8_t*)BL0942_Uart_Buffer,TIMEOUT);
    HAL_Delay(1);
    USART1_BaudRate_Reconfig(38400); //set the MCU USART1 BAUDRATE to 38400
    //modify the target reg  
    BL0942_Uart_Buffer[1] = Addr_FAST_RMS_TH;
    BL0942_Uart_Buffer[2] = 0x21;
    BL0942_Uart_Buffer[3] = 0x02;
    BL0942_Uart_Buffer[4] = 0x00;
    BL0942_Uart_Buffer[5] = ~( BL0942_Uart_Buffer[0] + BL0942_Uart_Buffer[1] + BL0942_Uart_Buffer[2] + BL0942_Uart_Buffer[3] + BL0942_Uart_Buffer[4]);
    BL0942_Uart1_W((uint8_t*)BL0942_Uart_Buffer,TIMEOUT); //set the overcurrent point: 0x221:1.5A
    BL0942_Uart1_R(BL0942_Addr_R,Addr_MASK,TIMEOUT);  //Read the OT_FUNX_Reg 
    BL0942_Uart_Buffer[1] = Addr_MASK;  
    BL0942_Uart_Buffer[3] = 0x00;
    BL0942_Uart_Buffer[4] = 0x00;
    BL0942_Uart_Buffer[5] = ~( BL0942_Uart_Buffer[0] + BL0942_Uart_Buffer[1] + BL0942_Uart_Buffer[2] + BL0942_Uart_Buffer[3] + BL0942_Uart_Buffer[4]);
    BL0942_Uart1_W((uint8_t*)BL0942_Uart_Buffer,TIMEOUT); //set the CF1 out to overcurrent indicator
    //lock 
    BL0942_Uart_Buffer[1] = Addr_WRPROT;
    BL0942_Uart_Buffer[2] = 0x00;
    BL0942_Uart_Buffer[3] = 0x00;
    BL0942_Uart_Buffer[4] = 0x00;
    BL0942_Uart_Buffer[5] = ~( BL0942_Uart_Buffer[0] + BL0942_Uart_Buffer[1] + BL0942_Uart_Buffer[2] + BL0942_Uart_Buffer[3] + BL0942_Uart_Buffer[4]);
    BL0942_Uart1_W((uint8_t*)BL0942_Uart_Buffer,TIMEOUT); 

4.读取电流有效值及验证寄存器配置值,

    BL0942_Uart1_R(BL0942_Addr_R,Addr_FAST_RMS_TH,TIMEOUT); 
    BL0942_Uart1_R(BL0942_Addr_R,Addr_MASK,TIMEOUT);
    BL0942_Uart1_R(BL0942_Addr_R,Addr_I_RMS,TIMEOUT);
**注意:
        1. BL0942自身不带保存功能,每次上电都要重新配置
        2. 串口波特率4800 和9600是通过外部条线的方式配置,19200 和38400则需要统通MODE寄存器进行配置**
  • 3
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: STM32功率计是一种基于电压电流检测的功率计程序,它能够检测电流电压和频率等电力参数。首先,STM32功率计通过接收电路获取电流电压信号,然后进行数字化处理。接着,程序对数字化的电流电压信号进行计算和分析,最后输出电力参数。这个过程中,程序需要具有高精度、高可靠性和稳定性等特点。 STM32功率计在电力系统中应用广泛,它能够精确地测量电力参数,从而保障电力系统的安全和稳定运行。例如,它可以在制造业中使用来监测机器的能耗情况,帮助企业控制成本和提高生产效率。此外,它还可以在智能家居中使用来监控电器的能耗情况,帮助用户节约用电。 总之,STM32功率计是一种非常有用的电力仪器,具有多种应用场景。它可以检测电流电压频率,保障电力系统的安全和稳定运行,同时也可以帮助企业和用户控制用电成本,提高生产效率和生活品质。 ### 回答2: STM32功率计是一种基于电压电流检测的功率计程序,主要用于检测电路中的电流电压以及频率等参数。具体来说,该程序利用STM32芯片作为控制核心,通过采集电路中的电压信号和电流信号,计算得到电路中的功率值。 在使用STM32功率计进行测试时,可通过输入电路参数和采集的电压电流信号,进入程序后,经过处理后能够得到电路的功率值。此外,该程序还可实时控制、监测电路的电流电压、频率等参数,为电路测试、调试提供了极大的便利。 相较于传统的功率计,STM32功率计有以下优势: 1.高精度:该程序利用高性能的STM32芯片进行数据采集和处理,能够实现更高的测量精度和稳定性。 2.快速响应:STM32芯片具有快速响应的特点,能够迅速对测试数据进行处理和输出,提高测试效率。 3.易于控制:基于STM32芯片的功率计程序可以通过简单的代码控制实现电路的电流电压、频率等参数的检测与调整,操作简便。 综上所述,STM32功率计是一种高性能、高精度的电路测试工具,可以有效地用来检测电路中的电流电压、频率等参数,是现代电路测试与调试的重要工具。 ### 回答3: STM32功率计是一种基于电压电流检测的功率计程序,适用于检测电流电压和频率。它是一种高效、精确的电能检测设备,可以广泛应用于家庭、商业和工业领域。 STM32功率计的主要原理是通过感应电路对电流电压进行采样,然后将采样值转换成数字信号,进而通过程序计算电流电压和功率等参数。该设备采用高精度电流检测芯片和AD转换器,可以精确地测量电流电压,并计算出功率和能等参数。 STM32功率计具有以下特点:可以实时监测电力负荷,精确测量电能参数;支持多个电器同时检测,具有高度的智能化;具有多种检测方式,包括手动检测和自动检测等;支持电压电流、功率、能等参数的实时显示。 总之,STM32功率计是一种高效、精确、实用的电能检测设备,可以广泛应用于各种电力检测场合,为用户提供高品质的电力检测服务。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值