Made a simple translation of the User's guide and added some of my own understanding.
I have written SPI with analog IO before, and today I will try to learn the built-in SPI module
1. Basic
1.1 SPI operation mode
In SPI mode, serial data will be accepted by multiple devices through a shared clock provided by the master and send. An additional pin, UCxSTE, provides transmit and transmit enable.
Three or four pins can be set for SPI data exchange
UCxSIMO: slave in, master out
UCxSOMI: slave out, master in
UCxCLK: SPI clock
UCxSTE: slave transfer enable
when four pins are enabled Multiple devices share one bus, not used in 3-pin mode
1.2 SPI initialization and reset
are the same as UART settings, USCI is reset by PUC or UCSWRST. When configuring, first UCSWRST=1, then configure the port, then UCSWRST=0, and finally enable the interrupt.
1.3 Master mode (Master mode)
The schematic diagram of both master mode and slave mode is very simple...
1.4 Slave mode
1.5 Transmit enable and receive enable
In master mode, when data is written into UCxTXBUF, the clock is generated, Data transfer starts.
In slave mode, transfers occur when the master provides the clock.
The SPI accepts data when a transmit is enabled, and the receive and transmit can occur simultaneously.
1.6 Clock control.
UCxCLK is provided by the host, when UCMST=1, bit CLK is provided by UCxCLK pin. When UCMST=0, the clock is provided by the master (this time it is a slave). When transmitting, both sending and receiving use the same clock and the same speed.
16-bit clock rate control registers: UCxxBR1 and BR0, same as UART mode. But this is bit clkock. Modulation is not needed in SPI mode. In USCI_A, UCAxMTL should be cleared.
The calculation formula is:
fbit-clock=fBRCLK/UCBRx
1.7 Polarity and phase
SPI has four modes, the difference is polarity and phase, which can be simply regarded as the difference between transmitting or receiving data at the rising or falling edge.
For details, you can go to this blog https://www.cnblogs.com/shangdawei/p/4752476.html,
which is very clear.
We only need to pay attention to the UCCKPH UCCKPL in this, which determines how the data is transmitted. When looking at the data sheet of the component, you need to observe the given timing diagram to determine how to configure it.
1.8 Interrupt
The interrupt is basically similar to UART, which was mentioned when writing UART before.
2. Register
This is not the same as the register that UART needs to configure, but the difference is mainly on CTL0.
2.1UCAxCTL0
UCCKPH, UCCKPL, timing configuration.
UCMSB: Transmit from LSB or MSB when transmitting
UC7BIT: Select seven-bit data or eight-bit data
UCMST: Select master or slave
UCMODEx: Three-pin four-pin mode selection
UCSYNC: Communication mode, 0 for asynchronous communication (UART)
1 for Synchronous communication (SPI)
must be configured as 1 at this time.
Others are relatively simple and will not be described in detail.
Third, the code can look at the routine.
The routine is also relatively simple, you can use two 430 microcontrollers for SPI communication experiments.
(A specific example may be placed in a few days)
/*
MSP430F55xx_uscia0_spi_09
主机模式
主机发送一个数据,从机返回,用LED来表征
*/
#include <msp430.h>
unsigned char MST_Data,SLV_Data;
unsigned char temp;
int main(void)
{
volatile unsigned int i;
WDTCTL = WDTPW+WDTHOLD; // Stop watchdog timer
P1OUT |= 0x02; // Set P1.0 for LED
// Set P1.1 for slave reset
P1DIR |= 0x03; // Set P1.0-2 to output direction
P3SEL |= BIT3+BIT4; // P3.3,4 option select
P2SEL |= BIT7; // P2.7 option select
UCA0CTL1 |= UCSWRST; // **Put state machine in reset**
UCA0CTL0 |= UCMST+UCSYNC+UCCKPL+UCMSB; // 3-pin, 8-bit SPI master
// Clock polarity high, MSB
UCA0CTL1 |= UCSSEL_2; // SMCLK
UCA0BR0 = 0x02; // /2
UCA0BR1 = 0; //
UCA0MCTL = 0; // No modulation
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
UCA0IE |= UCRXIE; // Enable USCI_A0 RX interrupt
P1OUT &= ~0x02; // Now with SPI signals initialized,
P1OUT |= 0x02; // reset slave
for(i=50;i>0;i--); // Wait for slave to initialize
MST_Data = 0x01; // Initialize data values
SLV_Data = 0x00; //
while (!(UCA0IFG&UCTXIFG)); // USCI_A0 TX buffer ready?
UCA0TXBUF = MST_Data; // Transmit first character
__bis_SR_register(LPM0_bits + GIE); // CPU off, enable interrupts
}
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=USCI_A0_VECTOR
__interrupt void USCI_A0_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCI_A0_VECTOR))) USCI_A0_ISR (void)
#else
#error Compiler not supported!
#endif
{
volatile unsigned int i;
switch(__even_in_range(UCA0IV,4))
{
case 0: break; // Vector 0 - no interrupt
case 2: // Vector 2 - RXIFG
while (!(UCA0IFG&UCTXIFG)); // USCI_A0 TX buffer ready?
if (UCA0RXBUF==SLV_Data) // Test for correct character RX'd
P1OUT |= 0x01; // If correct, light LED
else
P1OUT &= ~0x01; // If incorrect, clear LED
MST_Data++; // Increment data
SLV_Data++;
UCA0TXBUF = MST_Data; // Send next value
for(i = 20; i>0; i--); // Add time between transmissions to
// make sure slave can process information
break;
case 4: break; // Vector 4 - TXIFG
default: break;
}
}
//
/*
MSP430F55xx_uscia0_spi_10
从机模式
将主机传来的数据发送回去
*/
#include <msp430.h>
int main(void)
{
WDTCTL = WDTPW+WDTHOLD; // Stop watchdog timer
while(!(P2IN&0x80)); // If clock sig from mstr stays low,
// it is not yet in SPI mode
P3SEL |= BIT3+BIT4; // P3.3,4 option select
P2SEL |= BIT7; // P2.7 option select
UCA0CTL1 |= UCSWRST; // **Put state machine in reset**
UCA0CTL0 |= UCSYNC+UCCKPL+UCMSB; // 3-pin, 8-bit SPI slave,
// Clock polarity high, MSB
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
UCA0IE |= UCRXIE; // Enable USCI_A0 RX interrupt
__bis_SR_register(LPM4_bits + GIE); // Enter LPM4, enable interrupts
}
// Echo character
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=USCI_A0_VECTOR
__interrupt void USCI_A0_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCI_A0_VECTOR))) USCI_A0_ISR (void)
#else
#error Compiler not supported!
#endif
{
switch(__even_in_range(UCA0IV,4))
{
case 0:break; // Vector 0 - no interrupt
case 2: // Vector 2 - RXIFG
while (!(UCA0IFG&UCTXIFG)); // USCI_A0 TX buffer ready?
UCA0TXBUF = UCA0RXBUF;
break;
case 4:break; // Vector 4 - TXIFG
default: break;
}
}