系统的示意图如下所示:
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通信无法进行了。