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

 
 
7 страниц V  < 1 2 3 4 > »   
Reply to this topicStart new topic
> stm32f407 SPI обнаружил косяк
sidy
сообщение Dec 19 2012, 09:25
Сообщение #16


Местный
***

Группа: Участник
Сообщений: 280
Регистрация: 2-11-08
Пользователь №: 41 333



Цитата(KnightIgor @ Nov 17 2012, 02:37) *
1. Прочесть DR.
2. Записать в DR байт для передачи.
3. Ждать RXNE (будь-то тупо или путем реакции на прерывание).
4. Перейти к п.1., если еще есть данные для передачи.

И еще один момент если я осуществляю обмен таким образом, то часть байтов затирается. Например: я отсылаю следующие данные: 0x9F; 0; 0x9F; 0x9F; 0x9F; 0x9F. На осциллограмме первый байт правильный, второй тоже правильный остальные не правильные. Вместо 0x9F (0b10011111) судя по всему 1F (0b11111).
Прикрепленное изображение
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Dec 19 2012, 09:36
Сообщение #17


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(sidy @ Dec 19 2012, 15:25) *
И еще один момент если я осуществляю обмен таким образом, то часть байтов затирается.

Скорее всего косяк у вас в коде. Потому что описанный алгоритм - рабочий.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
cyb
сообщение Dec 19 2012, 13:58
Сообщение #18


Участник
*

Группа: Участник
Сообщений: 39
Регистрация: 29-08-11
Из: Киев
Пользователь №: 66 910



Похоже у меня подобная проблема на 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 );

Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Dec 19 2012, 14:22
Сообщение #19


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(cyb @ Dec 19 2012, 19:58) *
Похоже у меня подобная проблема на STM32F103VE. После отсылки байта, не происходит задержи при проверки флага.

У вас другая проблема. Вы отключаете CS сразу после записи байта в DR, не дожидаясь, пока он уйдёт в линию.
Если вы прочитаете эту ветку сначала, то найдёте пару рекомендаций, как это сделать.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
sidy
сообщение Dec 19 2012, 15:35
Сообщение #20


Местный
***

Группа: Участник
Сообщений: 280
Регистрация: 2-11-08
Пользователь №: 41 333



Цитата(AHTOXA @ Dec 19 2012, 13:36) *
Скорее всего косяк у вас в коде. Потому что описанный алгоритм - рабочий.

Привожу кусок кода:
первоночально записываю первый байт в передатчик:
Код
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++];            //Передаем следующий байт
  }
}


Сообщение отредактировал sidy - Dec 19 2012, 15:35
Go to the top of the page
 
+Quote Post
cyb
сообщение Dec 19 2012, 17:02
Сообщение #21


Участник
*

Группа: Участник
Сообщений: 39
Регистрация: 29-08-11
Из: Киев
Пользователь №: 66 910



Цитата(AHTOXA @ Dec 19 2012, 16:22) *
У вас другая проблема. Вы отключаете CS сразу после записи байта в DR, не дожидаясь, пока он уйдёт в линию.
Если вы прочитаете эту ветку сначала, то найдёте пару рекомендаций, как это сделать.

Ок, спасибо. Я правильно понимаю, что момент когда отпускать CS нужно смотреть по флагу BSY?

Сообщение отредактировал cyb - Dec 19 2012, 17:03
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Dec 19 2012, 17:36
Сообщение #22


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(sidy @ Dec 19 2012, 21:35) *
Привожу кусок кода:

Хорошо, давайте разбираться по порядку. Где у вас п.1 ("Прочесть DR.") ?

Цитата(cyb @ Dec 19 2012, 23:02) *
Ок, спасибо. Я правильно понимаю, что момент когда отпускать CS нужно смотреть по флагу BSY?

Да, он именно для этого и предназначен.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
sidy
сообщение Dec 20 2012, 04:08
Сообщение #23


Местный
***

Группа: Участник
Сообщений: 280
Регистрация: 2-11-08
Пользователь №: 41 333



