[其他ST产品] 用STM32进行交流电流电压的测量监控

[复制链接]
2291|19
 楼主| 发给她更好fh 发表于 2023-8-27 17:05 | 显示全部楼层 |阅读模式
本文介绍通过STM32和BL0942进行交流电流的测量和监控
能脉冲。
本文介绍如何通过STM32 以串口模式对BL0942进行配置读取,同时通过CF1监控过流,不多废话,直接上代码
 楼主| 发给她更好fh 发表于 2023-8-27 17:05 | 显示全部楼层
宏定义

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

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

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

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

  34. //采用美隆0.001毫欧贴片合金电阻,实际比1毫欧偏大,约1.023毫欧
  35. /*
  36. #define Power_K                        6378;        //        功率转换系数
  37. #define Current_K                25699;        //        电流转换系数
  38. #define Voltage_K                15883;         //        电压转换系数               
  39. #define Energy_K                5474;   //       
  40. */
 楼主| 发给她更好fh 发表于 2023-8-27 17:06 | 显示全部楼层
寄存器读写驱动
  1. /**
  2.   * [url=home.php?mod=space&uid=247401]@brief[/url] Read Bl0942 register.
  3.   * [url=home.php?mod=space&uid=536309]@NOTE[/url]  the reslt will be stored in BL0942_Elect,the converted I/V Parameter will be stored in BL0942_Elect
  4.   * @param ICAddr       Uart address of BL0942 .
  5.   * @param Reg          Target register to read data from.
  6.   * @param Timeout      Timeout duration.
  7.   * @retval Flag_BL0942_R
  8.   */
  9. uint8_t BL0942_Uart1_R(uint8_t ICAddr,uint8_t Reg,uint32_t Timeout)
  10. {
  11.   uint8_t tmp_2,aTxBuffer[2] = {0},aRxBuffer[4] = {0};
  12.   FourBytes_Type  tmp_D;
  13.   tmp_2=huart1.Instance->RDR;//???  
  14.   aTxBuffer[0]= ICAddr;
  15.   aTxBuffer[1]= Reg;
  16.   if(HAL_UART_Transmit(&huart1, (uint8_t*)aTxBuffer, 2, Timeout)!= HAL_OK)
  17.   {
  18.     Error_Handler();
  19.   }
  20.   if(HAL_UART_Receive(&huart1, (uint8_t *)aRxBuffer, 4, Timeout) != HAL_OK)
  21.   {
  22.     Error_Handler();  
  23.   }
  24.   tmp_D.uByte[0]=aRxBuffer[0];
  25.   tmp_D.uByte[1]=aRxBuffer[1];
  26.   tmp_D.uByte[2]=aRxBuffer[2];
  27.   tmp_2 = aTxBuffer[0] + aTxBuffer[1] + aRxBuffer[0] + aRxBuffer[1] + aRxBuffer[2];
  28.   tmp_2=~tmp_2;                //计算的校验和字节
  29.   if (aRxBuffer[3]==tmp_2)
  30.   {
  31.     Flag_BL0942_R = 1;
  32.     switch (Reg)
  33.     {
  34.       case Addr_I_RMS:
  35.            tmp_D.uLongs=tmp_D.uLongs*100/Current_K;
  36.            BL0942_Elect.Current_Value=tmp_D.uLongs;
  37.       break;              
  38.       case Addr_V_RMS:       
  39.            tmp_D.uLongs=tmp_D.uLongs*100/Voltage_K;
  40.            BL0942_Elect.Voltage_Value=tmp_D.uLongs;               
  41.       break;
  42.       case Addr_WATT:       
  43.            tmp_D.uLongs=tmp_D.uLongs*100/Power_K;
  44.            BL0942_Elect.Power_Value=tmp_D.uLongs;
  45.       break;  
  46.       case Addr_FREQ:       
  47.            tmp_D.uLongs=100000000/tmp_D.uLongs;                //转换为实际频率
  48.            BL0942_Elect.Freq=tmp_D.uLongs;
  49.       break;   
  50.       case Addr_I_FAST_RMS:                                //I_FAST_RMS
  51.            tmp_D.uLongs=tmp_D.uLongs*100/Current_K;
  52.            BL0942_Elect.F_Current_Value=tmp_D.uLongs;
  53.       break;  
  54.       case Addr_CF_CNT:                                        //电能脉冲计数       
  55.            if (tmp_D.uLongs>=BL0942_Elect.Fir_CF_CNT)               
  56.            {
  57.              BL0942_Elect.Mid_CF_CNT+=(tmp_D.uLongs-BL0942_Elect.Fir_CF_CNT);
  58.            }
  59.            else                //电能脉冲计数累积满出现溢出情况
  60.            {
  61.              BL0942_Elect.Mid_CF_CNT+=(tmp_D.uLongs+(0xFFFFFF-BL0942_Elect.Fir_CF_CNT));
  62.            }
  63.            BL0942_Elect.Fir_CF_CNT=tmp_D.uLongs;
  64.            //判断是否累积超过1度电的脉冲数,需要确保读取时间间隔内的电量不超过1度电,否则用整除
  65.            tmp_D.uLongs=Energy_K;
  66.            if (BL0942_Elect.Mid_CF_CNT>=tmp_D.uLongs)
  67.            {
  68.              BL0942_Elect.Energy_kwh++;
  69.              BL0942_Elect.Mid_CF_CNT-=Energy_K;
  70.            }
  71.       break;               
  72.       case Addr_WA_CREEP:
  73.            if( tmp_D.uByte[0] == 11)
  74.             {
  75.               //communication success between WB55 and BL0942
  76.             }
  77.             else
  78.             {
  79.               //communication fail between WB55 and BL0942
  80.             }
  81.       break;
  82.       case Addr_MASK:
  83.            BL0942_Uart_Buffer[2] = tmp_D.uByte[0] |0x01;
  84.       break;
  85.       case Addr_MODE:
  86.            BL0942_Uart_Buffer[2] = tmp_D.uByte[0];
  87.            BL0942_Uart_Buffer[3] = tmp_D.uByte[1] | 0x03;                 
  88.       break;              
  89.       case Addr_FAST_RMS_TH:              
  90.       break;              
  91.       default:
  92.       break;
  93.     }                                   
  94.   }
  95.   else
  96.   {
  97.     Flag_BL0942_R = 0;
  98.   }
  99.   return Flag_BL0942_R;
  100. }

  101. /**
  102.   * @brief Write  Bl0942 user configuraetion register.
  103.   * @note  
  104.   * @param PData[0]             Uart address of BL0942 .
  105.   * @param PData[1]             Target register to be written.
  106.   * @param PData[2...4]         the config data.
  107.   * @param PData[5]             CHSUM.
  108.   * @param Timeout              Timeout duration.
  109.   * @retval
  110.   */

  111. void BL0942_Uart1_W(uint8_t *pData,uint32_t Timeout)
  112. {
  113.   //send ICAddr & Reg address
  114.   if(HAL_UART_Transmit(&huart1, (uint8_t*)pData, 6, Timeout)!= HAL_OK)
  115.   {
  116.     Error_Handler();
  117.   }  
  118. }

  119. void USART1_BaudRate_Reconfig(uint32_t baud)
  120. {
  121.   huart1.Instance = USART1;
  122.   huart1.Init.BaudRate = baud;
  123.   huart1.Init.WordLength = UART_WORDLENGTH_8B;
  124.   huart1.Init.StopBits = UART_STOPBITS_1;
  125.   huart1.Init.Parity = UART_PARITY_NONE;
  126.   huart1.Init.Mode = UART_MODE_TX_RX;
  127.   huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  128.   huart1.Init.OverSampling = UART_OVERSAMPLING_8;
  129.   huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  130.   huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
  131.   huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  132.   if (HAL_UART_Init(&huart1) != HAL_OK)
  133.   {
  134.     Error_Handler();
  135.   }
  136. }

  137. }
 楼主| 发给她更好fh 发表于 2023-8-27 17:06 | 显示全部楼层
