В этой статье очень доходчиво и красиво описано, как работать с дисплеями подключенными по SPI.
Для кодирования пикселей достаточно только нижнего цикла 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 выполняется только при передаче последнего байта.
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); }