реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Не могу подружить SPI FLASH и STM32
moon333
сообщение Mar 2 2018, 12:42
Сообщение #1


Частый гость
**

Группа: Участник
Сообщений: 80
Регистрация: 27-01-16
Из: Москва
Пользователь №: 90 218



Пытаюсь подружит 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

Сообщение отредактировал moon333 - Mar 2 2018, 12:44
Go to the top of the page
 
+Quote Post
segment
сообщение Mar 2 2018, 12:50
Сообщение #2


Местный
***

Группа: Участник
Сообщений: 352
Регистрация: 10-08-06
Из: Санкт-Петербург
Пользователь №: 19 471



Что на шине творится во время передачи смотрели осциллографом или лог.анализатором?
Go to the top of the page
 
+Quote Post
moon333
сообщение Mar 2 2018, 13:00
Сообщение #3


Частый гость
**

Группа: Участник
Сообщений: 80
Регистрация: 27-01-16
Из: Москва
Пользователь №: 90 218



Цитата(segment @ Mar 2 2018, 17:50) *
Что на шине творится во время передачи смотрели осциллографом или лог.анализатором?


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

Странно что ID нормально считывается.
Go to the top of the page
 
+Quote Post
segment
сообщение Mar 2 2018, 13:18
Сообщение #4


Местный
***

Группа: Участник
Сообщений: 352
Регистрация: 10-08-06
Из: Санкт-Петербург
Пользователь №: 19 471



Мне кажется что проблема с флагами ожидания пересылки байт. Возможно, где-то Вы не дожидаетесь отправки байта и сразу начинаете следующие операции. Посмотрите в мануале как работать с регистрами и флагами блока SPI, а потом найдите несоответствие с Вашим кодом.
Go to the top of the page
 
+Quote Post
moon333
сообщение Mar 2 2018, 13:47
Сообщение #5


Частый гость
**

Группа: Участник
Сообщений: 80
Регистрация: 27-01-16
Из: Москва
Пользователь №: 90 218



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


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


Я посмотрел, вроде везде так сделано.
Go to the top of the page
 
+Quote Post
segment
сообщение Mar 2 2018, 13:59
Сообщение #6


Местный
***

Группа: Участник
Сообщений: 352
Регистрация: 10-08-06
Из: Санкт-Петербург
Пользователь №: 19 471



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


Что значит "везде"? Сверьтесь с мануалом и, если там все точно так же, то можно уже более детально смотреть.
Go to the top of the page
 
+Quote Post
moon333
сообщение Mar 2 2018, 14:46
Сообщение #7


Частый гость
**

Группа: Участник
Сообщений: 80
Регистрация: 27-01-16
Из: Москва
Пользователь №: 90 218



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


У Вас подозрение на то, что я пытаюсь отправить данные когда ещё SPI не готов.
Правильно ли я Вас понимаю?
Go to the top of the page
 
+Quote Post
segment
сообщение Mar 2 2018, 15:11
Сообщение #8


Местный
***

Группа: Участник
Сообщений: 352
Регистрация: 10-08-06
Из: Санкт-Петербург
Пользователь №: 19 471



Всего лишь подозрение, код смотрел по-диагонали. Посмотрите (помимо обязательного чтения мануала) также эту статью
Go to the top of the page
 
+Quote Post
x893
сообщение Mar 3 2018, 03:07
Сообщение #9


Профессионал
*****

Группа: Свой
Сообщений: 1 333
Регистрация: 27-10-08
Из: Планета Земля
Пользователь №: 41 226



Везде после

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
Go to the top of the page
 
+Quote Post
moon333
сообщение Mar 5 2018, 15:17
Сообщение #10


Частый гость
**

Группа: Участник
Сообщений: 80
Регистрация: 27-01-16
Из: Москва
Пользователь №: 90 218



Цитата(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);

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

Сообщение отредактировал moon333 - Mar 5 2018, 15:22
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 13th July 2025 - 06:42
Рейтинг@Mail.ru


Страница сгенерированна за 0.01468 секунд с 7
ELECTRONIX ©2004-2016