У модуля с экраном 9 ног для подключения по SPI (VCC, GND, CS, RESET, D/C, MOSI, SCK, LED, MISO)
К STM подключил так:
Код: Выделить всё
TFT STM32
-------------------
VCC 5v
GND GND
CS PB11
RESET PB12
DC PB10
MOSI PA7
SCK PA5
LED 3v
MISO PA6
Для проверки работы, пытаюсь прочитать из экрана его ID. Согласно datasheet, надо отправить команду 0x4, и 4 раза прочитать из экрана. В последних трех ответах будет ID (стр. 91 даташита). Команду шлю и читаю ответ в бесконечном цикле.
Для отладки, полученные значения шлю в UART. В ответ приходит 0, 0x3F и дальше все ответы 0xFF.
Для проверки работы SPI я слал с SPI1 на плате на SPI2 и обратно. Все работает, отправляется и принимает.
Буду очень благодарен, если подскажете, что делаю не правильно. Во вложении проект из Keil5.
Весь код специально написал прямо в main(), чтоб не искать по функциям. Убрал только работу с uart.
Пробовал устанавливать LSBFIRST (порядок бит) и менять скорость baute rate, но результат тот же.
Код: Выделить всё
#include "main.h"
/*
Подключение экрана:
TFT STM32
-------------------
VCC 5v
GND GND
CS PB11
RESET PB12
DC PB10
MOSI PA7
SCK PA5
LED 3v
MISO PA6
*/
int main(void)
{
//Инициализация UART2, используется для вывода отладки
uart_init();
//Включение тактирования порта B (для DC, RST, CS)
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
//Режим output для пинов 10, 11, 12
GPIOB->MODER |= GPIO_MODER_MODE10_0|GPIO_MODER_MODE11_0|GPIO_MODER_MODE12_0;
//Скорость порта Very High speed для 10, 11, 12
GPIOB->OSPEEDR |= GPIO_OSPEEDR_OSPEED10_0|GPIO_OSPEEDR_OSPEED10_1;
GPIOB->OSPEEDR |= GPIO_OSPEEDR_OSPEED11_0|GPIO_OSPEEDR_OSPEED11_1;
GPIOB->OSPEEDR |= GPIO_OSPEEDR_OSPEED12_0|GPIO_OSPEEDR_OSPEED12_1;
//Установка подтяжки:
//Обнуление на всякий случай
GPIOB->PUPDR &= ~(GPIO_PUPDR_PUPD10_0|GPIO_PUPDR_PUPD10_1);
GPIOB->PUPDR &= ~(GPIO_PUPDR_PUPD11_0|GPIO_PUPDR_PUPD11_1);
GPIOB->PUPDR &= ~(GPIO_PUPDR_PUPD12_0|GPIO_PUPDR_PUPD12_1);
//Установка подтяжки к GND (Pull-down)
GPIOB->PUPDR |= GPIO_PUPDR_PUPD10_1|GPIO_PUPDR_PUPD11_1|GPIO_PUPDR_PUPD12_1;
//Перед инициализацией SPI, устанавливаю CS в HIGH, т.е. отключаю выбор (активное состояние LOW)
GPIOB->BSRR |= GPIO_BSRR_BS11;
//Инициализация SPI
//Включить тактирование SPI1
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
//Включить тактирование порта А
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
//Включение AF5 на пинах 5,6,7
GPIOA->AFR[0] |= GPIO_AFRL_AFSEL5_0|GPIO_AFRL_AFSEL5_2;
GPIOA->AFR[0] |= GPIO_AFRL_AFSEL6_0|GPIO_AFRL_AFSEL6_2;
GPIOA->AFR[0] |= GPIO_AFRL_AFSEL7_0|GPIO_AFRL_AFSEL7_2;
//Режим альтернативной функция для PA5,PA6,PA7
GPIOA->MODER |= GPIO_MODER_MODE5_1|GPIO_MODER_MODE6_1|GPIO_MODER_MODE7_1;
//Скорость High speed
GPIOA->OSPEEDR |= GPIO_OSPEEDR_OSPEED5_0|GPIO_OSPEEDR_OSPEED5_1;
GPIOA->OSPEEDR |= GPIO_OSPEEDR_OSPEED6_0|GPIO_OSPEEDR_OSPEED6_1;
GPIOA->OSPEEDR |= GPIO_OSPEEDR_OSPEED7_0|GPIO_OSPEEDR_OSPEED7_1;
//Режим push-pull
GPIOA->OTYPER &= ~GPIO_OTYPER_OT5;
GPIOA->OTYPER &= ~GPIO_OTYPER_OT6;
GPIOA->OTYPER &= ~GPIO_OTYPER_OT7;
//Отключение подтяжки на PA5, PA6, PA7
GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPD5_0|GPIO_PUPDR_PUPD5_1);
GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPD6_0|GPIO_PUPDR_PUPD6_1);
GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPD7_0|GPIO_PUPDR_PUPD7_1);
//Режим работы по двум линиям
SPI1->CR1 &= ~SPI_CR1_BIDIMODE;
//Отключение CRC
SPI1->CR1 &= ~SPI_CR1_CRCEN;
//8-bit передача
SPI1->CR1 &= ~SPI_CR1_DFF;
//Програмное управление SS
SPI1->CR1 |= SPI_CR1_SSI|SPI_CR1_SSM;
//Режим работы SPI 0
SPI1->CR1 &= ~SPI_CR1_CPHA;
SPI1->CR1 &= ~SPI_CR1_CPOL;
//Выбор скорости /8
SPI1->CR1 &= ~SPI_CR1_BR;
SPI1->CR1 |= (SPI_CR1_BR_1);
//Установка флага Master
SPI1->CR1 |= SPI_CR1_MSTR;
//Выбор формата фрейма, какой бит передавать первым
//SPI1->CR1 |= SPI_CR1_LSBFIRST;
//Включение SPI1
SPI1->CR1 |= SPI_CR1_SPE;
//Установка CS в LOW, для выбора slave
GPIOB->BSRR |= GPIO_BSRR_BR11;
//Судя по описанию ili9341, RST активен кошда LOW.
//Т.е. для работы, нужно установить в HIGH
GPIOB->BSRR |= GPIO_BSRR_BS12;
//Экрану буду слать только команду на чтение, поэтому DC в LOW
GPIOB->BSRR |= GPIO_BSRR_BR10;
//Перед началом работы надо отправить команду SOFWARE RESET (0x1)
//Пока бит TXE не будет установлен, просто ждать
while(!(SPI1->SR & SPI_SR_TXE)){};
//Команда для чтения из экрана
SPI1->DR=0x1;
//Дисплею надо 5ms, чтобы выполнить reset, тупая пауза с запасом
for(int i=0; i < 10000000; i++);
while(1)
{
uint8_t d,f,g=0; //переменные, чтобы складывать ответы экрана
//Пока бит TXE не будет установлен, просто ждать
while(!(SPI1->SR & SPI_SR_TXE)){};
//Команда для чтения из экрана 0x4
//В ответ вернет 4 байта. В первом мусор, остальные 3 с ID
SPI1->DR=0x4;
//Сразу после отправки команды, в ответ сначала придет мусор
d=SPI1->DR;
//Чтобы получить ответ на команду, надо продолжить тактировать
//передавая 0 (NOP)
while(!(SPI1->SR & SPI_SR_TXE)){};
SPI1->DR=0;
// 1 из 3 байт ответа
d=SPI1->DR;
//Чтобы получить ответ на команду, надо продолжить тактировать
//передавая 0
while(!(SPI1->SR & SPI_SR_TXE)){};
SPI1->DR=0;
// 2 из 3 байт ответа
f=SPI1->DR;
//Чтобы получить ответ на команду, надо продолжить тактировать
//передавая 0
while(!(SPI1->SR & SPI_SR_TXE)){};
SPI1->DR=0;
// 3 из 3 байт ответа
g=SPI1->DR;
sprintf(str_buffer, "d: %02X f: %02X g: %02X \r\n",d,f,g);
uart_send_string(str_buffer);
};
};
Извиняюсь, случайно создал тему не в том разделе.
Можно перенести в ARM?


