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

 
 
3 страниц V   1 2 3 >  
Reply to this topicStart new topic
> STM32F4Discovery SPI, сигнал CS, что-то пошло не так
ilkz
сообщение Sep 9 2015, 10:49
Сообщение #1


Частый гость
**

Группа: Участник
Сообщений: 135
Регистрация: 9-09-11
Пользователь №: 67 084



Друзья, не могу понять в чем дело.
Завожу SPI в режиме мастера, сигналом CS управляю как отдельным пином.
Ожидаю поведения, когда он (CS) нулем подчеркивает все данные, но он почему-то этого не делает (см картинку).
Самое интересное, что если в начало тела while(1) дописать что-то типа printf("spi send %X\n", 0xC1);, то CS начинает формироваться правильно.

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

CODE
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);
}
}


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





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 - Sep 9 2015, 19:36
Причина редактирования: [codeebox] для длинного кода, [code] - для короткого!
Go to the top of the page
 
+Quote Post
esaulenka
сообщение Sep 9 2015, 11:23
Сообщение #2


Профессионал
*****

Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877



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

Они это и сами признают:
Цитата(Reference manual)
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


--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
Go to the top of the page
 
+Quote Post
ilkz
сообщение Sep 9 2015, 11:28
Сообщение #3


Частый гость
**

Группа: Участник
Сообщений: 135
Регистрация: 9-09-11
Пользователь №: 67 084



Цитата(esaulenka @ Sep 9 2015, 14:23) *
Какой-то странный флаг у ST-шников получился, да.

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


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

Как вы выходите из положения?
Go to the top of the page
 
+Quote Post
esaulenka
сообщение Sep 9 2015, 11:37
Сообщение #4


Профессионал
*****

Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877



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


--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
Go to the top of the page
 
+Quote Post
ilkz
сообщение Sep 9 2015, 11:43
Сообщение #5


Частый гость
**

Группа: Участник
Сообщений: 135
Регистрация: 9-09-11
Пользователь №: 67 084



:-)
С приемом да - все понятно.
Вопрос с только передачей.
Переадресую его к аудитории: как вы управляете сигналом CS, если SPI работает только на отправку?
Go to the top of the page
 
+Quote Post
Obam
сообщение Sep 9 2015, 11:53
Сообщение #6


Знающий
****

Группа: Участник
Сообщений: 756
Регистрация: 14-11-14
Пользователь №: 83 663



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

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


--------------------
Пролетарий умственного труда.
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Sep 9 2015, 11:57
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



Можно поилить TXE и BSY, или действительно что проще по RXNE,
Go to the top of the page
 
+Quote Post
ilkz
сообщение Sep 9 2015, 12:06
Сообщение #8


Частый гость
**

Группа: Участник
Сообщений: 135
Регистрация: 9-09-11
Пользователь №: 67 084



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

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


не работает - все равно нужна задержка между send() и while().
Go to the top of the page
 
+Quote Post
Obam
сообщение Sep 9 2015, 12:24
Сообщение #9


Знающий
****

Группа: Участник
Сообщений: 756
Регистрация: 14-11-14
Пользователь №: 83 663



Удалено. Согласен с rudy_b

Сообщение отредактировал Obam - Sep 9 2015, 12:32


--------------------
Пролетарий умственного труда.
Go to the top of the page
 
+Quote Post
rudy_b
сообщение Sep 9 2015, 12:25
Сообщение #10


Знающий
****

Группа: Свой
Сообщений: 888
Регистрация: 25-09-08
Из: Питер
Пользователь №: 40 458



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

Рекомендованные действия:
1. Wait until TXE=1
2. Then wait until BSY=0

Вероятно можно использовать и RXNE, но не проверял его работу при настройке только на передачу.
Go to the top of the page
 
+Quote Post
ilkz
сообщение Sep 9 2015, 12:53
Сообщение #11


Частый гость
**

Группа: Участник
Сообщений: 135
Регистрация: 9-09-11
Пользователь №: 67 084



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);
}


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


Как видим, сдвинулось на 1 клок laughing.gif
Go to the top of the page
 
+Quote Post
rudy_b
сообщение Sep 9 2015, 13:05
Сообщение #12


Знающий
****

Группа: Свой
Сообщений: 888
Регистрация: 25-09-08
Из: Питер
Пользователь №: 40 458



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

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

P.S. А можно попробовать сначала дождаться busy=1, а, потом, busy=0. Но аккуратно, это чревато осложнениями при наличии прерываний.
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Sep 9 2015, 13:08
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



Ну может тогда еще проще
Код
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);
}
Go to the top of the page
 
+Quote Post
Obam
сообщение Sep 9 2015, 13:37
Сообщение #14


Знающий
****

Группа: Участник
Сообщений: 756
Регистрация: 14-11-14
Пользователь №: 83 663



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

Сообщение отредактировал Obam - Sep 9 2015, 13:40


--------------------
Пролетарий умственного труда.
Go to the top of the page
 
+Quote Post
ilkz
сообщение Sep 9 2015, 13:47
Сообщение #15


Частый гость
**

Группа: Участник
Сообщений: 135
Регистрация: 9-09-11
Пользователь №: 67 084



Вроде как 168МГц.
Go to the top of the page
 
+Quote Post

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

 


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


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