使用 MSP430 SPI 和连接到一个 MAX17853的 MAX17841 (表10)、我能够获得对菊花链初始化序列的正确响应。 唤醒和 hello 所有事务在 MISO 线路上接收正确的响应,我得到返回为0x001的器件地址。 这与 Maxim 评估 GUI 相同。 这些 MSP430 SPI 响应已在示波器上捕获。
现在、我需要使 MAX17841的表11正常工作。 我发送了事务1、2和3 (WriteAll_transactions[0]= 0xc0; WriteAll_transactions[1]。Data[0]= 0xb0;WriteAll_transactions[2]。Data[0]= 0x01;)、但我没有得到0x12的接收。 相反、我得到0x11 (有时为0x21)、这意味着存在 RX_Overflow_Status 或存在未读数据。 我不明白这是为什么。 在表10中的事务中、命令0xC0和0xB0工作正常。 使用评估 GUI、表11工作正常。 因此、MSP430握手会丢失一些东西。 我感谢任何指示。 我已将当前文件附加到此帖子。
我尝试从 WriteAll_transactions [0]中包含和删除 PEC 字节、但从器件响应没有任何差异。
#include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <string.h> #include <driverlib.h> #include <intrinsics.h> #include <msp430.h> #include "clock~.h" // Clock configurations #define UART_TRANSMIT_BUFFER_LENGTH 76 #define UART_TXD_PORT GPIO_PORT_P1 #define UART_TXD_PIN GPIO_PIN4 #define UART_RXD_PORT GPIO_PORT_P1 #define UART_RXD_PIN GPIO_PIN5 #define UART_SELECT_FUNCTION GPIO_PRIMARY_MODULE_FUNCTION #define SPI_MOSI_PORT GPIO_PORT_P2 #define SPI_MOSI_PIN GPIO_PIN6 #define SPI_MISO_PORT GPIO_PORT_P2 #define SPI_MISO_PIN GPIO_PIN5 #define SPI_CLK_PORT GPIO_PORT_P2 #define SPI_CLK_PIN GPIO_PIN4 #define SPI_SELECT_FUNCTION GPIO_PRIMARY_MODULE_FUNCTION typedef struct { uint8_t Len; uint8_t Data[10]; } spi_MaximTrans_t; static uint8_t RXData[8] = {0}; //SPI receive byte /** * Initialize system clocks */ static void init_clock(void) { // Configure one FRAM waitstate as required by the device datasheet for MCLK // operation beyond 8MHz _before_ configuring the clock system. FRAMCtl_configureWaitStateControl(FRAMCTL_ACCESS_TIME_CYCLES_1); //Set DCO FLL reference = REFO CS_initClockSignal(CS_FLLREF, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1); //Set ACLK = REFO CS_initClockSignal(CS_ACLK, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1); CS_initFLLParam param = {0}; //Set Ratio/Desired MCLK Frequency, initialize DCO, save trim values CS_initFLLCalculateTrim(CS_MCLK_DESIRED_FREQUENCY_IN_KHZ, CS_MCLK_FLLREF_RATIO, ¶m); //Set MCLK = REFO CS_initClockSignal(CS_MCLK, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1); //Set SMCLK = DCO CS_initClockSignal(CS_SMCLK, CS_DCOCLKDIV_SELECT, CS_CLOCK_DIVIDER_1); //Clear all OSC fault flag CS_clearAllOscFlagsWithTimeout(1000); } /** * Initialize all of the IO pins per their configuration */ static void init_gpio(void) { // Set all GPIO pins to output low to prevent floating input and reduce power consumption GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN_ALL8); GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN_ALL8); GPIO_setOutputLowOnPin(GPIO_PORT_P3, GPIO_PIN_ALL8); GPIO_setOutputLowOnPin(GPIO_PORT_P4, GPIO_PIN_ALL8); GPIO_setOutputLowOnPin(GPIO_PORT_P5, GPIO_PIN_ALL8); GPIO_setOutputLowOnPin(GPIO_PORT_P6, GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2); GPIO_setAsOutputPin( GPIO_PORT_P1, GPIO_PIN_ALL8); GPIO_setAsOutputPin( GPIO_PORT_P2, GPIO_PIN_ALL8); GPIO_setAsOutputPin( GPIO_PORT_P3, GPIO_PIN_ALL8); GPIO_setAsOutputPin( GPIO_PORT_P4, GPIO_PIN_ALL8); GPIO_setAsOutputPin( GPIO_PORT_P5, GPIO_PIN_ALL8); GPIO_setAsOutputPin( GPIO_PORT_P6, GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2); } /* * Initialize the SPI peripheral on EUSCI A1 */ void init_spi_peripheral() { GPIO_setAsPeripheralModuleFunctionOutputPin(SPI_MOSI_PORT, SPI_MOSI_PIN, SPI_SELECT_FUNCTION); GPIO_setAsPeripheralModuleFunctionInputPin(SPI_MISO_PORT, SPI_MISO_PIN, SPI_SELECT_FUNCTION); GPIO_setAsPeripheralModuleFunctionOutputPin(SPI_CLK_PORT, SPI_CLK_PIN, SPI_SELECT_FUNCTION); //Initialize Master EUSCI_A_SPI_initMasterParam param = {0}; param.selectClockSource = EUSCI_A_SPI_CLOCKSOURCE_SMCLK; param.clockSourceFrequency = CS_getSMCLK(); param.desiredSpiClock = 1000000; param.msbFirst = UCMSB; param.clockPhase = EUSCI_A_SPI_PHASE_DATA_CAPTURED_ONFIRST_CHANGED_ON_NEXT; param.clockPolarity = EUSCI_A_SPI_CLOCKPOLARITY_INACTIVITY_LOW; param.spiMode = EUSCI_A_SPI_3PIN; EUSCI_A_SPI_initMaster(EUSCI_A1_BASE, ¶m); EUSCI_A_SPI_enable(EUSCI_A1_BASE); } void init_wd_bms_uart(void) { // Configure UART @38400 baud (EUSCI/16MHz) // software-dl.ti.com/.../index.html // Configure UCA0TXD and UCA0RXD GPIO_setAsPeripheralModuleFunctionOutputPin(UART_TXD_PORT, UART_TXD_PIN, UART_SELECT_FUNCTION); GPIO_setAsPeripheralModuleFunctionInputPin(UART_RXD_PORT, UART_RXD_PIN, UART_SELECT_FUNCTION); EUSCI_A_UART_initParam param = { .clockPrescalar = 26, .firstModReg = 0, .secondModReg = 214, .selectClockSource = EUSCI_A_UART_CLOCKSOURCE_SMCLK, .parity = EUSCI_A_UART_NO_PARITY, .msborLsbFirst = EUSCI_A_UART_LSB_FIRST, .numberofStopBits = EUSCI_A_UART_ONE_STOP_BIT, .uartMode = EUSCI_A_UART_MODE, .overSampling = EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION }; if(STATUS_FAIL == EUSCI_A_UART_init(EUSCI_A0_BASE, ¶m)) { return; } EUSCI_A_UART_enable(EUSCI_A0_BASE); } /** * UART_Transmit_String() * Prints a null terminated string on the UART * @param str null terminated string */ void UART_Transmit_String(const char *str) { int i = 0; for(i = 0; i < UART_TRANSMIT_BUFFER_LENGTH; i++) { if (str[i] != '\0') { while (EUSCI_A_UART_queryStatusFlags(EUSCI_A0_BASE, EUSCI_A_UART_BUSY)); EUSCI_A_UART_transmitData(EUSCI_A0_BASE, str[i]); } else { break; } } } void SetUpDCInitTransactions(spi_MaximTrans_t DCInit_transactions[]){ //Enable keep alive mode DCInit_transactions[0].Len = 2; DCInit_transactions[0].Data[0] = 0x10; DCInit_transactions[0].Data[1] = 0x5; //Read Back Transaction byte DCInit_transactions[1].Len = 2; DCInit_transactions[1].Data[0] = 0x11; DCInit_transactions[1].Data[1] = 0x0; //Enable Rx Interrupt flags DCInit_transactions[2].Len = 2; DCInit_transactions[2].Data[0] = 0x4; DCInit_transactions[2].Data[1] = 0x89; //No Receive //Read Back Transaction byte DCInit_transactions[3].Len = 2; DCInit_transactions[3].Data[0] = 0x5; DCInit_transactions[3].Data[1] = 0x0; //Clear receive buffer DCInit_transactions[4].Len = 1; DCInit_transactions[4].Data[0] = 0xe0; //No Receive //Wakeup UART slave devices DCInit_transactions[5].Len = 2; DCInit_transactions[5].Data[0] = 0x0e; DCInit_transactions[5].Data[1] = 0x30; //No Receive //Read Back Transaction byte DCInit_transactions[6].Len = 2; DCInit_transactions[6].Data[0] = 0x0f; DCInit_transactions[6].Data[1] = 0x0; //No Receive //2ms delay for each slave to wake up //Wait for all UART slave devices to wake up DCInit_transactions[7].Len = 2; DCInit_transactions[7].Data[0] = 0x01; DCInit_transactions[7].Data[1] = 0x0; //Receive of 0x21 expected //End of UART slave device wake-up period DCInit_transactions[8].Len = 2; DCInit_transactions[8].Data[0] = 0x0e; DCInit_transactions[8].Data[1] = 0x10; //Read Back Transaction byte DCInit_transactions[9].Len = 2; DCInit_transactions[9].Data[0] = 0x0f; DCInit_transactions[9].Data[1] = 0x0; //No Receive //2ms delay for each slave to report null message //Wait for null message to be received DCInit_transactions[10].Len = 2; DCInit_transactions[10].Data[0] = 0x01; DCInit_transactions[10].Data[1] = 0x0; //Receive 0x10 or 0x12 //Clear transmit buffer DCInit_transactions[11].Len = 1; DCInit_transactions[11].Data[0] = 0x20; //No Receive //Clear receive buffer DCInit_transactions[12].Len = 1; DCInit_transactions[12].Data[0] = 0xe0; //No Receive //Load the HELLOALL command sequence into the load queue DCInit_transactions[13].Len = 5; DCInit_transactions[13].Data[0] = 0xc0; DCInit_transactions[13].Data[1] = 0x03; //message length DCInit_transactions[13].Data[2] = 0x57; //HELLOALL command byte DCInit_transactions[13].Data[3] = 0x0; //Register address (0x00) DCInit_transactions[13].Data[4] = 0x0; //Initialization address of HELLOALL //Verify contents of the load queue DCInit_transactions[14].Len = 5; DCInit_transactions[14].Data[0] = 0xc1; DCInit_transactions[14].Data[1] = 0x0; DCInit_transactions[14].Data[2] = 0x0; DCInit_transactions[14].Data[3] = 0x0; DCInit_transactions[14].Data[4] = 0x0; //Transmit HELLOALL sequence DCInit_transactions[15].Len = 1; DCInit_transactions[15].Data[0] = 0xb0; //No Receive //2ms delay for each slave to respond //Poll RX_Stop_Status Bit DCInit_transactions[16].Len = 2; DCInit_transactions[16].Data[0] = 0x01; DCInit_transactions[16].Data[1] = 0x0; //Receive 0x12 //Service receive buffer. Read the HELLOALL message that propagated through the daisy chain //and was returned back to the ASCI.The host should verify the device count DCInit_transactions[17].Len = 4; DCInit_transactions[17].Data[0] = 0x93; DCInit_transactions[17].Data[1] = 0x0; DCInit_transactions[17].Data[2] = 0x0; DCInit_transactions[17].Data[3] = 0x0; //Check for receive buffer errors DCInit_transactions[18].Len = 0x09; DCInit_transactions[18].Data[0] = 0x0; } SPI_Send(spi_MaximTrans_t Transmit[], uint8_t index){ uint8_t SPI_TX_index = 0; //byte count in transaction GPIO_setOutputLowOnPin(GPIO_PORT_P3, GPIO_PIN1); //Maxim chip select low __delay_cycles(1000); //idle time between CS change for(SPI_TX_index = 0; SPI_TX_index < Transmit[index].Len; SPI_TX_index++){ while(!(UCA1IFG & UCTXIFG)); UCA1TXBUF = Transmit[index].Data[SPI_TX_index]; while (!(UCA1IFG & UCRXIFG)); RXData[SPI_TX_index] = UCA1RXBUF; } return; } /** * main.c */ int main(void) { static uint8_t TXData = 0; //transaction count static spi_MaximTrans_t DCInit_transactions[19]; static spi_MaximTrans_t WriteAll_transactions[3]; static spi_MaximTrans_t ReadAll_transactions[3]; static uint8_t noReceive = 0; static uint8_t noInc = 0; char buf[76]; WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer init_clock(); init_gpio(); // Set up IO pins GPIO_setOutputHighOnPin(GPIO_PORT_P3, GPIO_PIN1); //SPI slave chip select // Set P1.0 to output direction GPIO_setAsOutputPin (GPIO_PORT_P1, GPIO_PIN0); GPIO_setAsInputPinWithPullUpResistor (GPIO_PORT_P4, GPIO_PIN2); GPIO_enableInterrupt (GPIO_PORT_P4, GPIO_PIN2); GPIO_selectInterruptEdge (GPIO_PORT_P4, GPIO_PIN2, GPIO_HIGH_TO_LOW_TRANSITION); GPIO_clearInterrupt (GPIO_PORT_P4, GPIO_PIN2); GPIO_setAsOutputPin (GPIO_PORT_P6, GPIO_PIN2); PMM_unlockLPM5(); __enable_interrupt(); SetUpDCInitTransactions(DCInit_transactions); TXData = 0x0; // Holds transaction number // Setup peripheral(s) now that gpio and clocks are setup init_spi_peripheral(); // Init Maxim spi peripheral init_wd_bms_uart(); GPIO_setOutputHighOnPin (GPIO_PORT_P6, GPIO_PIN2); //SHDNL held high for 4ms to ensure all slaves are powered on __delay_cycles(32000); while (TXData < 19){ noInc = 0; SPI_Send(DCInit_transactions, TXData); if ((TXData == 6) || (TXData == 9) || (TXData == 15)) __delay_cycles(32000); //wait for slaves to wake up if (TXData == 7){ if (RXData[DCInit_transactions[7].Len-1] == 0x21){ TXData++; noReceive = 0; noInc = 1; sprintf(buf, "Wake Up status 0x21 received\n\r"); UART_Transmit_String(buf); } if (RXData[DCInit_transactions[7].Len-1] != 0x21){ TXData = 7; noReceive++; if (noReceive == 3){ sprintf(buf, "Wakeup Error\n\r"); //Need to set a Fault UART_Transmit_String(buf); } } } if (TXData == 10){ if ((RXData[DCInit_transactions[10].Len-1] == 0x10) || (RXData[DCInit_transactions[10].Len-1] == 0x12)){ TXData++; noReceive = 0; noInc = 1; sprintf(buf, "Wakeup Successful\n\r"); UART_Transmit_String(buf); } else{ TXData = 10; noReceive++; if (noReceive == 3){ sprintf(buf, "Wakeup Error: Preamble not received\n\r"); //Need to set a Fault UART_Transmit_String(buf); } } } if (TXData == 16){ if ((RXData[DCInit_transactions[16].Len-1] == 0x12)){ TXData++; noReceive = 0; noInc = 1; sprintf(buf, "HELLOALL successful\n\r"); UART_Transmit_String(buf); } else{ TXData = 16; noReceive++; if (noReceive == 3){ sprintf(buf, "Wakeup Error: Preamble not received\n\r"); //Need to set a Fault UART_Transmit_String(buf); } } } if ((noReceive == 0) && !noInc){ TXData++; } if (TXData < 19){ GPIO_setOutputHighOnPin(GPIO_PORT_P3, GPIO_PIN1); //Maxim chip select high __delay_cycles(1000); //idle time between CS change } } GPIO_setOutputHighOnPin(GPIO_PORT_P3, GPIO_PIN1); //Maxim chip select high __delay_cycles(1000); //idle time between CS change //Load WRITEALL sequence into the load queue WriteAll_transactions[0].Len = 7; WriteAll_transactions[0].Data[0] = 0xc0; //WR_LD_Q_SPI command byte WriteAll_transactions[0].Data[1] = 5; WriteAll_transactions[0].Data[2] = 0x02; //WRITEALL WriteAll_transactions[0].Data[3] = 0x12; //ADDRESS WriteAll_transactions[0].Data[4] = 0xb1; WriteAll_transactions[0].Data[5] = 0xb2; WriteAll_transactions[0].Data[6] = 0Xc4; //PEC byte // WriteAll_transactions[0].Data[7] = 0x0; //alive counter byte SPI_Send(WriteAll_transactions, 0); GPIO_setOutputHighOnPin(GPIO_PORT_P3, GPIO_PIN1); //Maxim chip select high __delay_cycles(1000); //idle time between CS change //Start transmitting the WRITEALL sequence from the transmit queue WriteAll_transactions[1].Len = 1; WriteAll_transactions[1].Data[0] = 0xb0; //WR_NXT_LD_Q_SPI command byte SPI_Send(WriteAll_transactions, 1); __delay_cycles(32000); GPIO_setOutputHighOnPin(GPIO_PORT_P3, GPIO_PIN1); //Maxim chip select high __delay_cycles(1000); //idle time between CS change WriteAll_transactions[2].Len = 2; WriteAll_transactions[2].Data[0] = 0x01; //Read RX_Status register WriteAll_transactions[2].Data[1] = 0x0; noReceive = 1; while ((noReceive > 0) && (noReceive < 3)){ SPI_Send(WriteAll_transactions, 2); if (RXData[WriteAll_transactions[2].Len-1] == 0x12){ sprintf(buf, "WRITEALL acknowledged\n\r"); UART_Transmit_String(buf); noReceive = 0; } else{ noReceive++; GPIO_setOutputHighOnPin(GPIO_PORT_P3, GPIO_PIN1); //Maxim chip select high __delay_cycles(1000); //idle time between CS change if (noReceive == 3){ sprintf(buf, "Writeall Error: not acknowledged\n\r"); //Need to set a Fault UART_Transmit_String(buf); } } } GPIO_setOutputHighOnPin(GPIO_PORT_P3, GPIO_PIN1); //Maxim chip select high __delay_cycles(1000); //idle time between CS change ReadAll_transactions[0].Len = 7; ReadAll_transactions[0].Data[0] = 0x93; ReadAll_transactions[0].Data[1] = 0x0; ReadAll_transactions[0].Data[2] = 0x0; ReadAll_transactions[0].Data[3] = 0x0; ReadAll_transactions[0].Data[4] = 0x0; ReadAll_transactions[0].Data[5] = 0x0; ReadAll_transactions[0].Data[6] = 0x0; SPI_Send(ReadAll_transactions, 0); GPIO_setOutputHighOnPin(GPIO_PORT_P3, GPIO_PIN1); //Maxim chip select high __delay_cycles(1000); //idle time between CS change ReadAll_transactions[1].Len = 2; ReadAll_transactions[1].Data[0] = 0x09; ReadAll_transactions[1].Data[1] = 0x0; SPI_Send(ReadAll_transactions, 0); GPIO_setOutputHighOnPin(GPIO_PORT_P3, GPIO_PIN1); //Maxim chip select high __delay_cycles(1000); //idle time between CS change } //****************************************************************************** // //This is the PORT2_VECTOR interrupt vector service routine // //****************************************************************************** #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector=PORT4_VECTOR __interrupt #elif defined(__GNUC__) __attribute__((interrupt(PORT2_VECTOR))) #endif void P4_ISR (void) { GPIO_clearInterrupt (GPIO_PORT_P4, GPIO_PIN2); // Toggle P1.0 output GPIO_toggleOutputOnPin (GPIO_PORT_P1, GPIO_PIN0); GPIO_setOutputHighOnPin(GPIO_PORT_P3, GPIO_PIN1); }