Перейти к содержанию
    

Не могу подружить SPI FLASH и STM32

Пытаюсь подружит stm32f427 и SPI flash W25Q64FV.

 

Для начала научился читать из FLASH Device Identification по команде Read JEDEC ID (9Fh)

 

SPI4_CS_LOW;
while(SPI_I2S_GetFlagStatus(SPI4, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI4, 0x9F);

while(SPI_I2S_GetFlagStatus(SPI4, SPI_I2S_FLAG_RXNE) == RESET);
data_spi = SPI_I2S_ReceiveData(SPI4);  // заглушка, чтобы очистить RXNE

while(SPI_I2S_GetFlagStatus(SPI4, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI4, 0x00);

while(SPI_I2S_GetFlagStatus(SPI4, SPI_I2S_FLAG_RXNE) == RESET);
data_flash[0] = SPI_I2S_ReceiveData(SPI4);

while(SPI_I2S_GetFlagStatus(SPI4, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI4, 0x00);

while(SPI_I2S_GetFlagStatus(SPI4, SPI_I2S_FLAG_RXNE) == RESET);
data_flash[1] = SPI_I2S_ReceiveData(SPI4);

while(SPI_I2S_GetFlagStatus(SPI4, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI4, 0x00);

	while(SPI_I2S_GetFlagStatus(SPI4, SPI_I2S_FLAG_RXNE) == RESET);
data_flash[2] = SPI_I2S_ReceiveData(SPI4);

SPI4_CS_HIGH;

 

Получаю вполне корректный ответ: 0xEF 0x40 0x17. Судя по даташиту такие значения имеют место быть.

 

824e917ced6a.png

 

Далее я пытался прочитать регистр состояния, после того как выполню команду Write Enable 0x06. По идее бит WEL должен быть установлен, однако читается одни нули 0x00.

 

Далее прилагаю код:

 

Инициализация SPI

void init_SPI()
{
	uint8_t x = 0x00;

//настройка CS и включения питания
GPIO_InitTypeDef GPIO_CS;	
GPIO_InitTypeDef GPIO_POW;

GPIO_CS.GPIO_Pin = GPIO_Pin_11;
GPIO_CS.GPIO_Mode = GPIO_Mode_OUT;
GPIO_CS.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_CS.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_CS.GPIO_OType = GPIO_OType_PP;

GPIO_POW.GPIO_Pin = GPIO_Pin_11;
GPIO_POW.GPIO_Mode = GPIO_Mode_OUT;
GPIO_POW.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_POW.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_POW.GPIO_OType = GPIO_OType_PP;

GPIO_Init(GPIOE, &GPIO_CS);
GPIO_Init(GPIOB, &GPIO_POW);


SPI_InitTypeDef SPI_struct_itit; //объявляем структуру для инициализации SPI
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI4, ENABLE); // включаем тактирование SPI4

	/* Инициализация структуры
	 Initialize the SPI_Direction - Двухнаправленный SPI или Однонаправленный
	 Initialize the SPI_Mode member  - Slave (ведомый) или Master(Мастер) 
	 Initialize the SPI_DataSize member - бит в сообщении (8 или 16)
	 Initialize the SPI_CPOL member - задаёт режим работы (режим 0,1,2,3)
	 Initialize the SPI_CPHA member - задаёт режим работы (режим 0,1,2,3)
	 Initialize the SPI_NSS member - Управление CS HARD - автоматически, soft - программно
	 Initialize the SPI_BaudRatePrescaler member - делитель для тактовой частоты SPI
	 Initialize the SPI_FirstBit member - младший или старшый байт первый 
	 Initialize the SPI_CRCPolynomial member - CRC полином
	*/
 SPI_struct_itit.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
 SPI_struct_itit.SPI_Mode = SPI_Mode_Master;
 SPI_struct_itit.SPI_DataSize = SPI_DataSize_8b;
 SPI_struct_itit.SPI_CPOL = SPI_CPOL_Low;
 SPI_struct_itit.SPI_CPHA = SPI_CPHA_1Edge;	
 SPI_struct_itit.SPI_NSS = SPI_NSS_Soft;
 SPI_struct_itit.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32;
 SPI_struct_itit.SPI_FirstBit = SPI_FirstBit_MSB;
 SPI_struct_itit.SPI_CRCPolynomial = 7;

SPI_Init (SPI4,&SPI_struct_itit);	// инициализируем SPI4
SPI_Cmd(SPI4,ENABLE);
}

 

Инициализация GPIO SPI

    // инициализация SPI4: SCL,MOSI
    Other_GPIO.GPIO_Pin =   GPIO_Pin_12 | GPIO_Pin_14;
    Other_GPIO.GPIO_Mode = GPIO_Mode_AF;
    Other_GPIO.GPIO_OType = GPIO_OType_PP;
    Other_GPIO.GPIO_PuPd = GPIO_PuPd_NOPULL;
    Other_GPIO.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOE, &Other_GPIO);
    // инициализация SPI4: MISO
    Other_GPIO.GPIO_Pin =  GPIO_Pin_13;
    Other_GPIO.GPIO_Mode = GPIO_Mode_AF;
    Other_GPIO.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOE, &Other_GPIO);
    // инициализация SPI4: NSS
    Other_GPIO.GPIO_Pin =  GPIO_Pin_11;
    Other_GPIO.GPIO_Mode = GPIO_Mode_OUT;
    Other_GPIO.GPIO_OType = GPIO_OType_PP;
    Other_GPIO.GPIO_PuPd = GPIO_PuPd_NOPULL;
    Other_GPIO.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOE, &Other_GPIO);
    //Выбираем альтернативную функцию для всех PIN-SPI
    GPIO_PinAFConfig(GPIOE, GPIO_PinSource12, GPIO_AF_SPI4);
    GPIO_PinAFConfig(GPIOE, GPIO_PinSource13, GPIO_AF_SPI4);
    GPIO_PinAFConfig(GPIOE, GPIO_PinSource14, GPIO_AF_SPI4);

 

