This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] LP-MSP430FR2476:来自 MAX17841从设备的 SPI 轮询中断

Guru**** 2386620 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1046884/lp-msp430fr2476-spi-polling-interrupt-from-max17841-slave

器件型号:LP-MSP430FR2476

您好!

由于某种原因、我对 MAX17841唤醒序列的结果有了很大的改进、目前只有一个 MAX17853连接到 MAX17841即可观察到这一点。 以前、我可以使用 Maxim 评估 GUI 与连接到 MAX17841的两个 MAX17853通信。

来自 MSP 430的所有 SPI 事务在范围上看起来都是准确的、包括来自 MAX17853的响应。 但在唤醒结束时、来自 MAX17841的 INT'输入不会触发。 我很感谢有人提出这种情况的原因。  启用不同的接收中断标志并不会产生不同的效果(事务2)。

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>

#include <driverlib.h>
#include <msp430.h> 
#include "clock~.h"                 // Clock configurations


static uint8_t TXData = 0;           //transaction count
static uint8_t RXData = 0;           //SPI receive byte


typedef struct {
    uint8_t    Len;
    uint8_t    Data[5];
} spi_MaximTrans_t;

static spi_MaximTrans_t DCInit_transactions[15];


uint8_t SPI_TX_index = 0;            //byte count in transaction



/**
 *  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, &param);

    //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()
{
    //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, &param);

        EUSCI_A_SPI_enable(EUSCI_A1_BASE);

}


void SetUpTransactions(void){       //All transactions padded to 4 bytes
    //Enable keep alive mode
    DCInit_transactions[0].Len = 2;
    DCInit_transactions[0].Data[0] = 0x10;
    DCInit_transactions[0].Data[1] = 0x5;

    DCInit_transactions[1].Len = 2;
    DCInit_transactions[1].Data[0] = 0x11;
    DCInit_transactions[1].Data[1] = 0x0;       //Read Transaction 1 byte

    //Enable Rx Interrupt flags
    DCInit_transactions[2].Len = 2;
    DCInit_transactions[2].Data[0] = 0x4;
    DCInit_transactions[2].Data[1] = 0x89;      //No Receive

    DCInit_transactions[3].Len = 2;
    DCInit_transactions[3].Data[0] = 0x5;
    DCInit_transactions[3].Data[1] = 0x0;      //Read Transaction 2 byte

    //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
    //2ms delay for each slave to wake up
    DCInit_transactions[6].Len = 2;
    DCInit_transactions[6].Data[0] = 0x0f;
    DCInit_transactions[6].Data[1] = 0x0;       //Read Transaction 4 byte

    //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;

    DCInit_transactions[9].Len = 2;
    DCInit_transactions[9].Data[0] = 0x0f;
    DCInit_transactions[9].Data[1] = 0x0;       //Read Transaction 5 byte
                                                //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

}


/**
 * main.c
 */
int main(void)
{

    static uint8_t noReceive = 0;
    static uint8_t noInc = 0;

    WDTCTL = WDTPW | WDTHOLD;   // stop watchdog timer


    init_clock();
    init_gpio();                                    // Set up IO pins

    GPIO_setOutputHighOnPin(GPIO_PORT_P3, GPIO_PIN1);

    // Configure SPI Pins for UCA1CLK, UCA1TXD/UCA1SIMO and UCA1RXD/UCA1SOMI
    /*
    * Select Port 2
    * Set Pin 4, Pin 5 and Pin 6 to input Secondary Module Function
    */
    GPIO_setAsPeripheralModuleFunctionInputPin(
        GPIO_PORT_P2,
        GPIO_PIN4 + GPIO_PIN5 + GPIO_PIN6,
        GPIO_PRIMARY_MODULE_FUNCTION
    );

    // 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();


    SetUpTransactions();
    TXData = 0x0;                             // Holds transaction number


    // Setup peripheral(s) now that gpio and clocks are setup
    init_spi_peripheral();                      // Init Maxim spi peripheral

    GPIO_setOutputHighOnPin (GPIO_PORT_P6, GPIO_PIN2);              //SHDNL held high for 4ms to ensure all slaves are powered on
    __delay_cycles(64000);



    while (TXData < 13){
        noInc = 0;
        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 < DCInit_transactions[TXData].Len; SPI_TX_index++){
            while(!(UCA1IFG & UCTXIFG));
            UCA1TXBUF = DCInit_transactions[TXData].Data[SPI_TX_index];
            while (!(UCA1IFG & UCRXIFG));
               RXData = UCA1RXBUF;
        }

        if ((TXData == 6) || (TXData == 9))
            __delay_cycles(64000);    //wait for slaves to wake up

        if (TXData == 7){
            if (RXData == 0x21){
               TXData++;
               noReceive = 0;
               noInc = 1;
            }
            if (RXData != 0x21){
               TXData = 7;
               noReceive = 1;
            }
         }
         if (TXData == 10){
            if ((RXData == 0x10) || (RXData == 0x12)){
               TXData++;
               noReceive = 0;
               noInc = 1;
            }
            else{
               TXData = 10;
               noReceive = 1;
            }
         }
         if (!noReceive && !noInc){
             TXData++;
         }

         if (TXData < 13){
             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_setOutputHighOnPin(GPIO_PORT_P3, GPIO_PIN1);
    GPIO_clearInterrupt (GPIO_PORT_P4, GPIO_PIN2);
    // Toggle P1.0 output
    GPIO_toggleOutputOnPin (GPIO_PORT_P1, GPIO_PIN0);

    GPIO_disableInterrupt (GPIO_PORT_P4, GPIO_PIN2);
    GPIO_setOutputHighOnPin(GPIO_PORT_P3, GPIO_PIN1);        //Maxim chip select high
}


  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    如何判断/INT 未发出? 您是否观察到(a)示波器或(b) P1.0 LED?

    我看不到您在哪里启用中断(GIE)。 请尝试在启动事务列表之前插入:

    >_enable_interrupt (); // GIE=1