moon333 0 2 марта, 2018 Опубликовано 2 марта, 2018 (изменено) · Жалоба Пытаюсь подружит 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. Судя по даташиту такие значения имеют место быть. Далее я пытался прочитать регистр состояния, после того как выполню команду 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. Наверняка, что то очевидное... Не вижу :( Изменено 2 марта, 2018 пользователем moon333 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Segment 3 2 марта, 2018 Опубликовано 2 марта, 2018 · Жалоба Что на шине творится во время передачи смотрели осциллографом или лог.анализатором? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
moon333 0 2 марта, 2018 Опубликовано 2 марта, 2018 · Жалоба Что на шине творится во время передачи смотрели осциллографом или лог.анализатором? Смотрел осциллографом: Данные бегут. Клок есть. CS тоже дёргается. Странно что ID нормально считывается. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Segment 3 2 марта, 2018 Опубликовано 2 марта, 2018 · Жалоба Мне кажется что проблема с флагами ожидания пересылки байт. Возможно, где-то Вы не дожидаетесь отправки байта и сразу начинаете следующие операции. Посмотрите в мануале как работать с регистрами и флагами блока SPI, а потом найдите несоответствие с Вашим кодом. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
moon333 0 2 марта, 2018 Опубликовано 2 марта, 2018 · Жалоба Мне кажется что проблема с флагами ожидания пересылки байт. Возможно, где-то Вы не дожидаетесь отправки байта и сразу начинаете следующие операции. Посмотрите в мануале как работать с регистрами и флагами блока SPI, а потом найдите несоответствие с Вашим кодом. Перед тем как что то писать в регистр SPI4->DR стоит: while(SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET); Я посмотрел, вроде везде так сделано. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Segment 3 2 марта, 2018 Опубликовано 2 марта, 2018 · Жалоба Я посмотрел, вроде везде так сделано. Что значит "везде"? Сверьтесь с мануалом и, если там все точно так же, то можно уже более детально смотреть. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
moon333 0 2 марта, 2018 Опубликовано 2 марта, 2018 · Жалоба Что значит "везде"? Сверьтесь с мануалом и, если там все точно так же, то можно уже более детально смотреть. У Вас подозрение на то, что я пытаюсь отправить данные когда ещё SPI не готов. Правильно ли я Вас понимаю? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Segment 3 2 марта, 2018 Опубликовано 2 марта, 2018 · Жалоба Всего лишь подозрение, код смотрел по-диагонали. Посмотрите (помимо обязательного чтения мануала) также эту статью Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
x893 55 3 марта, 2018 Опубликовано 3 марта, 2018 · Жалоба Везде после 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 0 5 марта, 2018 Опубликовано 5 марта, 2018 (изменено) · Жалоба добавьте 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); Всё заработало. Изменено 5 марта, 2018 пользователем moon333 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться