0
votes

I'm trying to write a program using the LPC1788 microcontroller, and I need to send and transmit data to a UFDC (universal frequency-to-digital converter) using SPI protocol. A datasheet for this can be found here. My microcontroller's SSP controller is set as the master and the UFDC presumably becomes the slave. I'm able to transmit information down the MOSI line and see the data appear on an oscilloscope. However, when I try to receive data on the MISO line, I only get back what I sent down the MOSI.

Here is a picture of the schematic.

The relevant part of the code I've written is below:

SSP_CFG_Type sspConfig;
SSP_DATA_SETUP_Type sspData;
LPC_SSP_TypeDef *SSPx = NULL;

UFDC_RESULT_T result_SSP0_FX1, result_SSP0_FX2;
UFDC_RESULT_T result_SSP1_FX1, result_SSP1_FX2;
UFDC_RESULT_T *result, *resultFX1, *resultFX2 = NULL;

uint8_t resultSign;
uint64_t resultInt, resultFract;

uint8_t SSP0resultFX1sign, SSP0resultFX2sign;
uint8_t SSP1resultFX1sign, SSP1resultFX2sign;

uint64_t SSP0resultFX1int, SSP0resultFX2int;
uint64_t SSP1resultFX1int, SSP1resultFX2int;

uint64_t SSP0resultFX1fract, SSP0resultFX2fract;
uint64_t SSP1resultFX1fract, SSP1resultFX2fract;

uint16_t getAccInstr = 0x01FF;
uint16_t setAccInstr = 0x0204;
uint16_t checkStatusInstr = 0x03FF;
uint16_t setMeasureModeInstr1 = 0x0600;
uint16_t setMeasureModeInstr2 = 0x060E;
uint16_t getBCDResultInstr = 0x07FF;
uint8_t startMeasureInstr = 0x09;

uint32_t measureInstr;

uint8_t txData[2];
uint8_t rxData[2];

uint16_t data;

sspConfig.CPHA = SSP_CPHA_FIRST;
sspConfig.CPOL = SSP_CPOL_HI;
sspConfig.ClockRate = 100000;
sspConfig.Databit = SSP_DATABIT_8;
sspConfig.Mode = SSP_MASTER_MODE;
sspConfig.FrameFormat = SSP_FRAME_SPI;

sspData.tx_data = txData;
sspData.rx_data = rxData;
sspData.length = 2;

printf("Initialising SSP0 and SSP1...\n\n");

PINSEL_ConfigPin(0, 15, 2); // SSP0_SCK
PINSEL_ConfigPin(0, 16, 2); // SSP0_SSEL
PINSEL_ConfigPin(0, 17, 2); // SSP0_MISO
PINSEL_ConfigPin(0, 18, 2); // SSP0_MOSI
PINSEL_ConfigPin(0, 6, 2); // SSP1_SCK
PINSEL_ConfigPin(0, 7, 2); // SSP1_SSEL
PINSEL_ConfigPin(0, 8, 2); // SSP1_MISO
PINSEL_ConfigPin(0, 9, 2); // SSP1_MOSI

PINSEL_SetFilter(0, 7, DISABLE);
PINSEL_SetFilter(0, 8, DISABLE);
PINSEL_SetFilter(0, 9, DISABLE);

SSP_Init(LPC_SSP0, &sspConfig);
SSP_Init(LPC_SSP1, &sspConfig);
SSP_Cmd(LPC_SSP0, ENABLE);
SSP_Cmd(LPC_SSP1, ENABLE);

printf("Reading UDFC frequency values...\n\n");
for(int i=0; i < 2; i++)
{
  if(i == 0)
  {
    SSPx = LPC_SSP0;
    resultFX1 = &result_SSP0_FX1;
    resultFX2 = &result_SSP0_FX2;
  }
  else
  {
    SSPx = LPC_SSP1;
    resultFX1 = &result_SSP1_FX1;
    resultFX2 = &result_SSP1_FX2;
  }

  // Set UFDC accuracy to 0.05%.
  SSP_SendData(SSPx, (uint8_t)(setAccInstr >> 8));
  SSP_SendData(SSPx, (uint8_t)(setAccInstr & 0xFF));

  // Check accuracy.
  while(1)
  {
    SSP_SendData(SSPx, (uint8_t)(getAccInstr >> 8));
    SSP_SendData(SSPx, (uint8_t)(getAccInstr & 0xFF));

    data = SSP_ReceiveData(SSPx);
    printf("Accuracy check 1: %i\n", data >> 8);
    printf("Accuracy check 2: %i\n", data & 0xFF);
  }
// More code follows.

The output I'm getting from this is below:

Accuracy check 1: 0
Accuracy check 2: 0
Accuracy check 1: 0
Accuracy check 2: 255
Accuracy check 1: 0
Accuracy check 2: 2
Accuracy check 1: 0
Accuracy check 2: 4
Accuracy check 1: 0
Accuracy check 2: 1
Accuracy check 1: 0
Accuracy check 2: 255
Accuracy check 1: 0
Accuracy check 2: 1
Accuracy check 1: 0
Accuracy check 2: 255
Accuracy check 1: 0
Accuracy check 2: 1
Accuracy check 1: 0
Accuracy check 2: 255

Edit: It's possible to set "loop back enable" with the SPI controllers to make the MOSI read input from the MISO and vice versa. However, I've checked the relevant register and this is disabled.

2
I hope not, I'll have my boss take a look at the pcb to double check but this is already mark II version of the board.Tagc
There are two UFDCs/SSP controllers on the board. I've tested with both and they both exhibit the same problem. This is almost certainly a software problem.Tagc

2 Answers

0
votes

After sending one byte over SPI, you have to clear one byte in the data register (DR) again.

In SPI you always send and receive a byte You cannot just send OR receive a byte, it's always AND. The technical explanation is that there is only one clock line, and two data lines (MISO and MOSI)

0
votes

I think you should check the receive FIFO not Empty Flag, right before reading the data with this line of code:

while (!(LPC_SSP0->SR & SSP_SR_RNE));// poll receive FIFO not empty flag

and in SPI initialization you should clear the receive FIFO with these lines of code:

while (LPC_SSP0->SR & SSP_SR_RNE){
    tmp = (uint32_t) SSP_ReceiveData(LPC_SSP0);
}

hope it will work!