应用TI的bq76PL455 前端模拟IC遇到问题,无法采集到电池电压
本公司需要应用bq76PL455IC进行电池管理电压采集,在使用中根据bq76PL455A-Q1 Example Code 进行配置,单片机能与之通信,可以配置控制IO口,清除错语,测试均衡控制信号测试,都没有问题,但是一直无法采集到电压:
U16 nSent, nRead;// nTopFound = 0;
U16 nDev_ID;// nGrp_ID;
U8 cnt_test = 0;
U8 bFrame[132];
U16 crc;
U32 wTemp = 0;
WakeUp_PL455();
__delay_ms(10);
nSent = PL455_WriteReg(0, 107, 0x8000, 2, FRMWRT_ALL_NR); // clear all fault summary flags
nSent = PL455_WriteReg(0, 81, 0x38, 1, FRMWRT_ALL_NR); // clear fault flags in the system status register
nSent = PL455_WriteReg(0, 14, 0x19, 1, FRMWRT_ALL_NR); // set auto-address mode on all boards
nSent = PL455_WriteReg(0, 12, 0x08, 1, FRMWRT_ALL_NR); // enter auto address mode on all boards, the next write to this ID will be its address
for (nDev_ID = 0; nDev_ID < TOTALBOARDS; nDev_ID++)
{
nSent = PL455_WriteReg(nDev_ID, 10, nDev_ID, 1, FRMWRT_ALL_NR); // send address to each board
}
nSent = PL455_WriteReg(0, 16, 0x1080, 2, FRMWRT_SGL_NR);
// Clear all faults
nSent = PL455_WriteReg(0, 82, 0xffc0, 2, FRMWRT_SGL_NR); // clear all fault summary flags
nSent = PL455_WriteReg(0, 81, 0x38, 1, FRMWRT_SGL_NR); // clear fault flags in the system status register
////////////////////////////////////////////////////////////////////////////////////////////////
//nSent = PL455_WriteReg(0, 60, 0x00, 1, FRMWRT_SGL_NR);
nSent = PL455_WriteReg(0, 61, 0x00, 1, FRMWRT_SGL_NR); // set 0 initial delay
nDev_ID = 0;
nSent = PL455_WriteReg(nDev_ID, 62, 0xBC, 1, FRMWRT_SGL_NR); // set 99.92us ADC sampling period
nDev_ID = 0;
nSent = PL455_WriteReg(nDev_ID, 7, 0x00, 1, FRMWRT_SGL_NR); // set no oversampling period
nDev_ID = 0;
nSent = PL455_WriteReg(nDev_ID, 81, 0x38, 1, FRMWRT_SGL_NR); // clear fault flags in the system status register
nRead = PL455_ReadReg(nDev_ID, 81, &wTemp, 1, 4); // 0ms timeout
nSent = PL455_WriteReg(nDev_ID, 82, 0xFFC0, 2, FRMWRT_SGL_NR); // clear all fault summary flags
nRead = PL455_ReadReg(nDev_ID, 82, &wTemp, 1, 4); // 0ms timeout
nSent = PL455_WriteReg(0, 13, 0x08, 1, FRMWRT_SGL_NR); // set number of cells to 8
nSent = PL455_WriteReg(0, 3, 0x00FF03C0, 4, FRMWRT_SGL_NR); // select all cell channels 1-8, AUX channels 0 and 1, and internal digital die and internal analog die temperatures
nDev_ID = 0;
nSent = PL455_WriteReg(nDev_ID, 144, 0xD1EC, 2, FRMWRT_SGL_NR); // set OV threshold = 4.1000V
nSent = PL455_WriteReg(nDev_ID, 142, 0x6148, 2, FRMWRT_SGL_NR); // set UV threshold = 1.9000V
nSent = PL455_WriteReg(0, 144, 0xD1EC, 2, FRMWRT_ALL_NR); // set OV threshold = 4.1000V
nSent = PL455_WriteReg(0, 142, 0x6148, 2, FRMWRT_ALL_NR); // set UV threshold = 1.9000V
nSent = PL455_WriteReg(0, 2, 0x02, 1, FRMWRT_ALL_NR); // send sync sample command
nSent = PL455_WriteReg(0, 2, 0x00, 1, FRMWRT_ALL_NR); // send sync sample command
nSent = PL455_WriteReg(0, 13, 0x08, 1, FRMWRT_SGL_NR); // set number of cells to 8
nSent = PL455_WriteReg(0, 3, 0x00FF03C0, 4, FRMWRT_SGL_NR); // select all cell channels 1-8, AUX channels 0 and 1, and internal digital die and internal analog die temperatures
nDev_ID = 0;
nSent = PL455_WriteReg(nDev_ID, 2, 0x20, 1, FRMWRT_SGL_R); // send sync sample command //发送采样命令
nSent = WaitRespFrame(bFrame, 27, 4); // 24 bytes data + packet header + CRC, 0ms timeout //读取采集数据
while(1)
{////发送采集命令后在此查询接收到的数据(1)//接收断点1
PIN_LED = !PIN_LED;
__delay_ms(2000);
ClrWdt();
Uart_SendChar1(rx_buf,27); //打印接收到的数据
}
在接收断点1处,接收到来自于前端IC传过来的数据为:(8路节电池电压和四路AUX电压)
17 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 87 7C 00 00 17 97
17 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 86 eC 00 00 16 46
17 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 86 f4 00 00 96 41
.......
//一直不明白为什么返回来的数据电压点都不对!电路板是官网的DEMO,只是控制端用单片机来处理。
由于项目紧急,只能在论坛上请求支持! 期待TI的技术支持能给以帮助!
U16 nSent, nRead;// nTopFound = 0;
U16 nDev_ID;// nGrp_ID;
U8 cnt_test = 0;
U8 bFrame[132];
U16 crc;
U32 wTemp = 0;
WakeUp_PL455();
__delay_ms(10);
nSent = PL455_WriteReg(0, 107, 0x8000, 2, FRMWRT_ALL_NR); // clear all fault summary flags
nSent = PL455_WriteReg(0, 81, 0x38, 1, FRMWRT_ALL_NR); // clear fault flags in the system status register
nSent = PL455_WriteReg(0, 14, 0x19, 1, FRMWRT_ALL_NR); // set auto-address mode on all boards
nSent = PL455_WriteReg(0, 12, 0x08, 1, FRMWRT_ALL_NR); // enter auto address mode on all boards, the next write to this ID will be its address
for (nDev_ID = 0; nDev_ID < TOTALBOARDS; nDev_ID++)
{
nSent = PL455_WriteReg(nDev_ID, 10, nDev_ID, 1, FRMWRT_ALL_NR); // send address to each board
}
nSent = PL455_WriteReg(0, 16, 0x1080, 2, FRMWRT_SGL_NR);
// Clear all faults
nSent = PL455_WriteReg(0, 82, 0xffc0, 2, FRMWRT_SGL_NR); // clear all fault summary flags
nSent = PL455_WriteReg(0, 81, 0x38, 1, FRMWRT_SGL_NR); // clear fault flags in the system status register
////////////////////////////////////////////////////////////////////////////////////////////////
//nSent = PL455_WriteReg(0, 60, 0x00, 1, FRMWRT_SGL_NR);
nSent = PL455_WriteReg(0, 61, 0x00, 1, FRMWRT_SGL_NR); // set 0 initial delay
nDev_ID = 0;
nSent = PL455_WriteReg(nDev_ID, 62, 0xBC, 1, FRMWRT_SGL_NR); // set 99.92us ADC sampling period
nDev_ID = 0;
//建议8次oversample。
nSent = PL455_WriteReg(nDev_ID, 7, 0x00, 1, FRMWRT_SGL_NR); // set no oversampling period
nDev_ID = 0;
nSent = PL455_WriteReg(nDev_ID, 81, 0x38, 1, FRMWRT_SGL_NR); // clear fault flags in the system status register
nRead = PL455_ReadReg(nDev_ID, 81, &wTemp, 1, 4); // 0ms timeout
nSent = PL455_WriteReg(nDev_ID, 82, 0xFFC0, 2, FRMWRT_SGL_NR); // clear all fault summary flags
nRead = PL455_ReadReg(nDev_ID, 82, &wTemp, 1, 4); // 0ms timeout
nSent = PL455_WriteReg(0, 13, 0x08, 1, FRMWRT_SGL_NR); // set number of cells to 8
nSent = PL455_WriteReg(0, 3, 0x00FF03C0, 4, FRMWRT_SGL_NR); // select all cell channels 1-8, AUX channels 0 and 1, and internal digital die and internal analog die temperatures
nDev_ID = 0;
nSent = PL455_WriteReg(nDev_ID, 144, 0xD1EC, 2, FRMWRT_SGL_NR); // set OV threshold = 4.1000V
nSent = PL455_WriteReg(nDev_ID, 142, 0x6148, 2, FRMWRT_SGL_NR); // set UV threshold = 1.9000V
nSent = PL455_WriteReg(0, 144, 0xD1EC, 2, FRMWRT_ALL_NR); // set OV threshold = 4.1000V
nSent = PL455_WriteReg(0, 142, 0x6148, 2, FRMWRT_ALL_NR); // set UV threshold = 1.9000V
//无效,建议删除
nSent = PL455_WriteReg(0, 2, 0x02, 1, FRMWRT_ALL_NR); // send sync sample command
//无效,建议删除
nSent = PL455_WriteReg(0, 2, 0x00, 1, FRMWRT_ALL_NR); // send sync sample command
//重复配置可以省略
nSent = PL455_WriteReg(0, 13, 0x08, 1, FRMWRT_SGL_NR); // set number of cells to 8
nSent = PL455_WriteReg(0, 3, 0x00FF03C0, 4, FRMWRT_SGL_NR); // select all cell channels 1-8, AUX channels 0 and 1, and internal digital die and internal analog die temperatures
nDev_ID = 0;
//发送sample and store 指令, 并delay 5ms,
nSend = PL455_WriteReg(0, 2, 0x00, 1, FRMWRT_ALL_NR);
_delay_ms(5);
nSent = PL455_WriteReg(nDev_ID, 2, 0x20, 1, FRMWRT_SGL_R); // send sync sample command //发送采样命令
nSent = WaitRespFrame(bFrame, 27, 4); // 24 bytes data + packet header + CRC, 0ms timeout //读取采集数据
while(1)
{////发送采集命令后在此查询接收到的数据(1)//接收断点1
PIN_LED = !PIN_LED;
__delay_ms(2000);
ClrWdt();
Uart_SendChar1(rx_buf,27); //打印接收到的数据
}
在接收断点1处,接收到来自于前端IC传过来的数据为:(8路节电池电压和四路AUX电压)
17 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 87 7C 00 00 17 97
17 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 86 eC 00 00 16 46
17 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 86 f4 00 00 96 41
.......
//一直不明白为什么返回来的数据电压点都不对!电路板是官网的DEMO,只是控制端用单片机来处理。
由于项目紧急,只能在论坛上请求支持! 期待TI的技术支持能给以帮助!
谢谢TI员工的回复!
还有个小问题,是关于把数据写入EEPORM的,是否是在初始化的前面写入两条指令如下:(就是把寄存器的值也写入了EEPROM,当电池包断电后,再有电时,这些寄存器的值会从EEPROM那边读过来,而单片机不用再配置)
U8 i,bFrame[132];
U16 nSent, nRead;
U16 nDev_ID;
U32 wTemp = 0;
ClrWdt();
WakeUp_PL455();
__delay_ms(20);
nSent = PL455_WriteReg(0, 130, 0x8C2DB194, 4, FRMWRT_ALL_NR); //写KEY1
__delay_ms(200);
nSent = PL455_WriteReg(0, 252, 0xA375E60F, 4, FRMWRT_ALL_NR); //get register to eeprom //写KEY2
__delay_ms(200);
nSent = PL455_WriteReg(0, 107, 0x8000, 2, FRMWRT_ALL_NR); // clear all fault summary flags
nSent = PL455_WriteReg(0, 81, 0x38, 1, FRMWRT_ALL_NR); // clear fault flags in the system status register
nSent = PL455_WriteReg(0, 82, 0xFFC0, 2, FRMWRT_ALL_NR); // clear all fault summary flags
nSent = PL455_WriteReg(0, 14, 0x19, 1, FRMWRT_ALL_NR);
nSent = PL455_WriteReg(0, 12, 0x08, 1, FRMWRT_ALL_NR);
for (nDev_ID = 0; nDev_ID < TOTALBOARDS; nDev_ID++)
{
nSent = PL455_WriteReg(nDev_ID, 10, nDev_ID, 1, FRMWRT_ALL_NR);
}
nSent = PL455_WriteReg(0, 40, 0, 1, FRMWRT_SGL_NR); //禁用通信故障检测
nSent = PL455_WriteReg(0, 16, 0x1080, 2, FRMWRT_SGL_NR);
nSent = PL455_WriteReg(0, 19, 0x08, 1, FRMWRT_SGL_NR);
nSent = PL455_WriteReg(0, 61, 0x00, 1, FRMWRT_SGL_NR); // set 0 initial delay
...................
....................
.....................
END Bq455_Init
是否在初始寄存器这前,写入KEY1 和KEY2之后,到初始化END Bq455_Init之间配置的寄存器的值都也存到了EEPROM当中,下次电池包断电后,不需要再配置Bq455了?
烧写就是把当前ram里的配置值写入到eeprom , 下次上电自动载入。
但是注意
1 . 不是所有寄存器都有对应的eeprom 状态寄存器 故障寄存器。还有一些测试寄存器 没有对应的eeprom, 如果要修改 依然要上电就配置 具体参照dataflash的描述
2. 地址寄存器也会被烧写 下次启动会自动载入eeprom的地址 , 如果是通过菊花链链接 而不是在同一个板子上的话 启动需要软件再做一次autoaddress分配地址。如果芯片发生复位 地址会变成eeprom内的地址,如果系统干扰导致芯片复位 一定要注意处理可能出现的地址变化的状况 做一次autoaddress
3. 烧写次数不超过5次,一般是产线下线检测和校准的之后做烧写即可
如果芯片发生复位 地址会变成eeprom内的地址? 此话怎么理解,不太明白,还有就是dataflash的描述的文档,方便留一个链接地址吗?非常感谢了
复位 会重新载入EEPROM到RAM。
http://www.ti.com/lit/ds/symlink/bq76pl455a-q1.pdf
这个文档早前已经下载过的,但是对EEprom的存储描述得不是很详细,比如我在 bq76PL455A Q1 Software Design Reference PDF中看到的EEPROM操作方式是:
1. Write Magic Number 1. //写入魔术值1 //94 00 82 8C2DB194 62B1
2. Write Magic Number 2. //写入魔术值2 //94 00 FC A375E60F BC27
3. Save register values to EEPROM. //Write RAM to EEPROM: // 91 00 0C 10 2830 ==>Device:00 寄存器地址 0x0C data:10 //是否这个data的值不是 //实际写入的值,而是操作EEPROM_BIT的写法? 没有看到PDF有相关的说明
4. Wait until save of register values is complete //__delay_ms(200);
比如,需要把0xoc的寄存器配置成0X55;然后把它保存到EEPROM中,是否该这样操作:
1.先初始化BQ455,分配地址,清除错误
2.写入 0xoc的寄存器值为0X55
3......................
4. 94 00 82 8C2DB194 62B1 //写入魔术值1
5.94 00 FC A375E60F BC27 //写入魔术值2
6.91 00 0C 10 2830 //0x0c 的值写入EEPROM //此处的 0x10 表示要把 0x0c的值0x55写入EEPROM中,而不是说把 0x10写入到EEPROM中的吧?
7.__delay_ms(200);
END bq455_init
91 00 0C 10 2830 是用来使能EEPROM的烧写。
写入magic就是让455A将当前寄存器的值保存到EEPROM中, 是整块区域所有的都保存。不能单个bit的写。
0x0c没有EEPROM。无法保存。请看page66的表格确认你要改的寄存器有没有EEPROM.
另外,烧写前请清除Customer check sum 错误。
好的,非常感谢wang's!
请问这是什么软件编译的?CCS吗
您好,请你是用CCS写的程序吗?
TI 例程是用CCS的。
你好,请问返回的电压和温度数据具体是哪些值?数据头是那几个量,CRC是那几个量?
你好,我现在用MCU跟PL455通信时,读到器件状态寄存器(81)的数据为0x01,我看这的解释是系统正在进行初始化,然后我要是给寄存器2发送采集命令0x20的话,采集不到数据,455的Fault引脚为低电平;然后我要是给寄存器(81)写0x39的话,MCU有时就能读到数据,有时读不到,并且读到的电压数据都不对(实际的电池电压为3.8V,采集回来的显示电压为10mv~40mV),请问这是什么原因,为什么芯片会一直在进行初始化?
你好,我现在用MCU跟PL455通信时,读到器件状态寄存器(81)的数据为0x01,我看这的解释是系统正在进行初始化,然后我要是给寄存器2发送采集命令0x20的话,采集不到数据,455的Fault引脚为低电平;然后我要是给寄存器(81)写0x39的话,MCU有时就能读到数据,有时读不到,并且读到的电压数据都不对(实际的电池电压为3.8V,采集回来的显示电压为10mv~40mV),请问这是什么原因,为什么芯片会一直在进行初始化?
帧头是1个byte, 返回的是data 长度-1, CRC是最后两个byte。
我的按这个加大了OVERSMPL ,做了延迟,读出来来的数据也都是采样数据都是0
现在数据是第一个是0x1F,中间都是0x00,第34个数据是0xA5,第35个数据是0xC4,我设置的通道是采样16节电池电压;另外我请问下455的VM引脚是不是要输出-5V才正常?我的没有输出,请问这是什么情况?
1F是帧头,1F+1=32,是指你返回的有效数据是32个。第34个,第35个是CRC码。你试试中间接个电压
我知道数据传回来的格式;我就是接的电压测试的,实际电压是3.8V,采集回来的都为0,所以才有这疑问。
在调试455,求例程