Перейти к содержанию
    

STM32F4Discovery SPI, сигнал CS

Друзья, не могу понять в чем дело.

Завожу SPI в режиме мастера, сигналом CS управляю как отдельным пином.

Ожидаю поведения, когда он (CS) нулем подчеркивает все данные, но он почему-то этого не делает (см картинку).

Самое интересное, что если в начало тела while(1) дописать что-то типа printf("spi send %X\n", 0xC1);, то CS начинает формироваться правильно.

 

Код привожу ниже.

 

void spi2_init(void){
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_SPI2); // sck
GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_SPI2); // mosi
GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_SPI2); // miso

GPIO.GPIO_Mode = GPIO_Mode_AF;
GPIO.GPIO_Speed = GPIO_Speed_50MHz;
GPIO.GPIO_OType = GPIO_OType_PP;
GPIO.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_Init(GPIOB, &GPIO);

SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_Init(SPI2, &SPI_InitStructure);
//SPI_I2S_ITConfig(SPI2,SPI_I2S_IT_RXNE,ENABLE);
SPI_Cmd(SPI2, ENABLE);
SPI_NSSInternalSoftwareConfig(SPI2, SPI_NSSInternalSoft_Set);

GPIO.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12;
GPIO.GPIO_Mode = GPIO_Mode_OUT;
GPIO.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init (GPIOB, &GPIO);
}

void spi2_send(uint8_t value) {
SPI_I2S_SendData(SPI2, value);
while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET);
}

void ad_send(uint8_t value) {
GPIO_ResetBits(GPIOB, GPIO_Pin_12);
spi2_send(value);
GPIO_SetBits(GPIOB, GPIO_Pin_12);
}

int main(void) {
SystemInit();
TM_DELAY_Init();
TM_DISCO_LedInit();
spi2_init();
while (1) {
	//printf("spi send %X\n", 0xC1);
	ad_send(0xC1);
	Delayms(1);
}
}

 

post-67084-1441792417_thumb.png

 

 

 

 

UPD:

Опытным путем выяснилось, что если вставить задержку между SPI_I2S_SendData() и ожиданием флага SPI_I2S_FLAG_BSY, то все начинает работать:

 

void spi2_send(uint8_t value) {
    int i;
    SPI_I2S_SendData(SPI2, value);
    for(i=0; i<63; i++);
    while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET);
}

 

Получается что нельзя проверяь флаг SPI_I2S_FLAG_BSY сразу после отправки? Он что, не успевает встать?

Изменено пользователем IgorKossak
[codeebox] для длинного кода, [code] - для короткого!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Какой-то странный флаг у ST-шников получился, да.

 

Они это и сами признают:

Note: Do not use the BSY flag to handle each data transmission or reception. It is better to use the

TXE and RXNE flags instead

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Какой-то странный флаг у ST-шников получился, да.

 

Они это и сами признают:

 

Ок, допустим. Но рекомендуемый ими флаг TXE имеет не совсем то поведение что нужно: он единичится, когда данные попадают в сдвиговый регистр, а не когда они из него улетели на улицу. Т.е. для управления собственным сигналом CS испоьзование флага TXE не подходит.

 

Как вы выходите из положения?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вопрос крайне интересен :-)

Мне всегда был нужен двунаправленный SPI, в этом случае отлично работает метод "положили в DR, подождали RXNE, считали DR".

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

:-)

С приемом да - все понятно.

Вопрос с только передачей.

Переадресую его к аудитории: как вы управляете сигналом CS, если SPI работает только на отправку?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

"…как вы управляете сигналом CS, если SPI работает только на отправку?…"

 

Вот именно так и управляем :)

RXNE==1 равнозначен полностью завершённой транзакции.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну ок, логика вида:

 

void spi2_send(uint8_t value) {
    SPI_I2S_SendData(SPI2, value);
    while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);
}

 

не работает - все равно нужна задержка между send() и while().

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Это стандартная проблема для всей криворукой периферии Stm32, особенно раздражает в RTC. Хардовый автомат тактируется не клоками проца, а деленными клоками периферии. Соответственно, busy устанавливается с задержкой по клоку периферии. А догадаться асинхронно установить busy по загрузке данных DR сразу у них ума не хватило.

 

Рекомендованные действия:

1. Wait until TXE=1

2. Then wait until BSY=0

 

Вероятно можно использовать и RXNE, но не проверял его работу при настройке только на передачу.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

rudy_b, проверяем:

 

void spi2_send(uint8_t value) {
    SPI_I2S_SendData(SPI2, value);
    while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == 1);
    while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == 0);
}

 

post-67084-1441803179_thumb.png

 

Как видим, сдвинулось на 1 клок :laughing:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Рекомендация - из их даташита (stm32F207).

 

Ну, какой-то прогресс есть. Можно попробовать еще (до анализа busy) подождать RXNE.

 

P.S. А можно попробовать сначала дождаться busy=1, а, потом, busy=0. Но аккуратно, это чревато осложнениями при наличии прерываний.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну может тогда еще проще

void spi2_send(uint8_t value) {
    SPI_I2S_SendData(SPI2, value);
    while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == 1);
    while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == 0);
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

SPI в 8 раз медленней ядра (пост #1); на какой частоте ядро "молотит" что флаги не успевают (с т.з. ядра) высталяться\сниматься?

Изменено пользователем Obam

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...