Цитата(AHTOXA @ Dec 19 2012, 21:36) *
Хорошо, давайте разбираться по порядку. Где у вас п.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++];            //Передаем следующий байт
  }
}

Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Dec 20 2012, 04:28
Сообщение #24


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



А чему равно Rx_Data?
Как настроен SPI, какие прерывания разрешены?
Почему вы проверяете if(Rx_Data>=6) вне ветки if(SPI3->SR&SPI_SR_RXNE)?


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
sidy
сообщение Dec 20 2012, 04:51
Сообщение #25


Местный
***

Группа: Участник
Сообщений: 280
Регистрация: 2-11-08
Пользователь №: 41 333



Цитата(AHTOXA @ Dec 20 2012, 08:28) *
А чему равно 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++];        //Следующий байт в буфер передачи
}
}


Сообщение отредактировал sidy - Dec 20 2012, 04:52
Go to the top of the page
 
+Quote Post
sidy
сообщение Dec 20 2012, 06:41
Сообщение #26


Местный
***

Группа: Участник
Сообщений: 280
Регистрация: 2-11-08
Пользователь №: 41 333



Посмотрел я сейчас осциллограммы и кажется (если я правильно понял, что в SPI нет пауз между байтами) передаю я, то что записываю в буфер передачи (см осциллограмму).
Прикрепленное изображение


Теперь у меня возник вопрос по поводу поднимания CS. Из следующей осциллограммы видно, что при передаче одного байта CS поднимается раньше чем заканчиваются SCK.
Прикрепленное изображение


Как я понял для поднятия CS нужно ждать когда снимется флаг BSY. Но в прерывании не есть хорошо ждать while(!(SPI3->SR&SPI_SR_BSY)).

Сообщение отредактировал sidy - Dec 20 2012, 06:41
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Dec 20 2012, 07:16
Сообщение #27


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(sidy @ Dec 20 2012, 10:51) *
Код
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). Потому что случаются прерывания совсем без установленных флагов.

Цитата(sidy @ Dec 20 2012, 12:41) *
Как я понял для поднятия CS нужно ждать когда снимется флаг BSY. Но в прерывании не есть хорошо ждать while(!(SPI3->SR&SPI_SR_BSY)).

Там после RXNE ждать максимум пол-бита. Так что ничего страшного.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
cyb
сообщение Dec 20 2012, 09:22
Сообщение #28


Участник
*

Группа: Участник
Сообщений: 39
Регистрация: 29-08-11
Из: Киев
Пользователь №: 66 910



Цитата
Как я понял для поднятия CS нужно ждать когда снимется флаг BSY. Но в прерывании не есть хорошо ждать while(!(SPI3->SR&SPI_SR_BSY)).

По идеи ОСРВ должно перехватывать и выполнять параллельно задачи, поэтому зависонов как бы не будет. Только не все ОСРВ, у FreeRTOS например может возникнуть затык, там есть специальная функция для передачи управления другим задачам taskYIELD()
Go to the top of the page
 
+Quote Post
sidy
сообщение Dec 21 2012, 12:08
Сообщение #29


Местный
***

Группа: Участник
Сообщений: 280
Регистрация: 2-11-08
Пользователь №: 41 333



Спасибо за разъяснения. Задам еще вопрос здесь по поводу data-flash at45db поскольку уже упоминалась в данной теме. Пытаюсь считать с нее device id и manufacture id для этого подаю код команды 0х9F и дополнительно 5 фиктивных байтов (см осциллограммы). На выходе SO получаю не понятную картину. Что это может быть (сигналы WP=1, RESET=1, Vcc=3.3 В)? Или может просто попалась неисправная микросхема.
Прикрепленное изображение

Прикрепленное изображение

Прикрепленное изображение
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Dec 21 2012, 15:32
Сообщение #30


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Похоже, MISO сконфигурирован как выход.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post

7 страниц V  < 1 2 3 4 > » 
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


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


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