调用驱动进行串口波特率、过流阀值、CF1功能配置
  1. /enable Reg modification
  2.     BL0942_Uart_Buffer[1] = Addr_WRPROT;
  3.     BL0942_Uart_Buffer[2] = 0x55;
  4.     BL0942_Uart_Buffer[3] = 0x00;
  5.     BL0942_Uart_Buffer[4] = 0x00;
  6.     BL0942_Uart_Buffer[5] = ~( BL0942_Uart_Buffer[0] + BL0942_Uart_Buffer[1] + BL0942_Uart_Buffer[2] + BL0942_Uart_Buffer[3] + BL0942_Uart_Buffer[4]);
  7.     BL0942_Uart1_W((uint8_t*)BL0942_Uart_Buffer,TIMEOUT);
  8.     //modify the Baudrate to 38400
  9.     BL0942_Uart1_R(BL0942_Addr_R,Addr_MODE,TIMEOUT); //read the Mode_Reg
  10.     BL0942_Uart_Buffer[1] = Addr_MODE;
  11.     BL0942_Uart_Buffer[4] = 0x00;
  12.     BL0942_Uart_Buffer[5] = ~( BL0942_Uart_Buffer[0] + BL0942_Uart_Buffer[1] + BL0942_Uart_Buffer[2] + BL0942_Uart_Buffer[3] + BL0942_Uart_Buffer[4]);
  13.     BL0942_Uart1_W((uint8_t*)BL0942_Uart_Buffer,TIMEOUT);
  14.     HAL_Delay(1);
  15.     USART1_BaudRate_Reconfig(38400); //set the MCU USART1 BAUDRATE to 38400
  16.     //modify the target reg  
  17.     BL0942_Uart_Buffer[1] = Addr_FAST_RMS_TH;
  18.     BL0942_Uart_Buffer[2] = 0x21;
  19.     BL0942_Uart_Buffer[3] = 0x02;
  20.     BL0942_Uart_Buffer[4] = 0x00;
  21.     BL0942_Uart_Buffer[5] = ~( BL0942_Uart_Buffer[0] + BL0942_Uart_Buffer[1] + BL0942_Uart_Buffer[2] + BL0942_Uart_Buffer[3] + BL0942_Uart_Buffer[4]);
  22.     BL0942_Uart1_W((uint8_t*)BL0942_Uart_Buffer,TIMEOUT); //set the overcurrent point: 0x221:1.5A
  23.     BL0942_Uart1_R(BL0942_Addr_R,Addr_MASK,TIMEOUT);  //Read the OT_FUNX_Reg
  24.     BL0942_Uart_Buffer[1] = Addr_MASK;  
  25.     BL0942_Uart_Buffer[3] = 0x00;
  26.     BL0942_Uart_Buffer[4] = 0x00;
  27.     BL0942_Uart_Buffer[5] = ~( BL0942_Uart_Buffer[0] + BL0942_Uart_Buffer[1] + BL0942_Uart_Buffer[2] + BL0942_Uart_Buffer[3] + BL0942_Uart_Buffer[4]);
  28.     BL0942_Uart1_W((uint8_t*)BL0942_Uart_Buffer,TIMEOUT); //set the CF1 out to overcurrent indicator
  29.     //lock
  30.     BL0942_Uart_Buffer[1] = Addr_WRPROT;
  31.     BL0942_Uart_Buffer[2] = 0x00;
  32.     BL0942_Uart_Buffer[3] = 0x00;
  33.     BL0942_Uart_Buffer[4] = 0x00;
  34.     BL0942_Uart_Buffer[5] = ~( BL0942_Uart_Buffer[0] + BL0942_Uart_Buffer[1] + BL0942_Uart_Buffer[2] + BL0942_Uart_Buffer[3] + BL0942_Uart_Buffer[4]);
  35.     BL0942_Uart1_W((uint8_t*)BL0942_Uart_Buffer,TIMEOUT);
 楼主| 发给她更好fh 发表于 2023-8-27 17:06 | 显示全部楼层
