Part Number:MSP430G2553
Tool/software: Code Composer Studio
Hi all,
I am trying to connect SPI flash (W25Q80DVSSIG-ND(Please visit the site to view this file)) to MSP430g2553 launch pad. Here I made the connections as below
P1.1 SOMI <---------- 2nd Pin DO
P1.2 SIMO ----------->5th Pin DI
P1.4 SCLK ----------->6th Pin CLK
P2.0 SS ------------>1st Pin CS
I tried to use example code from TI to get the manufacturer id and device id. But I am failing to receive the expected data. Please have a look into my code and tell me if I made any mistakes. Please find the attachment for the data sheet of Winbond W25Q80DV spi flash memory.
And if anyone have sample codes or driver codes please do share with me.
Thanks in Advance.
Regards
Santhosh
//******************************************************************************
// 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 MasterType3 [3] = {0,0,0};
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;
uint8_t uca0_rx_val = 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 = UCSWRST;
UCA0CTL0 |= UCCKPH + UCMSB + UCMST + UCSYNC; //Clock Polarity: The inactive state is LOW
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);
// SPI_Master_WriteReg(0x90, MasterType3, 3);
SLAVE_CS_OUT &= ~(SLAVE_CS_PIN);
SendUCA0Data(0x06); //Sending Write Enable command
SLAVE_CS_OUT |= SLAVE_CS_PIN;
__bis_SR_register(LPM0_bits + GIE);
SLAVE_CS_OUT &= ~(SLAVE_CS_PIN); //Sending Read Manufacturer ID command
SendUCA0Data(0x90); //Instruction
SendUCA0Data(0x00); //24 bit address (000000h)
SendUCA0Data(0x00);
SendUCA0Data(0x00);
SLAVE_CS_OUT |= SLAVE_CS_PIN;
// SLAVE_CS_OUT &= ~(SLAVE_CS_PIN);
// SendUCA0Data(0x03);
// SendUCA0Data(0x02);
// SendUCA0Data(0x01);
// SendUCA0Data(0x00);
// SendUCA0Data(0x41);
// SendUCA0Data(0x42);
// SendUCA0Data(0x43);
// SendUCA0Data(0x44);
// __bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ interrupts
// SLAVE_CS_OUT |= SLAVE_CS_PIN;
__bis_SR_register(LPM0_bits + GIE);
while(1)
{
}
}
//******************************************************************************
// 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)
{
uca0_rx_val = UCA0RXBUF; //Checking here the data I receive while I am in Debugging...
/*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
}