赞
踩
本文介绍通过STM32和BL0942进行交流电流的测量和监控
能脉冲。
本文介绍如何通过STM32 以串口模式对BL0942进行配置读取,同时通过CF1监控过流,不多废话,直接上代码
**
**
#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; // */
/** * @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(); } } }
/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);
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寄存器进行配置**
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。