系统的示意图如下所示:

MCU对BQ79600进行初始化的时候,MCU通过Wakeup ping可以唤醒桥接芯片BQ79600, 但是在进行自动编码的时候,MCU检测到SPI_RDY信号一直为低,导致无法与BQ79600进行通信,从而陷入无限等待之后,编码过程无法通过。
BQ79600的初始化代码如下:
void Task_AfeComm_Init(void)
{
#if 1
//INITIALIZE BQ79600
//two wakes in case the MCU had nCS and MOSI = 0 at start (which would put the device in shutdown)
//or in case the device was previously put in shutdown through a shutdown ping
SpiWake79600(); //send wake ping to bridge device
SysDelay_mS(4); //wait tSU(WAKE_SHUT), at least 3.5ms
//SpiWake79600(); //send wake ping to bridge device
//SysDelay_mS(4); //tSU(WAKE_SHUT), at least 3.5ms
//INITIALIZE BQ79616-Q1 STACK
SpiWriteReg(0, CONTROL1, 0x20, 1, FRMWRT_SGL_W); //send wake tone to stack devices
SysDelay_mS(12*TOTALBOARDS); //wake tone duration is ~1.6ms per board + 10ms per board for each device to wake up from shutdown = 11.6ms per 616 board.
//AUTO-ADDRESS
SpiAutoAddress(); //auto address sequence
//RESET ANY COMM FAULT CONDITIONS FROM STARTUP
SpiWriteReg(0, FAULT_RST1, 0xFF, 1, FRMWRT_STK_W); //Reset faults on stacked devices
SpiWriteReg(0, FAULT_RST2, 0xFF, 1, FRMWRT_STK_W); //Reset faults on stacked devices
SpiWriteReg(0, Bridge_FAULT_RST, 0x22, 1, FRMWRT_SGL_W); //Reset FAULT_COMM and FAULT_SYS on bridge device
//ENABLE BQ79616-Q1 MAIN ADC
SpiWriteReg(0, ACTIVE_CELL, ACTIVE_CELL_16S, 1, FRMWRT_STK_W); //Set all cells to active
SpiWriteReg(0, GPIO_CONF1, ((GPIO_CFG_ADC << 3) | GPIO_CFG_ADC), 1, FRMWRT_STK_W); //Configure temp samp
SpiWriteReg(0, GPIO_CONF2, ((GPIO_CFG_ADC << 3) | GPIO_CFG_ADC), 1, FRMWRT_STK_W); //Configure temp samp
SpiWriteReg(0, GPIO_CONF3, ((GPIO_CFG_ADC << 3) | GPIO_CFG_ADC), 1, FRMWRT_STK_W); //Configure temp samp
SpiWriteReg(0, GPIO_CONF4, ((GPIO_CFG_ADC << 3) | GPIO_CFG_ADC), 1, FRMWRT_STK_W); //Configure temp samp
SpiWriteReg(0, ADC_CTRL1, (ADC_MAIN_GO_START | ADC_RUNMODE_CONTINUE), 1, FRMWRT_STK_W); //continuous run and MAIN_GO
//SysDelay_uS(5*TOTALBOARDS + 192); //5us reclocking per board and 192us for round robin to complete
#endif
TMR_InitTimer(TID_AFE_COMM, 200);
}
自动编码过程的代码如下:
void SpiAutoAddress()
{
UINT8 BoardIdx;
UINT8 AutoAddr_RspData[8] = { 0 };
//DUMMY WRITE TO SNCHRONIZE ALL DAISY CHAIN DEVICES DLL (IF A DEVICE RESET OCCURED PRIOR TO THIS)
SpiWriteReg(0, OTP_ECC_DATAIN1, 0x00, 1, FRMWRT_STK_W);
SpiWriteReg(0, OTP_ECC_DATAIN2, 0x00, 1, FRMWRT_STK_W);
SpiWriteReg(0, OTP_ECC_DATAIN3, 0x00, 1, FRMWRT_STK_W);
SpiWriteReg(0, OTP_ECC_DATAIN4, 0x00, 1, FRMWRT_STK_W);
SpiWriteReg(0, OTP_ECC_DATAIN5, 0x00, 1, FRMWRT_STK_W);
SpiWriteReg(0, OTP_ECC_DATAIN6, 0x00, 1, FRMWRT_STK_W);
SpiWriteReg(0, OTP_ECC_DATAIN7, 0x00, 1, FRMWRT_STK_W);
SpiWriteReg(0, OTP_ECC_DATAIN8, 0x00, 1, FRMWRT_STK_W);
//ENABLE AUTO ADDRESSING MODE
/*
bit7 DIR_SEL = 选择菊花链通信方向。
0 = 在两个器件以菊花链方式连接的情况下,命令帧从下部器件的 COMH 传输到下一个器件的 COML。
1 = 在两个器件以菊花链方式连接的情况下,命令帧从下部器件的 COML 传输到下一个器件的 COMH。
bit6 SEND_SHUTDOWN = 沿堆栈向上,向下一个器件发送SHUTDOWN音。接收此位设置的器件不受影响。读取时该位被清除。
0 = 就绪
1 = 沿堆栈向上发送关断音
bit5 SEND_WAKE = 沿堆栈向上,向下一个器件发送唤醒音。读取时该位被清除。
0 = 就绪
1 = 沿堆栈向上,向下一个器件发送唤醒音。
bit4 SEND_SLPTOACT = 沿堆栈向上,发送 SLEEPtoACTIVE 音。读取时该位被清除。
0 = 就绪
1 = 沿堆栈向上,发送 SLEEPtoACTIVE 音
bit3 GOTO_SHUTDOWN = 将器件转换为 SHUTDOWN 模式。读取时该位被清除。
0 = 就绪
1 = 进入 SHUTDOWN 模式
bit2 GOTO_SLEEP = 将器件转换为 SLEEP 模式。读取时该位被清除。
0 = 就绪
1 = 进入 SLEEP 模式
bit1 SOFT_RESET = 将数字复位为 OTP 默认值。读取时该位被清除。设置该位将使器件向上层堆栈器件生成唤醒音。
0 = 就绪
1 = 复位器件
bit0 ADDR_WR = 使器件启动自动寻址。设置该位时,器件不会转发它接收到的第一个转换,从而允许将器件地址写入单个器件。
0 = 不执行自动寻址。器件正常转发通信事务。
1 = 正在对器件自动寻址;将不会转发它收到的第一个通信事务。
*/
SpiWriteReg(0, CONTROL1, 0X01, 1, FRMWRT_ALL_W);
//SET ADDRESSES FOR EVERY BOARD
//for(BoardIdx = 0; BoardIdx < PARA_GetUint16(PID_SYS_BMU_NUM); BoardIdx++)
for(BoardIdx = 0; BoardIdx < TOTALBOARDS; BoardIdx++)
{
SpiWriteReg(0, DIR0_ADDR, BoardIdx, 1, FRMWRT_ALL_W);
}
//BROADCAST WRITE TO SET ALL DEVICES AS STACK DEVICE
//Bit0: TOP_STACK. 将器件定义为堆栈中地址最高的器件. 0=不是ToS器件; 1=是ToS器件
//Bit1: STACK_DEV. 将器件定义为菊花链配置中的基底器件或堆栈器件. 0=基底器件; 1=堆栈器件
SpiWriteReg(0, COMM_CTRL, 0x02, 1, FRMWRT_ALL_W);
//SET THE HIGHEST DEVICE IN THE STACK AS BOTH STACK AND TOP OF STACK
SpiWriteReg(TOTALBOARDS-1, COMM_CTRL, 0x03, 1, FRMWRT_SGL_W);
//SYNCRHONIZE THE DLL WITH A THROW-AWAY READ
SpiReadReg(0, OTP_ECC_DATAIN1, AutoAddr_RspData, 1, 100, FRMWRT_STK_R);
//MCU is blocked while read register OTP_ECC_DATAIN2
SpiReadReg(0, OTP_ECC_DATAIN2, AutoAddr_RspData, 1, 100, FRMWRT_STK_R);
SpiReadReg(0, OTP_ECC_DATAIN3, AutoAddr_RspData, 1, 100, FRMWRT_STK_R);
SpiReadReg(0, OTP_ECC_DATAIN4, AutoAddr_RspData, 1, 100, FRMWRT_STK_R);
SpiReadReg(0, OTP_ECC_DATAIN5, AutoAddr_RspData, 1, 100, FRMWRT_STK_R);
SpiReadReg(0, OTP_ECC_DATAIN6, AutoAddr_RspData, 1, 100, FRMWRT_STK_R);
SpiReadReg(0, OTP_ECC_DATAIN7, AutoAddr_RspData, 1, 100, FRMWRT_STK_R);
SpiReadReg(0, OTP_ECC_DATAIN8, AutoAddr_RspData, 1, 100, FRMWRT_STK_R);
//OPTIONAL: read back all device addresses
//for(BoardIdx = 0; BoardIdx < PARA_GetUint16(PID_SYS_BMU_NUM); BoardIdx++)
for(BoardIdx = 0; BoardIdx < TOTALBOARDS; BoardIdx++)
{
SpiReadReg(BoardIdx, DIR0_ADDR, AutoAddr_RspData, 1, 100, FRMWRT_SGL_R);
}
//OPTIONAL: read register address 0x2001 and verify that the value is 0x14
SpiReadReg(0, 0x2001, AutoAddr_RspData, 1, 100, FRMWRT_SGL_R);
return;
}
请帮忙分析一下是什么原因,导致MCU在读取寄存器0x344 (OTP_ECC_DATAIN2)的时候,就一直提示SPI通信无法进行了。