sidy 1 19 декабря, 2012 Опубликовано 19 декабря, 2012 · Жалоба 1. Прочесть DR. 2. Записать в DR байт для передачи. 3. Ждать RXNE (будь-то тупо или путем реакции на прерывание). 4. Перейти к п.1., если еще есть данные для передачи. И еще один момент если я осуществляю обмен таким образом, то часть байтов затирается. Например: я отсылаю следующие данные: 0x9F; 0; 0x9F; 0x9F; 0x9F; 0x9F. На осциллограмме первый байт правильный, второй тоже правильный остальные не правильные. Вместо 0x9F (0b10011111) судя по всему 1F (0b11111). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 15 19 декабря, 2012 Опубликовано 19 декабря, 2012 · Жалоба И еще один момент если я осуществляю обмен таким образом, то часть байтов затирается. Скорее всего косяк у вас в коде. Потому что описанный алгоритм - рабочий. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
cyb 0 19 декабря, 2012 Опубликовано 19 декабря, 2012 · Жалоба Похоже у меня подобная проблема на STM32F103VE. После отсылки байта, не происходит задержи при проверки флага. В общем ситуация номер 1, всё на картинке. Код: GPIO_ResetBits( SD_CS_GPIO_PORT, SD_CS_PIN ); while( SPI_I2S_GetFlagStatus( SD_SPI, SPI_I2S_FLAG_TXE ) == RESET ) /*!< Wait until the transmit buffer is empty */ ; SPI_I2S_SendData( SD_SPI, 0xAA ); /*!< Send the byte */ GPIO_SetBits( SD_CS_GPIO_PORT, SD_CS_PIN ); Ситуация номер 2. Делитель на 2 И ситуация номер 3. Тут вставленна задержка GPIO_ResetBits( SD_CS_GPIO_PORT, SD_CS_PIN ); while( SPI_I2S_GetFlagStatus( SD_SPI, SPI_I2S_FLAG_TXE ) == RESET ) /*!< Wait until the transmit buffer is empty */ ; SPI_I2S_SendData( SD_SPI, 0xAA ); /*!< Send the byte */ __delay_cycles( 45 ); GPIO_SetBits( SD_CS_GPIO_PORT, SD_CS_PIN ); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 15 19 декабря, 2012 Опубликовано 19 декабря, 2012 · Жалоба Похоже у меня подобная проблема на STM32F103VE. После отсылки байта, не происходит задержи при проверки флага. У вас другая проблема. Вы отключаете CS сразу после записи байта в DR, не дожидаясь, пока он уйдёт в линию. Если вы прочитаете эту ветку сначала, то найдёте пару рекомендаций, как это сделать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sidy 1 19 декабря, 2012 Опубликовано 19 декабря, 2012 (изменено) · Жалоба Скорее всего косяк у вас в коде. Потому что описанный алгоритм - рабочий. Привожу кусок кода: первоночально записываю первый байт в передатчик: SPI3->DR=TransmitBuffer[0]; Tx_Data=1; затем обработчик прерываний: void SPI3_IRQHandler (void){ if(Rx_Data>=6) { //Если все передали CS_SET1; return; } if(SPI3->SR&SPI_SR_RXNE){ ReceiveBuffer[Rx_Data++]=SPI3->DR; //Очищаем RXNE чтением DR SPI3->DR=TransmitBuffer[Tx_Data++]; //Передаем следующий байт } } Изменено 19 декабря, 2012 пользователем sidy Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
cyb 0 19 декабря, 2012 Опубликовано 19 декабря, 2012 (изменено) · Жалоба У вас другая проблема. Вы отключаете CS сразу после записи байта в DR, не дожидаясь, пока он уйдёт в линию. Если вы прочитаете эту ветку сначала, то найдёте пару рекомендаций, как это сделать. Ок, спасибо. Я правильно понимаю, что момент когда отпускать CS нужно смотреть по флагу BSY? Изменено 19 декабря, 2012 пользователем cyb Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 15 19 декабря, 2012 Опубликовано 19 декабря, 2012 · Жалоба Привожу кусок кода: Хорошо, давайте разбираться по порядку. Где у вас п.1 ("Прочесть DR.") ? Ок, спасибо. Я правильно понимаю, что момент когда отпускать CS нужно смотреть по флагу BSY? Да, он именно для этого и предназначен. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sidy 1 20 декабря, 2012 Опубликовано 20 декабря, 2012 · Жалоба Хорошо, давайте разбираться по порядку. Где у вас п.1 ("Прочесть DR.") ? Добавил чтение DR, но это ничего не изменило: Recycler=SPI3->DR; SPI3->DR=TransmitBuffer[0]; Tx_Data=1; Обработчик: void SPI3_IRQHandler (void){ if(Rx_Data>=6) { //Если все передали CS_SET1; return; } if(SPI3->SR&SPI_SR_RXNE){ ReceiveBuffer[Rx_Data++]=SPI3->DR; //Очищаем RXNE чтением DR SPI3->DR=TransmitBuffer[Tx_Data++]; //Передаем следующий байт } } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 15 20 декабря, 2012 Опубликовано 20 декабря, 2012 · Жалоба А чему равно Rx_Data? Как настроен SPI, какие прерывания разрешены? Почему вы проверяете if(Rx_Data>=6) вне ветки if(SPI3->SR&SPI_SR_RXNE)? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sidy 1 20 декабря, 2012 Опубликовано 20 декабря, 2012 (изменено) · Жалоба А чему равно Rx_Data? Как настроен SPI, какие прерывания разрешены? Почему вы проверяете if(Rx_Data>=6) вне ветки if(SPI3->SR&SPI_SR_RXNE)? Первоначально Rx_Data=0; Привожу конфигурацию SPI3, прерывания разрешены только по приему. //******************************************************************************** ********* //*Конфигурация SPI3 //******************************************************************************** ********* RCC->APB1ENR|=RCC_APB1ENR_SPI3EN; //Тактирование SPI3 SPI3->CR1|=SPI_CR1_BR_2 |SPI_CR1_BR_1 |SPI_CR1_BR_0 //Скорость Fpclk/256 84 МГц/256=328,125 кГц |SPI_CR1_LSBFIRST //LSB передается вперед |SPI_CR1_SSM //NSS управляется програмно |SPI_CR1_SSI; //NSS=1 SPI3->CR2|=SPI_CR2_SSOE; //NSS в качестве выхода /*CPOL=0 (clock polarity) CK to 0 when idle; CPHA=0 (clock phase) the first clock transition is the first data capture edge DFF=0 (data frame format) 8-bit data format*/ SPI3->CR2|=SPI_CR2_RXNEIE; //Прерывания по окончанию приема и передачи SPI3->CR1|=SPI_CR1_MSTR; //SPI3 режим мастера NVIC_SetPriority(SPI3_IRQn, 3); //Прерывание SPI3 третье по приоритету NVIC_EnableIRQ(SPI3_IRQn); //Разрешаем прерывания SPI3 SPI3->CR1|=SPI_CR1_SPE; //Разрешаем работу SPI3 CS_SET0; //CS=0 Recycler=SPI3->DR; //Прочесть DR SPI3->DR=MASTER_Buffer_Tx[0]; //Первый байт в буфер передачи Tx_Data=1; } void SPI3_IRQHandler (void){ if(SPI3->SR&SPI_SR_RXNE){ SLAVE_Buffer_Rx[Rx_Data++]=SPI3->DR; //Очищаем RXNE чтением DR if(Rx_Data==6){ CS_SET1; return; } SPI3->DR=MASTER_Buffer_Tx[Tx_Data++]; //Следующий байт в буфер передачи } } Изменено 20 декабря, 2012 пользователем sidy Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sidy 1 20 декабря, 2012 Опубликовано 20 декабря, 2012 (изменено) · Жалоба Посмотрел я сейчас осциллограммы и кажется (если я правильно понял, что в SPI нет пауз между байтами) передаю я, то что записываю в буфер передачи (см осциллограмму). Теперь у меня возник вопрос по поводу поднимания CS. Из следующей осциллограммы видно, что при передаче одного байта CS поднимается раньше чем заканчиваются SCK. Как я понял для поднятия CS нужно ждать когда снимется флаг BSY. Но в прерывании не есть хорошо ждать while(!(SPI3->SR&SPI_SR_BSY)). Изменено 20 декабря, 2012 пользователем sidy Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 15 20 декабря, 2012 Опубликовано 20 декабря, 2012 · Жалоба void SPI3_IRQHandler (void){ if(SPI3->SR&SPI_SR_RXNE){ SLAVE_Buffer_Rx[Rx_Data++]=SPI3->DR; //Очищаем RXNE чтением DR if(Rx_Data==6){ CS_SET1; return; } SPI3->DR=MASTER_Buffer_Tx[Tx_Data++]; //Следующий байт в буфер передачи } } Всё же лучше запись в DR тоже засунуть в блок if(SPI3->SR&SPI_SR_RXNE). Потому что случаются прерывания совсем без установленных флагов. Как я понял для поднятия CS нужно ждать когда снимется флаг BSY. Но в прерывании не есть хорошо ждать while(!(SPI3->SR&SPI_SR_BSY)). Там после RXNE ждать максимум пол-бита. Так что ничего страшного. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
cyb 0 20 декабря, 2012 Опубликовано 20 декабря, 2012 · Жалоба Как я понял для поднятия CS нужно ждать когда снимется флаг BSY. Но в прерывании не есть хорошо ждать while(!(SPI3->SR&SPI_SR_BSY)). По идеи ОСРВ должно перехватывать и выполнять параллельно задачи, поэтому зависонов как бы не будет. Только не все ОСРВ, у FreeRTOS например может возникнуть затык, там есть специальная функция для передачи управления другим задачам taskYIELD() Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sidy 1 21 декабря, 2012 Опубликовано 21 декабря, 2012 · Жалоба Спасибо за разъяснения. Задам еще вопрос здесь по поводу data-flash at45db поскольку уже упоминалась в данной теме. Пытаюсь считать с нее device id и manufacture id для этого подаю код команды 0х9F и дополнительно 5 фиктивных байтов (см осциллограммы). На выходе SO получаю не понятную картину. Что это может быть (сигналы WP=1, RESET=1, Vcc=3.3 В)? Или может просто попалась неисправная микросхема. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 15 21 декабря, 2012 Опубликовано 21 декабря, 2012 · Жалоба Похоже, MISO сконфигурирован как выход. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться