0

I've got an LCD screen that I am using that requires the first spi packet that is sent to be 10 bits long and all subsequent packets to be 8 bits long. So commands are 10 bits and data is bits. Sending data to the device must happen after a command in the same transaction.

I tried a few implementations of this that utilize the HAL but they all appear to cause some strange behavior on the MOSI and CLK lines.

Approach 1: Using the HAL

void set_spi_size_10(SPI_HandleTypeDef *hspi)
{
    HAL_SPI_DeInit(hspi);
    hspi->Init.DataSize = SPI_DATASIZE_10BIT;
    HAL_SPI_Init(hspi);
}

void set_spi_size_8(SPI_HandleTypeDef *hspi)
{
    HAL_SPI_DeInit(hspi);
    hspi->Init.DataSize = SPI_DATASIZE_8BIT;
    HAL_SPI_Init(hspi);
}

void send_data() 
{
    set_spi_size_10(&hspi2);
    HAL_SPI_Transmit(&hspi2, some_buffer, HAL_MAX_DELAY);
    set_spi_size_8(&hspi2);
}

Approach 2: Register Manipulation

void set_spi_size_10(SPI_HandleTypeDef *hspi)
{

    __HAL_SPI_DISABLE(hspi);
    hspi->Init.DataSize = SPI_DATASIZE_10BIT;
    uint32_t frxth = SPI_RXFIFO_THRESHOLD_HF;
    WRITE_REG(hspi->Instance->CR2, (((hspi->Init.NSS >> 16U) & SPI_CR2_SSOE) |
                                    (hspi->Init.TIMode & SPI_CR2_FRF) |
                                    (hspi->Init.NSSPMode & SPI_CR2_NSSP) |
                                    (SPI_DATASIZE_10BIT & SPI_CR2_DS_Msk) |
                                    (frxth & SPI_CR2_FRXTH)));
    __HAL_SPI_ENABLE(hspi);
}

void set_spi_size_8(SPI_HandleTypeDef *hspi)
{
    __HAL_SPI_DISABLE(hspi);

    hspi->Init.DataSize = SPI_DATASIZE_8BIT;
    uint32_t frxth = SPI_RXFIFO_THRESHOLD_QF;
    WRITE_REG(hspi->Instance->CR2, (((hspi->Init.NSS >> 16U) & SPI_CR2_SSOE) |
                                    (hspi->Init.TIMode & SPI_CR2_FRF) |
                                    (hspi->Init.NSSPMode & SPI_CR2_NSSP) |
                                    (SPI_DATASIZE_8BIT & SPI_CR2_DS_Msk) |
                                    (frxth & SPI_CR2_FRXTH)));
    __HAL_SPI_ENABLE(hspi);
}

When using the functions by themselves they work fine, but when using the functions immediately after one another the transaction doesn't work appropriately.

Using a logic analyzer I can see that the init/deinit times appear to be fairly long and when reiniting it causes an unintended change in the CLK and MOSI lines.

I'd prefer not to bit bang the data out if possible, but that is an alternative. (Looking at the device manufacturers examples this is the approach they took).

https://www.newhavendisplay.com/specs/NHD-0420DZW-AB5.pdf https://github.com/NewhavenDisplay/NHD-0420DZW_Example/blob/main/NHD-0420DZW_Serial/NHD-0420DZW_Serial.ino

emg184
  • 850
  • 8
  • 19
  • Disabling and enabling the device might cause your unwanted signal changes. – Gerhardh Jul 08 '21 at 12:09
  • That's what i thought as well however changing the data size on the handle without calling init again does nothing – emg184 Jul 08 '21 at 12:37
  • 1
    Sure, mapping that struct to registers of the SPI controller is done in init function. You could try to just use the `WRITE_REG(...` command from those functions. You also need to find a way to detect when the first transmission is completed. – Gerhardh Jul 08 '21 at 12:56
  • Isn't that roughly what the second approach is doing so you would suggest just not using the enable and disable – emg184 Jul 08 '21 at 13:01
  • 1
    Yes, you should try to avoid the disabling/enabling part. And as I mentioned you must synch with the end of the first transmission. – Gerhardh Jul 08 '21 at 13:12
  • You do not need to change the data size of the SPI transaction and no one does it this way. You try to sort out the problem which does not exist. – 0___________ Jul 08 '21 at 18:54
  • Is there a reason why I don't need to change the SPI size? Or can you clock out two extra bits using the HAL spi interface. I was able to get it to work using the approach above. – emg184 Jul 09 '21 at 15:37

0 Answers0