cancel
Showing results for 
Search instead for 
Did you mean: 

ILI9341 with STM32F0

proc9
Associate II
Posted on August 16, 2015 at 16:23

Hello.

I'm playing with the STM32F072Discovery and it's great but I have a little problem.

I don't know how I can transfer data to the display via the SPI more efficiently.

For now I've configured it to work with DMA but it's no use because this display uses GPIO pin for D/C (data/command) and even with DMA I have to make a while loop to wait for a complete SPI transfer and an empty buffer because the display won't read correctly that pin.

Does someone have any idea how to do that?

This library http://dorkbotpdx.org/blog/paul/display_spi_optimization uses a feature of other microcontroller that has multiple hardware CS pins to control that but the STM32F0 has only one so that idea has no use here.

Thanks in advance for any advice.
4 REPLIES 4
Posted on August 16, 2015 at 17:09

Well the STM32 would permit you to use GPIO pins for any number of Chip Select arrangements. With DMA you'd want to manage the stream using TC interrupts, and state machines. If the command portion only needs one word (I don't use this display, and haven't rtfm), you could presumably send that manually, and then fire the bulk of the data, and change the command/data select when you get the RXNE off the command.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
proc9
Associate II
Posted on August 16, 2015 at 17:35

Thanks for help but I don't understand, I'm new to this topic but you said that at the end of the transfer I need to read RXNE flag - isn't it supposed to be tied to incomming data?

So for the DC i'll try to make some kind of a state machine in the interrupt. DMA TC interrupt is generated after all the data is transfered or after one byte when CNDTR is just decremented by one? I couldn't find that in RM to be sure.

Here's a little piece of code I'm using, CS is managed by hardware. For now I don't have a reliable solution to switch SPI from 8bit to 16bit on the fly so it's like it is.

Is it possible to use DMA in circular mode for this purpose? I think about disabling it after transfer in the interrupt and in the spiwrite function I'd just write DMA_CCR_EN because the CNDTR should be automatically reloaded? I'm trying to make it as fast as possible because for now I'm struggling to get more than 1-2FPS.

void Adafruit_ILI9341::spiwrite8(uint8_t c)

{

aTxBuffer[0] = c;

// DMA1_Channel3->CCR &=~ DMA_CCR_EN;

DMA1_Channel3->CCR = 0; // dirty hack to save some time

   DMA1_Channel3->CNDTR = 1; // Data size

// DMA1_Channel3->CCR |= DMA_CCR_EN;

   DMA1_Channel3->CCR = DMA_CCR_DIR | DMA_CCR_EN;

while((SPI1->SR & SPI_SR_BSY) && (!(SPI1->SR & SPI_SR_TXE)));

}

void Adafruit_ILI9341::spiwrite16(uint16_t c)

{

aTxBuffer[0] = c>>8;

aTxBuffer[1] = c;

DMA1_Channel3->CCR = 0;

DMA1_Channel3->CNDTR = 2; // Data size

DMA1_Channel3->CCR = DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_EN;

while((SPI1->SR & SPI_SR_BSY) && (!(SPI1->SR & SPI_SR_TXE)));

}

void Adafruit_ILI9341::writecommand(uint8_t c)

{

GPIOB->BRR = LCD_DC_PIN;

spiwrite8(c);

}

void Adafruit_ILI9341::writedata(uint8_t c)

{

GPIOB->BSRR = LCD_DC_PIN;

spiwrite8(c);

}
Posted on August 16, 2015 at 18:25

The SPI bus is symmetrical, and has one clock, the data clocks out, and returned data clocks back. RXNE signals after the last bit hits the wire, so allows you to release CS after the data has actually been sent. TXE on the other hand relates to a buffer, and is somewhat disconnected in the time domain with respect to the signal going over the wire.

Sending one or two bytes via DMA seems a bit inefficient. It's better suited to applications where 10, 100 or 1000 bytes transit. And then rather than sitting in a loop, burning cycles, waiting for it to complete, you catch the completion with DMA TC, and SPI interrupts. ie the TC interrupt will fire when it's delivered the last byte to the SPI buffer, not when it actually finishes arriving at the device, so you'd then want to catch the SPI RXNE, and prepare the next transfer.

If you want to control selects between bytes, look at creating an outgoing buffer, and manage that in the SPI RXNE interrupt

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
proc9
Associate II
Posted on August 28, 2015 at 19:42

Thank you very much clive1!

That solution is working great. I'm now trying to port it to STM32F103 because when I added FFT and sensors reading the tiny Cortex M0 is little too slow for that and I'm having next problem. The STM32F072 managed CS line automatically by hardware and it was working great, unfortunately the older STM32F103 is having problem with that, I can see outgoing transmission with Logic Analyzer on CLK and MOSI but NSS is always pulled low :\

Here is a piece of code I'm using (just now for software transfer not DMA and IT)

void Configure_GPIO_SPI1(void)

{

RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_AFIOEN;

GPIOA->CRL &= ~(GPIO_CRL_CNF4 | GPIO_CRL_MODE4 | GPIO_CRL_CNF5 | GPIO_CRL_MODE5 | GPIO_CRL_CNF6 | GPIO_CRL_MODE6 | GPIO_CRL_CNF7 | GPIO_CRL_MODE7);

GPIOA->CRL |= GPIO_CRL_CNF4_1 | GPIO_CRL_MODE4 | GPIO_CRL_CNF5_1 | GPIO_CRL_MODE5 | GPIO_CRL_CNF7_1 | GPIO_CRL_MODE7;

}

void Configure_SPI1(void)

{

RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;

SPI1->CR2 = SPI_CR2_SSOE;

SPI1->CR1 = SPI_CR1_MSTR | SPI_CR1_BR_2 | SPI_CR1_SPE;

}