AHTOXA 18 9 января, 2013 Опубликовано 9 января, 2013 · Жалоба по картинке Думаю, что врёт картинка. Потому что в тексте не так. (И из опыта - тоже не так.) BSY сделан для управления чипселектом, а чипселект надо держать до конца байта, а не до гипотетического момента, когда нам думается, что ведомое устройство уже приняло байт. У нас есть команды проверки флага, перехода, если установился, подготовки байта (CS) для засылки в порт, засылки в порт. Даже на 168 MHz тактовой это займет не один десяток ns. Пара nop, что вы добавляете, составит ~1/4 от всего количества команд. Да ради бога, если вам нравится делать устройства, работа которых зависит от погоды на Марсе - делайте, как вам угодно. Только потом не удивляйтесь, если ваш девайс перестанет работать с новой партией микросхем. Вам два человека хором говорят, что RXNE и BSY - это не одно и то же, и что они ходили по этим граблям. Но выбор, конечно, за вами. Именно на STM32F207. НА STM32F103 разрешал отдельной командой. Иначе - никак. У меня на 10x тоже одной командой: RCC->APB1ENR |= RCC_APB1ENR_SPI2EN; SPIx->I2SCFGR &= ~SPI_I2SCFGR_I2SMOD; SPIx->CR2 = 0; SPIx->CR1 = SPI_CR1_MSTR | divisor | SPI_CR1_SSM | SPI_CR1_SSI | SPI_CR1_SPE | phase | cpol; И работает. ЧЯДНТ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 9 января, 2013 Опубликовано 9 января, 2013 · Жалоба ... а чипселект надо держать до конца байта, а не до гипотетического момента... Не надо И работает. ЧЯДНТ? Что нам скажет товарищ HHIMERA? 103-й я программировал так. Возможно, при другом сочетании можно было бы сразу разрешить. SPI1->CR1 = SPI_CR1_SSI | SPI_CR1_BR_0 | SPI_CR1_MSTR; // Fpclk/4 SPI1->CR2 = SPI_CR2_SSOE; ... SPI_Cmd(SPI1, ENABLE); // разрешить SPI1 два человека хором говорят, что RXNE и BSY - это не одно и то же, и что они ходили по этим граблям И я прошелся когда-то давным-давно, и ничего не заметил: inline uint8_t SFMByte_send(uint8_t data) { while (!(SPI1->SR & SPI_SR_TXE)); // ждать освобождения SPI1->DR = data; // послать данные while (!(SPI1->SR & SPI_SR_RXNE)); // ждать байта в приемнике (конца передачи) // while (SPI1->SR & SPI_SR_BSY); // другой способ дождаться конца передачи return SPI1->DR; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HHIMERA 0 9 января, 2013 Опубликовано 9 января, 2013 · Жалоба Что вы референс не читали... RXNE говорит только о том, что можно/нельзя забирать данные из приёмного буфера, но это, увы, не признак окончания передачи... вернее, не всегда является признаком... По поводу SPI_CR1_SSM и SPI_CR1_SSI... всегда их устанавливал... во всей линейке STM32... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 9 января, 2013 Опубликовано 9 января, 2013 · Жалоба Что вы референс не читали... RXNE говорит только о том, что можно/нельзя забирать данные из приёмного буфера, но это, увы, не признак окончания передачи... вернее, не всегда является признаком... Да ну? А вы в курсе, что прием и передача происходят синхронно? Один битик выдвинули, один задвинули. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HHIMERA 0 9 января, 2013 Опубликовано 9 января, 2013 · Жалоба И я прошелся когда-то давным-давно, и ничего не заметил: inline uint8_t SFMByte_send(uint8_t data) { while (!(SPI1->SR & SPI_SR_TXE)); // ждать освобождения SPI1->DR = data; // послать данные while (!(SPI1->SR & SPI_SR_RXNE)); // ждать байта в приемнике (конца передачи) // while (SPI1->SR & SPI_SR_BSY); // другой способ дождаться конца передачи return SPI1->DR; Конечно не заметили... while (!(SPI1->SR & SPI_SR_TXE)); здесь и даром не нужна... смело можно выкинуть... И вполне логично, если возвращать return SPI1->DR, то и проверять нужно while (!(SPI1->SR & SPI_SR_RXNE)); ... О дёргании CS тут не слова... увы... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 9 января, 2013 Опубликовано 9 января, 2013 · Жалоба О дёргании CS тут не слова... увы... inline uint32_t SFMID_read(void) { SFMSel_low(); volatile uint32_t ID = 0; SFMByte_send(SFM_RDID); // Send "RDID " instruction ID = SFMByte_send(SFM_DUMMY); // Read a byte from the SFM ID = (ID<<8) | (SFMByte_send(SFM_DUMMY)); // Read a byte from the SFM ID = (ID<<8) | (SFMByte_send(SFM_DUMMY)); // Read a byte from the SFM SFMSel_high(); return ID; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Tahoe 0 9 января, 2013 Опубликовано 9 января, 2013 · Жалоба Да ну? А вы в курсе, что прием и передача происходят синхронно? Один битик выдвинули, один задвинули. И о чем нам это говорит? (с) Какая еще такая "синхронная" связь, между "выдвижением битиков" и выставлением флагов, которые еще через стопицот разных шин, с не пойми какими частотами, доставляются до ядра? В каком порядке эти флаги выставляются, какие там буферизации/задержки, не видя исходного Verilog/VHDL ( на чем там был пИсан этот SPI модуль ), можно только гадать. Или просто воспользоваться описанием в документации. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HHIMERA 0 9 января, 2013 Опубликовано 9 января, 2013 · Жалоба Да ну? А вы в курсе, что прием и передача происходят синхронно? Один битик выдвинули, один задвинули. Неужели??? Вы так и собираетесь мучаться со SPI STM32 на уровне АВР??? ))) Да дочитайте уже референс до конца... спокойно и без нервов... включите воображение... В частности... для чего существует TXE... и что такое непрерывный режим передачи... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 9 января, 2013 Опубликовано 9 января, 2013 · Жалоба Не надо Я лично сталкивался с устройствами, которые отбрасывали посылку, если чипселект не удерживать до окончания клоков. Но раз вам не надо, то конечно, дело ваше. Вообще, у вас очень странная позиция. Если вы утверждаете, что нет разницы между RXNE и BSY, то почему вы упёрлись в использование RXNE? Чисто чтоб поспорить? Короче, утомили вы меня, не стану больше вас отговаривать от глупых поступков. Да и вообще зря я это начал, сразу было понятно, что бесперспективняк. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 9 января, 2013 Опубликовано 9 января, 2013 · Жалоба while (!(SPI1->SR & SPI_SR_TXE)); здесь и даром не нужна... смело можно выкинуть... это верно Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Tahoe 0 9 января, 2013 Опубликовано 9 января, 2013 · Жалоба Я лично сталкивался с устройствами, которые отбрасывали посылку, если чипселект не удерживать до окончания клоков Скажу больше, я даже сталкивался с камнем, который защелкивал CS фронтом последнего клока. :) Хотя, формально, это не был SPI, просто serial interface. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 9 января, 2013 Опубликовано 9 января, 2013 · Жалоба Я лично сталкивался с устройствами, которые отбрасывали посылку, если чипселект не удерживать до окончания клоков. Но раз вам не надо, то конечно, дело ваше. Взгляните на картинку еще раз. Среза при передаче последнего бита b7 нет. Ждать нечего. Вообще, у вас очень странная позиция. Если вы утверждаете, что нет разницы между RXNE и BSY, то почему вы упёрлись в использование RXNE? Чисто чтоб поспорить? А вы? Вы так и собираетесь мучаться со SPI STM32 на уровне АВР??? ))) Да дочитайте уже референс до конца... спокойно и без нервов... включите воображение... В частности... для чего существует TXE... и что такое непрерывный режим передачи... Фантазии отбрасываем. Обсуждаем технические вопросы. Оценки личностных качеств оставляем при себе. Меня больше интересуют биты SSM и SSI. Скажу больше, я даже сталкивался с камнем, который защелкивал CS фронтом последнего клока. :) Хотя, формально, это не был SPI, просто serial interface. О сдвиговых регистрах я упоминал выше. И о чем нам это говорит? (с) Какая еще такая "синхронная" связь, между "выдвижением битиков" и выставлением флагов, которые еще через стопицот разных шин, с не пойми какими частотами, доставляются до ядра? О том, что если флаги дошли до ядра, то битики уже выдвинуты и задвинуты. :) А пока от ядра дойдет до порта, пройдет ох... ох, сколько наносекунд! Так что ведомое устройство уже получит своё. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HHIMERA 0 9 января, 2013 Опубликовано 9 января, 2013 · Жалоба Фантазии отбрасываем. Обсуждаем технические вопросы. А я технически и обсудил... Приведённые вами примеры - "лишь бы работало"... В них возможности SPI STM32 не раскрыты даже частично... но я не настаиваю... Меня больше интересуют биты SSM и SSI. Всё сначала... Что с ними не так??? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Tahoe 0 9 января, 2013 Опубликовано 9 января, 2013 · Жалоба О том, что если флаги дошли до ядра, то битики уже выдвинуты и задвинуты. :) Не надо приписывать флагу то, в чем он "не копенгаген". Битики может и задвинуты, но откуда RXNE знать, что SPI трансфер завершен? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 11 января, 2013 Опубликовано 11 января, 2013 · Жалоба Подправил код для чтения идентификатора SPI Flash Memory, что показывал выше. Такты выдаются непрерывным потоком, сигнал SS стал короче в 1.5 раза. uint32_t SFMID_read(void) { SMSS_ON(); uint32_t id = 0; SPI1->DR = SFM_RDID; // послать команду "RDID" while (!(SPI1->SR & SPI_SR_TXE)); // ждать освобождение передатчика SPI1->DR = SFM_DUMMY; // послать пустой байт while (!(SPI1->SR & SPI_SR_RXNE)); // ждать байт в приемнике id = SPI1->DR; // High Impedance while (!(SPI1->SR & SPI_SR_TXE)); // ждать освобождение передатчика SPI1->DR = SFM_DUMMY; // послать пустой байт while (!(SPI1->SR & SPI_SR_RXNE)); // ждать байт в приемнике id = SPI1->DR << 16; // Manufacturer while (!(SPI1->SR & SPI_SR_TXE)); // ждать освобождение передатчика SPI1->DR = SFM_DUMMY; // послать пустой байт while (!(SPI1->SR & SPI_SR_RXNE)); // ждать байт в приемнике id |= SPI1->DR << 8; // Memory type // while (!(SPI1->SR & SPI_SR_TXE)); // ждать освобождение передатчика while (!(SPI1->SR & SPI_SR_RXNE)); // ждать байт в приемнике id |= SPI1->DR; // Memory capacity // while (SPI1->SR & SPI_SR_BSY); // ждать, если SPI занят SMSS_OFF(); // Test = id; return id; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться