Part Number: MSP432P401R
Hello!
I am having a bit of a problem setting up an SPI transmission with an MSP432 microcontroller.
I am quite new to this controller, so maybe this question is obvious.
Basically I am trying to drive an EA DOGL-128 graphical LCD display with SPI interface.
This is how the spi interface is initialised:
#include <driverlib.h> #include <spi_drv.h> /* SPI Master Configuration Parameter */ const eUSCI_SPI_MasterConfig spiMasterConfig = { EUSCI_B_SPI_CLOCKSOURCE_SMCLK, // SMCLK Clock Source 12000000, // SMCLK = DCO = 12MHZ 10000, // SPICLK = 10khz EUSCI_B_SPI_MSB_FIRST, // MSB First EUSCI_B_SPI_PHASE_DATA_CHANGED_ONFIRST_CAPTURED_ON_NEXT, // Phase EUSCI_B_SPI_CLOCKPOLARITY_INACTIVITY_HIGH, // High polarity EUSCI_B_SPI_3PIN // 3Wire SPI Mode }; Public void spi_init(void) { /* Selecting P1.5 and P1.6 in SPI mode */ GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1, GPIO_PIN5 | GPIO_PIN6 , GPIO_PRIMARY_MODULE_FUNCTION); // Set pin 4.3 as CS pin. GPIO_setAsOutputPin(GPIO_PORT_P4, GPIO_PIN3); /* We should give a falling edge to CS pin, not entirely sure if this is necessary. */ /* Possibly we might have to catch the transmit interrupt and then control CS??? Not yet sure how this works. */ GPIO_setOutputHighOnPin(GPIO_PORT_P4, GPIO_PIN3); /* Configuring SPI in 3wire master mode */ SPI_initMaster(EUSCI_B0_BASE, &spiMasterConfig); /* Enable SPI module */ SPI_enableModule(EUSCI_B0_BASE); }
And this is what the transmit function looks like:
Public void spi_transmit_byte(U8 byte) { /* Polling to see if the TX buffer is ready */ while (!(SPI_getInterruptStatus(EUSCI_B0_BASE,EUSCI_B_SPI_TRANSMIT_INTERRUPT))); /* Transmitting data to slave */ SPI_transmitData(EUSCI_B0_BASE, byte); }
Now the SPI transmission itself works OK, checked with a logic analyser and it seems there is no problem with it.
The problem is that the LCD has an A0 pin that basically determines if the command I am sending should be interpreted
as writing data or as a command. The A0 pin needs to be set low/high at the end of the SPI byte transmission.
I tried controlling it like this at first:
Private void disp_command(U8 cmd, Boolean reg_select) { if (reg_select) { GPIO_setOutputHighOnPin(GPIO_PORT_P1, GPIO_PIN7); } else { GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN7); } spi_transmit_byte(cmd); }
But this did not work, because the A0 pin got set before the previous byte was finished sending.
So I tried to set A0 in the spi_transmit_byte function.
Public void spi_transmit_byte(U8 byte, Boolean reg_select) { /* Polling to see if the TX buffer is ready */ while (!(SPI_getInterruptStatus(EUSCI_B0_BASE,EUSCI_B_SPI_TRANSMIT_INTERRUPT))); /* Transmitting data to slave */ if (reg_select) { GPIO_setOutputHighOnPin(GPIO_PORT_P1, GPIO_PIN7); } else { GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN7); } SPI_transmitData(EUSCI_B0_BASE, byte); }
However in this case A0 is also set at the wrong time. More exactly it is set during the PREVIOUS
byte, so the transmission isn't correct. Basically the way I understand it, is that the EUSCI_B_SPI_TRANSMIT_INTERRUPT is raised
when the SPI interface is ready for a new byte, but the old one hasn't finished sending yet. What I need to do is somehow catch the moment
when the MCU starts to actually send a byte and then control the A0 pin. Right now I don't see a good way of doing this. maybe somebody has experience with a similar problem.
PS! In the code there are the following defines:
#define Public
#define Private static