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.
请问官方有给出msp430g系列 USI模块的SPI底层函数代码吗?我想深入学习一下430的spi.
msp430g系列是没有库函数的,都是直接操作寄存器。所以官网的例程没有所谓底层函数的说法。
上传两个例程,你参考下
//****************************************************************************** // MSP430G2xx3 Demo - USCI_A0, SPI 3-Wire Slave multiple byte RX/TX // // Description: SPI master communicates to SPI slave sending and receiving // 3 different messages of different length. SPI slave will enter LPM0 // while waiting for the messages to be sent/receiving using SPI interrupt. // ACLK = NA, MCLK = SMCLK = DCO 16MHz. // // // MSP430G2553 // ----------------- // /|\ | P2.0|<- Master's GPIO (Chip Select) // | | | // ---|RST RST |<- Master's GPIO (To reset slave) // | | // | P1.2|<- Data In (UCA0SIMO) // | | // | P1.1|-> Data Out (UCA0SOMI) // | | // | P1.4|<- Serial Clock In (UCA0CLK) // // Nima Eskandari // Texas Instruments Inc. // April 2017 // Built with CCS V7.0 //****************************************************************************** #include <msp430.h> #include <stdint.h> //****************************************************************************** // Example Commands ************************************************************ //****************************************************************************** #define DUMMY 0xFF #define SLAVE_CS_IN P2IN #define SLAVE_CS_DIR P2DIR #define SLAVE_CS_PIN BIT0 /* CMD_TYPE_X_SLAVE are example commands the master sends to the slave. * The slave will send example SlaveTypeX buffers in response. * * CMD_TYPE_X_MASTER are example commands the master sends to the slave. * The slave will initialize itself to receive MasterTypeX example buffers. * */ #define CMD_TYPE_0_SLAVE 0 #define CMD_TYPE_1_SLAVE 1 #define CMD_TYPE_2_SLAVE 2 #define CMD_TYPE_0_MASTER 3 #define CMD_TYPE_1_MASTER 4 #define CMD_TYPE_2_MASTER 5 #define TYPE_0_LENGTH 1 #define TYPE_1_LENGTH 2 #define TYPE_2_LENGTH 6 #define MAX_BUFFER_SIZE 20 /* MasterTypeX are example buffers initialized in the master, they will be * sent by the master to the slave. * SlaveTypeX are example buffers initialized in the slave, they will be * sent by the slave to the master. * */ uint8_t MasterType2 [TYPE_2_LENGTH] = {0}; uint8_t MasterType1 [TYPE_1_LENGTH] = { 0, 0}; uint8_t MasterType0 [TYPE_0_LENGTH] = { 0}; uint8_t SlaveType2 [TYPE_2_LENGTH] = {'A', 'B', 'C', 'D', '1', '2'}; uint8_t SlaveType1 [TYPE_1_LENGTH] = {0x15, 0x16}; uint8_t SlaveType0 [TYPE_0_LENGTH] = {12}; //****************************************************************************** // General SPI State Machine *************************************************** //****************************************************************************** typedef enum SPI_ModeEnum{ IDLE_MODE, TX_REG_ADDRESS_MODE, RX_REG_ADDRESS_MODE, TX_DATA_MODE, RX_DATA_MODE, TIMEOUT_MODE } SPI_Mode; /* Used to track the state of the software state machine*/ SPI_Mode SlaveMode = RX_REG_ADDRESS_MODE; /* The Register Address/Command to use*/ uint8_t ReceiveRegAddr = 0; /* ReceiveBuffer: Buffer used to receive data in the ISR * RXByteCtr: Number of bytes left to receive * ReceiveIndex: The index of the next byte to be received in ReceiveBuffer * TransmitBuffer: Buffer used to transmit data in the ISR * TXByteCtr: Number of bytes left to transfer * TransmitIndex: The index of the next byte to be transmitted in TransmitBuffer * */ uint8_t ReceiveBuffer[MAX_BUFFER_SIZE] = {0}; uint8_t RXByteCtr = 0; uint8_t ReceiveIndex = 0; uint8_t TransmitBuffer[MAX_BUFFER_SIZE] = {0}; uint8_t TXByteCtr = 0; uint8_t TransmitIndex = 0; /* Initialized the software state machine according to the received cmd * * cmd: The command/register address received * */ void SPI_Slave_ProcessCMD(uint8_t cmd); /* The transaction between the slave and master is completed. Uses cmd * to do post transaction operations. (Place data from ReceiveBuffer * to the corresponding buffer based in the last received cmd) * * cmd: The command/register address corresponding to the completed * transaction */ void SPI_Slave_TransactionDone(uint8_t cmd); void CopyArray(uint8_t *source, uint8_t *dest, uint8_t count); void SendUCA0Data(uint8_t val); void SendUCA0Data(uint8_t val) { while (!(IFG2 & UCA0TXIFG)); // USCI_A0 TX buffer ready? UCA0TXBUF = val; } void SPI_Slave_ProcessCMD(uint8_t cmd) { ReceiveIndex = 0; TransmitIndex = 0; RXByteCtr = 0; TXByteCtr = 0; switch (cmd) { case (CMD_TYPE_0_SLAVE): //Send slave device id (This device's id) SlaveMode = TX_DATA_MODE; TXByteCtr = TYPE_0_LENGTH; //Fill out the TransmitBuffer CopyArray(SlaveType0, TransmitBuffer, TYPE_0_LENGTH); //Send First Byte SendUCA0Data(TransmitBuffer[TransmitIndex++]); TXByteCtr--; break; case (CMD_TYPE_1_SLAVE): //Send slave device time (This device's time) SlaveMode = TX_DATA_MODE; TXByteCtr = TYPE_1_LENGTH; //Fill out the TransmitBuffer CopyArray(SlaveType1, TransmitBuffer, TYPE_1_LENGTH); //Send First Byte SendUCA0Data(TransmitBuffer[TransmitIndex++]); TXByteCtr--; break; case (CMD_TYPE_2_SLAVE): //Send slave device location (This device's location) SlaveMode = TX_DATA_MODE; TXByteCtr = TYPE_2_LENGTH; //Fill out the TransmitBuffer CopyArray(SlaveType2, TransmitBuffer, TYPE_2_LENGTH); //Send First Byte SendUCA0Data(TransmitBuffer[TransmitIndex++]); TXByteCtr--; break; case (CMD_TYPE_0_MASTER): SlaveMode = RX_DATA_MODE; RXByteCtr = TYPE_0_LENGTH; break; case (CMD_TYPE_1_MASTER): SlaveMode = RX_DATA_MODE; RXByteCtr = TYPE_1_LENGTH; break; case (CMD_TYPE_2_MASTER): SlaveMode = RX_DATA_MODE; RXByteCtr = TYPE_2_LENGTH; break; default: __no_operation(); break; } } void SPI_Slave_TransactionDone(uint8_t cmd) { switch (cmd) { case (CMD_TYPE_0_SLAVE): //Slave device id was sent(This device's id) break; case (CMD_TYPE_1_SLAVE): //Slave device time was sent(This device's time) break; case (CMD_TYPE_2_SLAVE): //Send slave device location (This device's location) break; case (CMD_TYPE_0_MASTER): CopyArray(ReceiveBuffer, MasterType0, TYPE_0_LENGTH); break; case (CMD_TYPE_1_MASTER): CopyArray(ReceiveBuffer, MasterType1, TYPE_1_LENGTH); break; case (CMD_TYPE_2_MASTER): CopyArray(ReceiveBuffer, MasterType2, TYPE_2_LENGTH); break; default: __no_operation(); break; } } void CopyArray(uint8_t *source, uint8_t *dest, uint8_t count) { uint8_t copyIndex = 0; for (copyIndex = 0; copyIndex < count; copyIndex++) { dest[copyIndex] = source[copyIndex]; } } //****************************************************************************** // Device Initialization ******************************************************* //****************************************************************************** void initClockTo16MHz() { if (CALBC1_16MHZ==0xFF) // If calibration constant erased { while(1); // do not load, trap CPU!! } DCOCTL = 0; // Select lowest DCOx and MODx settings BCSCTL1 = CALBC1_16MHZ; // Set DCO DCOCTL = CALDCO_16MHZ; } void initGPIO() { //SPI Pins P1SEL = BIT1 + BIT2 + BIT4; P1SEL2 = BIT1 + BIT2 + BIT4; //LEDs P1DIR |= BIT0 + BIT6; P1OUT &= ~(BIT0 + BIT6); } void initSPI() { UCA0CTL1 = UCSWRST; // **Put state machine in reset** UCA0CTL0 |= UCCKPL + UCMSB + UCSYNC; // 3-pin, 8-bit SPI Slave UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine** IE2 |= UCA0RXIE; // Enable USCI0 RX interrupt SLAVE_CS_DIR &= ~(SLAVE_CS_PIN); } //****************************************************************************** // Main ************************************************************************ // Enters LPM0 and waits for SPI interrupts. The data sent from the master is * // then interpreted and the device will respond accordingly * //****************************************************************************** int main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer while (!(P1IN & BIT4)); // If clock sig from mstr stays low, // it is not yet in SPI mode initClockTo16MHz(); initGPIO(); initSPI(); __bis_SR_register(LPM0_bits + GIE); // Enter LPM4, enable interrupts __no_operation(); return 0; } //****************************************************************************** // SPI Interrupt *************************************************************** //****************************************************************************** #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector=USCIAB0RX_VECTOR __interrupt void USCI0RX_ISR (void) #elif defined(__GNUC__) void __attribute__ ((interrupt(USCIAB0RX_VECTOR))) USCI0RX_ISR (void) #else #error Compiler not supported! #endif { if (IFG2 & UCA0RXIFG) { unsigned char uca0_rx_val = UCA0RXBUF; if (!(SLAVE_CS_IN & SLAVE_CS_PIN)) { switch (SlaveMode) { case (RX_REG_ADDRESS_MODE): ReceiveRegAddr = uca0_rx_val; SPI_Slave_ProcessCMD(ReceiveRegAddr); break; case (RX_DATA_MODE): ReceiveBuffer[ReceiveIndex++] = uca0_rx_val; RXByteCtr--; if (RXByteCtr == 0) { //Done Receiving MSG SlaveMode = RX_REG_ADDRESS_MODE; SPI_Slave_TransactionDone(ReceiveRegAddr); } break; case (TX_DATA_MODE): if (TXByteCtr > 0) { SendUCA0Data(TransmitBuffer[TransmitIndex++]); TXByteCtr--; } if (TXByteCtr == 0) { //Done Transmitting MSG SlaveMode = RX_REG_ADDRESS_MODE; SPI_Slave_TransactionDone(ReceiveRegAddr); } break; default: __no_operation(); break; } } } }
//****************************************************************************** // MSP430G2xx3 Demo - USCI_A0, SPI 3-Wire Master multiple byte RX/TX // // Description: SPI master communicates to SPI slave sending and receiving // 3 different messages of different length. SPI master will enter LPM0 mode // while waiting for the messages to be sent/receiving using SPI interrupt. // SPI Master will initially wait for a port interrupt in LPM0 mode before // starting the SPI communication. // ACLK = NA, MCLK = SMCLK = DCO 16MHz. // // // MSP430G2553 // ----------------- // /|\ | P2.0|-> Slave Chip Select (GPIO) // | | | // ---|RST P1.5|-> Slave Reset (GPIO) // | | // | P1.2|-> Data Out (UCA0SIMO) // | | // Button ->|P1.3 P1.1|<- Data In (UCA0SOMI) // | | // | P1.4|-> Serial Clock Out (UCA0CLK) // // Nima Eskandari // Texas Instruments Inc. // April 2017 // Built with CCS V7.0 //****************************************************************************** #include <msp430.h> #include <stdint.h> //****************************************************************************** // Example Commands ************************************************************ //****************************************************************************** #define DUMMY 0xFF #define SLAVE_CS_OUT P2OUT #define SLAVE_CS_DIR P2DIR #define SLAVE_CS_PIN BIT0 /* CMD_TYPE_X_SLAVE are example commands the master sends to the slave. * The slave will send example SlaveTypeX buffers in response. * * CMD_TYPE_X_MASTER are example commands the master sends to the slave. * The slave will initialize itself to receive MasterTypeX example buffers. * */ #define CMD_TYPE_0_SLAVE 0 #define CMD_TYPE_1_SLAVE 1 #define CMD_TYPE_2_SLAVE 2 #define CMD_TYPE_0_MASTER 3 #define CMD_TYPE_1_MASTER 4 #define CMD_TYPE_2_MASTER 5 #define TYPE_0_LENGTH 1 #define TYPE_1_LENGTH 2 #define TYPE_2_LENGTH 6 #define MAX_BUFFER_SIZE 20 /* MasterTypeX are example buffers initialized in the master, they will be * sent by the master to the slave. * SlaveTypeX are example buffers initialized in the slave, they will be * sent by the slave to the master. * */ uint8_t MasterType0 [TYPE_0_LENGTH] = {0x11}; uint8_t MasterType1 [TYPE_1_LENGTH] = {8, 9}; uint8_t MasterType2 [TYPE_2_LENGTH] = {'F', '4' , '1' , '9', '2', 'B'}; uint8_t SlaveType2 [TYPE_2_LENGTH] = {0}; uint8_t SlaveType1 [TYPE_1_LENGTH] = {0}; uint8_t SlaveType0 [TYPE_0_LENGTH] = {0}; //****************************************************************************** // General SPI State Machine *************************************************** //****************************************************************************** typedef enum SPI_ModeEnum{ IDLE_MODE, TX_REG_ADDRESS_MODE, RX_REG_ADDRESS_MODE, TX_DATA_MODE, RX_DATA_MODE, TIMEOUT_MODE } SPI_Mode; /* Used to track the state of the software state machine*/ SPI_Mode MasterMode = IDLE_MODE; /* The Register Address/Command to use*/ uint8_t TransmitRegAddr = 0; /* ReceiveBuffer: Buffer used to receive data in the ISR * RXByteCtr: Number of bytes left to receive * ReceiveIndex: The index of the next byte to be received in ReceiveBuffer * TransmitBuffer: Buffer used to transmit data in the ISR * TXByteCtr: Number of bytes left to transfer * TransmitIndex: The index of the next byte to be transmitted in TransmitBuffer * */ uint8_t ReceiveBuffer[MAX_BUFFER_SIZE] = {0}; uint8_t RXByteCtr = 0; uint8_t ReceiveIndex = 0; uint8_t TransmitBuffer[MAX_BUFFER_SIZE] = {0}; uint8_t TXByteCtr = 0; uint8_t TransmitIndex = 0; /* SPI Write and Read Functions */ /* For slave device, writes the data specified in *reg_data * * reg_addr: The register or command to send to the slave. * Example: CMD_TYPE_0_MASTER * *reg_data: The buffer to write * Example: MasterType0 * count: The length of *reg_data * Example: TYPE_0_LENGTH * */ SPI_Mode SPI_Master_WriteReg(uint8_t reg_addr, uint8_t *reg_data, uint8_t count); /* For slave device, read the data specified in slaves reg_addr. * The received data is available in ReceiveBuffer * * reg_addr: The register or command to send to the slave. * Example: CMD_TYPE_0_SLAVE * count: The length of data to read * Example: TYPE_0_LENGTH * */ SPI_Mode SPI_Master_ReadReg(uint8_t reg_addr, uint8_t count); void CopyArray(uint8_t *source, uint8_t *dest, uint8_t count); void SendUCA0Data(uint8_t val); void CopyArray(uint8_t *source, uint8_t *dest, uint8_t count) { uint8_t copyIndex = 0; for (copyIndex = 0; copyIndex < count; copyIndex++) { dest[copyIndex] = source[copyIndex]; } } SPI_Mode SPI_Master_WriteReg(uint8_t reg_addr, uint8_t *reg_data, uint8_t count) { MasterMode = TX_REG_ADDRESS_MODE; TransmitRegAddr = reg_addr; //Copy register data to TransmitBuffer CopyArray(reg_data, TransmitBuffer, count); TXByteCtr = count; RXByteCtr = 0; ReceiveIndex = 0; TransmitIndex = 0; SLAVE_CS_OUT &= ~(SLAVE_CS_PIN); SendUCA0Data(TransmitRegAddr); __bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ interrupts SLAVE_CS_OUT |= SLAVE_CS_PIN; return MasterMode; } SPI_Mode SPI_Master_ReadReg(uint8_t reg_addr, uint8_t count) { MasterMode = TX_REG_ADDRESS_MODE; TransmitRegAddr = reg_addr; RXByteCtr = count; TXByteCtr = 0; ReceiveIndex = 0; TransmitIndex = 0; SLAVE_CS_OUT &= ~(SLAVE_CS_PIN); SendUCA0Data(TransmitRegAddr); __bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ interrupts SLAVE_CS_OUT |= SLAVE_CS_PIN; return MasterMode; } void SendUCA0Data(uint8_t val) { while (!(IFG2 & UCA0TXIFG)); // USCI_A0 TX buffer ready? UCA0TXBUF = val; } //****************************************************************************** // Device Initialization ******************************************************* //****************************************************************************** void initClockTo16MHz() { if (CALBC1_16MHZ==0xFF) // If calibration constant erased { while(1); // do not load, trap CPU!! } DCOCTL = 0; // Select lowest DCOx and MODx settings BCSCTL1 = CALBC1_16MHZ; // Set DCO DCOCTL = CALDCO_16MHZ; } void initGPIO() { //LEDs P1OUT = 0x00; // P1 setup for LED & reset output P1DIR |= BIT0 + BIT5 + BIT6; //SPI Pins P1SEL = BIT1 + BIT2 + BIT4; P1SEL2 = BIT1 + BIT2 + BIT4; //Button to initiate transfer P1DIR &= ~(BIT3); P1OUT |= BIT3; // P1.3 pull up P1REN |= BIT3; // P1.3 pull up/down resistor enable P1IE |= BIT3; // P1.3 interrupt enabled P1IES |= BIT3; // P1.3 Hi/lo edge P1IFG &= ~BIT3; // P1.3 IFG cleared } void initSPI() { //Clock Polarity: The inactive state is high //MSB First, 8-bit, Master, 3-pin mode, Synchronous UCA0CTL0 |= UCCKPL + UCMSB + UCMST + UCSYNC; UCA0CTL1 |= UCSSEL_2; // SMCLK UCA0BR0 |= 0x20; // /2 UCA0BR1 = 0; // UCA0MCTL = 0; // No modulation must be cleared for SPI UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine** IE2 |= UCA0RXIE; // Enable USCI0 RX interrupt SLAVE_CS_DIR |= SLAVE_CS_PIN; SLAVE_CS_OUT |= SLAVE_CS_PIN; } //****************************************************************************** // Main ************************************************************************ // Send and receive three messages containing the example commands ************* //****************************************************************************** int main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer initClockTo16MHz(); initGPIO(); initSPI(); P1OUT &= ~BIT5; // Now with SPI signals initialized, __delay_cycles(100000); P1OUT |= BIT5; // reset slave __delay_cycles(100000); // Wait for slave to initialize P1OUT |= BIT0; __bis_SR_register(LPM0_bits + GIE); // CPU off, enable interrupts SPI_Master_ReadReg(CMD_TYPE_2_SLAVE, TYPE_2_LENGTH); CopyArray(ReceiveBuffer, SlaveType2, TYPE_2_LENGTH); SPI_Master_ReadReg(CMD_TYPE_1_SLAVE, TYPE_1_LENGTH); CopyArray(ReceiveBuffer, SlaveType1, TYPE_1_LENGTH); SPI_Master_ReadReg(CMD_TYPE_0_SLAVE, TYPE_0_LENGTH); CopyArray(ReceiveBuffer, SlaveType0, TYPE_0_LENGTH); SPI_Master_WriteReg(CMD_TYPE_2_MASTER, MasterType2, TYPE_2_LENGTH); SPI_Master_WriteReg(CMD_TYPE_1_MASTER, MasterType1, TYPE_1_LENGTH); SPI_Master_WriteReg(CMD_TYPE_0_MASTER, MasterType0, TYPE_0_LENGTH); __bis_SR_register(LPM0_bits + GIE); } //****************************************************************************** // SPI Interrupt *************************************************************** //****************************************************************************** #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector=USCIAB0RX_VECTOR __interrupt void USCIA0RX_ISR(void) #elif defined(__GNUC__) void __attribute__ ((interrupt(USCIAB0RX_VECTOR))) USCIA0RX_ISR (void) #else #error Compiler not supported! #endif { if (IFG2 & UCA0RXIFG) { uint8_t uca0_rx_val = UCA0RXBUF; switch (MasterMode) { case TX_REG_ADDRESS_MODE: if (RXByteCtr) { MasterMode = RX_DATA_MODE; // Need to start receiving now //Send Dummy To Start __delay_cycles(2000); SendUCA0Data(DUMMY); } else { MasterMode = TX_DATA_MODE; // Continue to transmision with the data in Transmit Buffer //Send First SendUCA0Data(TransmitBuffer[TransmitIndex++]); TXByteCtr--; } break; case TX_DATA_MODE: if (TXByteCtr) { SendUCA0Data(TransmitBuffer[TransmitIndex++]); TXByteCtr--; } else { //Done with transmission MasterMode = IDLE_MODE; __bic_SR_register_on_exit(CPUOFF); // Exit LPM0 } break; case RX_DATA_MODE: if (RXByteCtr) { ReceiveBuffer[ReceiveIndex++] = uca0_rx_val; //Transmit a dummy RXByteCtr--; } if (RXByteCtr == 0) { MasterMode = IDLE_MODE; __bic_SR_register_on_exit(CPUOFF); // Exit LPM0 } else { SendUCA0Data(DUMMY); } break; default: __no_operation(); break; } __delay_cycles(50); } } //****************************************************************************** // PORT1 Interrupt ************************************************************* // Interrupt occurs on button press and initiates the SPI data transfer ******** //****************************************************************************** #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector=PORT1_VECTOR __interrupt void Port_1(void) #elif defined(__GNUC__) void __attribute__ ((interrupt(PORT1_VECTOR))) Port_1 (void) #else #error Compiler not supported! #endif { P1OUT |= BIT6; P1IFG &= ~BIT3; // P1.3 IFG cleared P1IE &= ~BIT3; //Initiate __bic_SR_register_on_exit(LPM0_bits); // Exit LPM0 }