Top.Mail.Ru
Уведомления
Очистить все

[Решено] TFT дисплей ILI9341. SPI

Страница 6 / 6
(@eduard)
Level 4 Moderator

В этой статье очень доходчиво и красиво описано, как работать с дисплеями подключенными по SPI.

ОтветитьЦитата
Размещено : 17.10.2023 06:10
Aveal
(@aveal)
Top level Admin
От: @stm

Для кодирования пикселей достаточно только нижнего цикла while((SPI1->SR & SPI_SR_TXE) == RESET);, верхний для безопасности, это хорошо, но неправильной последовательностью думаю это нельзя назвать. Ок, пусть будет.

И снова не совсем так ) При любом расположении строка

while((SPI1->SR & SPI_SR_TXE) == RESET); 

служит одной цели - убедиться, что предыдущие данные ушли, и можно писать новые.

Если вернуться к оберткам в виде функций для удобства:

/* ---------------------------------------------------------------------------*/
void ST7735_SendByte(uint8_t data)
{
  while((SPI1->SR & SPI_SR_TXE) == RESET);  
  SPI1->DR = data;
}

/* ---------------------------------------------------------------------------*/

/* ---------------------------------------------------------------------------*/
void ST7735_WaitLastData()
{
  while((SPI1->SR & SPI_SR_TXE) == RESET);
  while((SPI1->SR & SPI_SR_BSY) != RESET);
}

/* ---------------------------------------------------------------------------*/

Запись последовательности байт выглядит так:

for (uint32_t i = 0; i < num; i++)
{
  ST7735_SendByte(*data);
  data++;
}

ST7735_WaitLastData();

По шагам это превращается в:

while((SPI1->SR & SPI_SR_TXE) == RESET);  
SPI1->DR = data;
while((SPI1->SR & SPI_SR_TXE) == RESET);  
SPI1->DR = data;
while((SPI1->SR & SPI_SR_TXE) == RESET);  
SPI1->DR = data;
while((SPI1->SR & SPI_SR_TXE) == RESET);  
SPI1->DR = data;

while((SPI1->SR & SPI_SR_TXE) == RESET);
while((SPI1->SR & SPI_SR_BSY) != RESET);
  • Проверяем, что можно писать данные в регистр
  • Пишем данные в регистр DR
  • Проверяем, что эти данные ушли в сдвиговый регистр = можно писать новые данные
  • Пишем данные
  • ...
  • ...
  • После последнего байта проверяем и флаг SPI_SR_TXE и флаг SPI_SR_BSY, только после этого (!) можно менять сигналы на DC и т. д.

Соответственно, если пишем только один байт, то последовательность такая:

while((SPI1->SR & SPI_SR_TXE) == RESET);  
SPI1->DR = data;
while((SPI1->SR & SPI_SR_TXE) == RESET);
while((SPI1->SR & SPI_SR_BSY) != RESET);
  • Проверяем, что ушли предыдущие данные
  • Пишем новые данные
  • Проверяем, что ушли новые данные

Но при отправке последовательности байт проверка флага SPI_SR_BSY выполняется только при передаче последнего байта.

От: @stm

HAL овским функциям может было необходимо деактивировать Чип Селект после каждой передачи данных.
Передаче данных через регистры это не нужно.

CS никак не связан с тем, какие библиотеки используются. Этот сигнал нужен для активации/деактивации slave'а на шине, у меня активируется внутри функций отрисовки:

void ST7735_DrawRect(uint16_t cStart, uint16_t rStart, uint16_t cStop, uint16_t rStop, uint16_t color)
{
  HAL_GPIO_WritePin(ST7735_CS_PORT, ST7735_CS_PIN, GPIO_PIN_RESET);
  ST7735_SetColAddr(cStart, cStop - 1);
  ST7735_SetRowAddr(rStart, rStop - 1);
  
  ST7735_SendCommand(ST7735_RAMWR);
  
  uint32_t size = (cStop - cStart) * (rStop - rStart);
  uint8_t colorBytes[2];
  colorBytes[0] = (color & 0xFF00) >> 8;
  colorBytes[1] = color & 0x00FF;
  
  HAL_GPIO_WritePin(ST7735_DC_PORT, ST7735_DC_PIN, GPIO_PIN_SET);
  
  for (uint32_t i = 0; i < size; i++)
  {
    ST7735_SendByte(colorBytes[0]);
    ST7735_SendByte(colorBytes[1]);
  }
  
  ST7735_WaitLastData();
  HAL_GPIO_WritePin(ST7735_CS_PORT, ST7735_CS_PIN, GPIO_PIN_SET);
}
ОтветитьЦитата
Размещено : 17.10.2023 08:52
Страница 6 / 6
Поделиться: