Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Не могу подружить SPI FLASH и STM32
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
moon333
Пытаюсь подружит stm32f427 и SPI flash W25Q64FV.

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

CODE

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. Судя по даташиту такие значения имеют место быть.



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

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

Инициализация SPI
CODE
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. Наверняка, что то очевидное... Не вижу sad.gif
segment
Что на шине творится во время передачи смотрели осциллографом или лог.анализатором?
moon333
Цитата(segment @ Mar 2 2018, 17:50) *
Что на шине творится во время передачи смотрели осциллографом или лог.анализатором?


Смотрел осциллографом:
Данные бегут. Клок есть. CS тоже дёргается.

Странно что ID нормально считывается.
segment
Мне кажется что проблема с флагами ожидания пересылки байт. Возможно, где-то Вы не дожидаетесь отправки байта и сразу начинаете следующие операции. Посмотрите в мануале как работать с регистрами и флагами блока SPI, а потом найдите несоответствие с Вашим кодом.
moon333
Цитата(segment @ Mar 2 2018, 17:18) *
Мне кажется что проблема с флагами ожидания пересылки байт. Возможно, где-то Вы не дожидаетесь отправки байта и сразу начинаете следующие операции. Посмотрите в мануале как работать с регистрами и флагами блока SPI, а потом найдите несоответствие с Вашим кодом.


Перед тем как что то писать в регистр SPI4->DR стоит:
Код
while(SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET);


Я посмотрел, вроде везде так сделано.
segment
Цитата(moon333 @ Mar 2 2018, 16:47) *
Я посмотрел, вроде везде так сделано.


Что значит "везде"? Сверьтесь с мануалом и, если там все точно так же, то можно уже более детально смотреть.
moon333
Цитата(segment @ Mar 2 2018, 17:59) *
Что значит "везде"? Сверьтесь с мануалом и, если там все точно так же, то можно уже более детально смотреть.


У Вас подозрение на то, что я пытаюсь отправить данные когда ещё SPI не готов.
Правильно ли я Вас понимаю?
segment
Всего лишь подозрение, код смотрел по-диагонали. Посмотрите (помимо обязательного чтения мануала) также эту статью
x893
Везде после

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
moon333
Цитата(x893 @ Mar 3 2018, 08:07) *
добавьте
while(SPI_I2S_GetFlagStatus(SPI4, SPI_I2S_FLAG_RXNE) == RESET);
... SPI_I2S_ReceiveData(SPI4);

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


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

Цитата(segment @ Mar 2 2018, 20:11) *
Всего лишь подозрение, код смотрел по-диагонали. Посмотрите (помимо обязательного чтения мануала) также эту статью


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

Добавил:
Код
while (SPI_I2S_GetFlagStatus(SPIx,SPI_FLAG_BSY)!=RESET);

Всё заработало.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2024 Invision Power Services, Inc.