读取电流有效值及验证寄存器配置值,
  1.     BL0942_Uart1_R(BL0942_Addr_R,Addr_FAST_RMS_TH,TIMEOUT);
  2.     BL0942_Uart1_R(BL0942_Addr_R,Addr_MASK,TIMEOUT);
  3.     BL0942_Uart1_R(BL0942_Addr_R,Addr_I_RMS,TIMEOUT);
 楼主| 发给她更好fh 发表于 2023-8-27 17:06 | 显示全部楼层
  1. **注意:
  2.         1. BL0942自身不带保存功能,每次上电都要重新配置
  3.         2. 串口波特率4800 和9600是通过外部条线的方式配置,19200 和38400则需要统通MODE寄存器进行配置**
Pulitzer 发表于 2024-9-16 07:14 | 显示全部楼层

输入电源电流环路
童雨竹 发表于 2024-9-16 09:10 | 显示全部楼层

单片机一般都有内部程序区和数据区
Wordsworth 发表于 2024-9-16 10:13 | 显示全部楼层

输入和输出电流环路连接的位置只能是相应的输入 输出电容的接线端
公羊子丹 发表于 2024-9-16 12:09 | 显示全部楼层

CPLD解密,DSP解密都习惯称为单片机解密
万图 发表于 2024-9-16 13:12 | 显示全部楼层

引线越长,它能接收和传送的干扰信号频率就越低
Uriah 发表于 2024-9-16 14:15 | 显示全部楼层

输入电压端上测得的值比它实际
帛灿灿 发表于 2024-9-16 16:11 | 显示全部楼层

引线的长和宽影响它的电阻和电感量
Bblythe 发表于 2024-9-16 17:14 | 显示全部楼层

它们的放置要尽可能靠近
周半梅 发表于 2024-9-16 19:10 | 显示全部楼层

大部分单片机都带有加密锁定位或者加密字节
您需要登录后才可以回帖 登录 | 注册

本版积分规则

43

主题

563

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部