Посылка команды Write Enable

//включение записи во flash
void FLASH_Write_Enable(SPI_TypeDef* SPIx)
{
    if (SPIx == SPI4)    SPI4_CS_LOW;
    else                __NOP; // Временная заглушка для SPI1
    
    while(SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET);
    SPI_I2S_SendData(SPIx, WriteEnable);
    
    if (SPIx == SPI4)    SPI4_CS_HIGH;
    else                __NOP; // Временная заглушка для SPI1
    
}

 

Ну и функция считывания Статус регистра

uint8_t READ_Stat_Reg (SPI_TypeDef* SPIx)
{
    volatile uint8_t byte = 0x00;
    
    SPI4_CS_LOW;
        
    while(SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET);
    SPI_I2S_SendData(SPI4, 0x05);
    
    while(SPI_I2S_GetFlagStatus(SPI4, SPI_I2S_FLAG_RXNE) == RESET);
    byte = SPI_I2S_ReceiveData(SPI4);
    
    while(SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET);
    SPI_I2S_SendData(SPI4, 0x00);
    
    while(SPI_I2S_GetFlagStatus(SPI4, SPI_I2S_FLAG_RXNE) == RESET);
    byte = SPI_I2S_ReceiveData(SPIx);
    
    SPI4_CS_HIGH;
    
    return byte;
    
}

 

основная main()

int main(void)
{

init_CLOCK();

init_GPIO();

GPIOB->ODR &= ~GPIO_Pin_11; //power FLASH on

init_SPI();

FLASH_Write_Enable(SPI4);

x = READ_Stat_Reg(SPI4);

..................

 

 

брейкпоинт ставлю в функции READ_Stat_Reg на строчке SPI4_CS_HIGH;

 

 

Почему читаются одни 0. Наверняка, что то очевидное... Не вижу :(

Изменено пользователем moon333

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Что на шине творится во время передачи смотрели осциллографом или лог.анализатором?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Что на шине творится во время передачи смотрели осциллографом или лог.анализатором?

 

Смотрел осциллографом:

Данные бегут. Клок есть. CS тоже дёргается.

 

Странно что ID нормально считывается.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Мне кажется что проблема с флагами ожидания пересылки байт. Возможно, где-то Вы не дожидаетесь отправки байта и сразу начинаете следующие операции. Посмотрите в мануале как работать с регистрами и флагами блока SPI, а потом найдите несоответствие с Вашим кодом.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Мне кажется что проблема с флагами ожидания пересылки байт. Возможно, где-то Вы не дожидаетесь отправки байта и сразу начинаете следующие операции. Посмотрите в мануале как работать с регистрами и флагами блока SPI, а потом найдите несоответствие с Вашим кодом.

 

Перед тем как что то писать в регистр SPI4->DR стоит:

while(SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET);

 

Я посмотрел, вроде везде так сделано.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я посмотрел, вроде везде так сделано.

 

Что значит "везде"? Сверьтесь с мануалом и, если там все точно так же, то можно уже более детально смотреть.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Что значит "везде"? Сверьтесь с мануалом и, если там все точно так же, то можно уже более детально смотреть.

 

У Вас подозрение на то, что я пытаюсь отправить данные когда ещё SPI не готов.

Правильно ли я Вас понимаю?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Всего лишь подозрение, код смотрел по-диагонали. Посмотрите (помимо обязательного чтения мануала) также эту статью

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Везде после

 

while(SPI_I2S_GetFlagStatus(SPI4, SPI_I2S_FLAG_TXE) == RESET);

SPI_I2S_SendData(SPI4, ...);

 

добавьте

 

while(SPI_I2S_GetFlagStatus(SPI4, SPI_I2S_FLAG_RXNE) == RESET);

... SPI_I2S_ReceiveData(SPI4);

 

Если не понятно зачем - прочитайте про работу SPI в RM

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

добавьте

while(SPI_I2S_GetFlagStatus(SPI4, SPI_I2S_FLAG_RXNE) == RESET);

... SPI_I2S_ReceiveData(SPI4);

 

Если не понятно зачем - прочитайте про работу SPI в RM

 

Overrun flag к моменту приёма всегда был чист. Хотя изначально я тоже на это напарывался.

 

Всего лишь подозрение, код смотрел по-диагонали. Посмотрите (помимо обязательного чтения мануала) также эту статью

 

Спасибо. До этого читал по диагонали и из за этого допустил ошибку. Снимал CS раньше, чем успевал передать все данные...

 

Добавил:

while (SPI_I2S_GetFlagStatus(SPIx,SPI_FLAG_BSY)!=RESET);

Всё заработало.

Изменено пользователем moon333

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...