我将 SPI 设置为轮询模式、正如我最近的主题中所述。
LP-MSP430FR2476:SPI 发送和接收中断- MSP 低功耗微控制器论坛- MSP 低功耗微控制器- TI E2E 支持论坛
根据 MSP430用户指南 slau445i、发送和接收操作同时发生。 如果从器件需要响应、该接收字节何时会出现在 MISO 上? 在示波器视图中、我可以看到所有传输的字节、但 MISO 线路上没有活动。
#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];
uint8_t RxFlag;
} 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, ¶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()
{
//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 = 0;
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 SetUpTransactions(void){ //All transactions padded to 4 bytes
//Enable keep alive mode
DCInit_transactions[0].Len = 4;
DCInit_transactions[0].Data[0] = 0x10;
DCInit_transactions[0].Data[1] = 0x5;
DCInit_transactions[0].Data[2] = 0x11;
DCInit_transactions[0].Data[3] = 0x0;
DCInit_transactions[0].RxFlag = 0x0; //No Receive
//Enable Rx Interrupt flags
DCInit_transactions[1].Len = 4;
DCInit_transactions[1].Data[0] = 0x4;
DCInit_transactions[1].Data[1] = 0x88;
DCInit_transactions[1].Data[2] = 0x0;
DCInit_transactions[1].Data[3] = 0x0;
DCInit_transactions[1].RxFlag = 0x0; //No Receive
//Clear receive buffer
DCInit_transactions[2].Len = 4;
DCInit_transactions[2].Data[0] = 0xe0;
DCInit_transactions[2].Data[1] = 0x0;
DCInit_transactions[2].Data[2] = 0x0;
DCInit_transactions[2].Data[3] = 0x0;
DCInit_transactions[2].RxFlag = 0x0; //No Receive
//Wakeup UART slave devices
DCInit_transactions[3].Len = 4;
DCInit_transactions[3].Data[0] = 0xe0;
DCInit_transactions[3].Data[1] = 0x30;
DCInit_transactions[3].Data[2] = 0x0;
DCInit_transactions[3].Data[3] = 0x0;
DCInit_transactions[3].RxFlag = 0x0; //No Receive
//2ms delay for each slave to wake up
//Wait for all UART slave devices to wake up
DCInit_transactions[4].Len = 4;
DCInit_transactions[4].Data[0] = 0x01;
DCInit_transactions[4].Data[1] = 0x0;
DCInit_transactions[4].Data[2] = 0x0;
DCInit_transactions[4].Data[3] = 0x91;
DCInit_transactions[4].RxFlag = 0x1; //Receive of 0x21 expected
//Read message command. This was added to see a SPI receive byte on the MSP430
//Without this, there was no change in the SPI receive buffer.
//End of UART slave device wake-up period
DCInit_transactions[5].Len = 4;
DCInit_transactions[5].Data[0] = 0x0e;
DCInit_transactions[5].Data[1] = 0x10;
DCInit_transactions[5].Data[2] = 0x0;
DCInit_transactions[5].Data[3] = 0x0;
DCInit_transactions[5].RxFlag = 0x0; //No Receive
//2ms delay for each slave to report null message
//Wait for null message to be received
DCInit_transactions[6].Len = 4;
DCInit_transactions[6].Data[0] = 0x01;
DCInit_transactions[6].Data[1] = 0x0;
DCInit_transactions[6].Data[2] = 0x0;
DCInit_transactions[6].Data[3] = 0x0;
DCInit_transactions[6].RxFlag = 0x1; //Receive 0x10 or 0x12
//Clear transmit buffer
DCInit_transactions[7].Len = 4;
DCInit_transactions[7].Data[0] = 0x20;
DCInit_transactions[7].Data[1] = 0x0;
DCInit_transactions[7].Data[2] = 0x0;
DCInit_transactions[7].Data[3] = 0x0;
DCInit_transactions[7].RxFlag = 0x0; //No Receive
//Clear receive buffer
DCInit_transactions[8].Len = 4;
DCInit_transactions[8].Data[0] = 0xe0;
DCInit_transactions[8].Data[1] = 0x0;
DCInit_transactions[8].Data[2] = 0x0;
DCInit_transactions[8].Data[3] = 0x0;
DCInit_transactions[8].RxFlag = 0x0; //No Receive
}
/**
* main.c
*/
int main(void)
{
uint32_t i;
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);
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_setOutputLowOnPin(GPIO_PORT_P3, GPIO_PIN1); //Maxim chip select low
for(i=10000; i>0; i--); //idle time between SPI transactions
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;
}
TXData = 1;
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;
}
TXData = 2;
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;
}
TXData = 3;
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;
}
__delay_cycles(64000);
TXData = 4;
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 == 4) && (RXData == 0x21)){
DCInit_transactions[TXData].RxFlag = 0;
TXData = 5;
}
// GPIO_setOutputHighOnPin(GPIO_PORT_P3, GPIO_PIN1); //Maxim chip select high
}
//******************************************************************************
//
//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);
}