关于串口通信读取BL0942芯片电压电流的使用
概述:
通过串口通信来获取BL0942芯片采集到的电压电流,采用的芯片为10引脚类型,电压采样为电阻采样,电流采样为互感器采样。
芯片功能特点:
-
两路独立的Sigma-Delta ADC,一路电流和一路电压。
-
电流有效值范围(10mA~35A)@1mohm 有功电能(1w~7700w)@1mohm
-
可测量电流电压有效值,快速电流有效值,有功功率,电流电压波形
-
批次出厂增益误差小于1%,外围元件满足一定条件下可以免校准
-
电流通道具备过流监控功能,监控阈值及响应时间可设置
-
电压/电流过零信号输出 内置波形寄存器,可输出波形数据用于负载类型分析
-
集成SPI(最快速率支持900KHz)/UART(4800-38400bps)通信方式
-
电源掉电监测,低于2.7V时,芯片进入复位状态
-
内置1.218V参考电压源 内置振荡电路,时钟约4MHz
-
芯片单工作电源3.3V,低功耗10mW(典型值)
封装与管脚描述:
采用的10引脚封装芯片
寄存器说明:
通过串口向BL0942发送指令,根据寄存器地址我们可以读取到相应数据。
特殊寄存器说明:
电压采样电路及说明:
电压采样使用的方法为电阻采样,由芯片管脚描述中所说VP为电压信号输入端,可以看到图中电压通道通过R2(390K*5)+R1(0.51K)电阻分压把交流220V电压降到mV级信号给VP管脚;根据提供的公式:
其中,V_eff 表示电压有效值,V_ref 表示典型值1.218V。
我们就可以算出实际的电压值,不同个体芯片会有些许误差,可以通过自定义系数来校正。
下图为芯片应用指南的电阻电路图:
电流采样电路及说明:
电流采样使用的方法为电流互感器采样,由芯片管脚描述中所说IP,IN为电流模拟输入端;我们只需看图中IP1,IN1引脚。假设电流互感器CT1的变比为Rt=2000(2000:1),负载电阻R5(3.3欧),根据提供的公式:
其中,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;
}
}
}
作者:柒樂葉