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

Вот код:

 

    while ( ( (SPI2 -> SR) & 0x2 ) == RESET)
    {
     //wait until TXE bit is 1
    }
    SPI2 -> DR = d0;

 

 

когда этот код исполняется на чипе, или в дебаггере без брейкпоинтов то на осциллографе я только вижу SCK поднятый а MOSI на нуле.

Но когда я исполняю этот код по очереди линию за линией в дебаггере, или же ставлю брейк поинт в дебаггере между циклом while и строчкой с записью в DR, а затем достигнув брейкпоинта опятй продолжаю исполнять код, то на осциллографе вижу переключение SCK и отсылку битов d0.

 

в чем может быть проблема?

 

Мне например кажется что SPI2 -> DR = d0; который сразу следует после цикла не дает возможности SPI контроллеру быстро среагировать и послать бит, а исполняя код строка за строкой все работает.

 

но ведь с другой стороны, я же циклом проверяю бит ТХЕ!? и если я вышел с цикла то буфер свободен и должен бит нормально отослатся?

(я пробовал тоже самое циклом проверять и бит BSY, тоже самое)

 

есть идеи?

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


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

Вы только посылаете, ничего не читаете?

Покажите, что у вас до и после делается.

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


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

после - бесконечный цикл.

до - ничего касательно этого SPI порта.

 

да, я просто отсылаю один байт. ничего не принимаю.

 

простой тест, отсылаю, а на выходе ножки цепляю на осциллограф посмотреть.

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


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

На тактовые частоты посмотрите, все ли такие, как задумано.

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


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

вот настройка SPI

//=============================================================================
// SPI2 Related configuration
//=============================================================================
// enable SPI2 clock
((RCC_TypeDef *) (RCC_BASE))->APB1ENR |= RCC_APB1ENR_SPI2EN;


// configure SPI2
((SPI_TypeDef *) (SPI2_BASE)) -> CR1 |= (SPI_CR1_SPE | SPI_CR1_CPOL |
SPI_CR1_CPHA | SPI_CR1_MSTR |
SPI_CR1_BR_1 | SPI_CR1_SSM | SPI_CR1_SSI);

 

фпцлк=42MHz, BR=010, когда на осциллографе (в случае если между циклом проверки ТХЕ и записью в регистр DR стоит брейкпоинт) виден SCK , его период примерно 5 MHz.

 

что тут может быть не так?

с настройкой точно нет! Иначе вообще бы не работало! Но байт отсылается ведь! Но отсылается только когда поочередно в дебаггере те две линии кода исполняю.

 

я даже пробовал считывать в переменные содержимое регистра SRи CR1сразу после выхода из цикла проверки на бит ТХЕ. результат:

CR1=б1101010111

(SSM=1,SSI=1,SPE=1,BR=010,MSTR=1,CPOL=1,CPHA=1)

SR=0х2 (т.е. только ТХЕ=1)

 

а после этого идет запись в DR.

все же вроде правильно!

 

в чем может быть причина?

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


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

в чем может быть причина?

Может, в настройках оптимизации. Попробуйте отключить оптимизацию.

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


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

идея такая

данные в регистр

включили передатчик (данные из приемного регистра передаются в сдвиговый)

подождали когда освободиться передающий регистр.

 

может вы не тот флажок смотрите, проверяете что освободился не передающий (сдвиговый) регистр, а проверяет что приемный свободен (в смысле тот в которые кладут данные, которые потом передаются в сдвиговый?)

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


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

идея такая

данные в регистр

включили передатчик (данные из приемного регистра передаются в сдвиговый)

подождали когда освободиться передающий регистр.

 

может вы не тот флажок смотрите, проверяете что освободился не передающий (сдвиговый) регистр, а проверяет что приемный свободен (в смысле тот в которые кладут данные, которые потом передаются в сдвиговый?)

Вы кажется первый мой пост совсем пропустили.

вот же код:

    while ( ( (SPI2 -> SR) & 0x2 ) == RESET)
    {
     //wait until TXE bit is 1
    }
    SPI2 -> DR = d0;

 

если после цикла ставлю брейк, а потом повторно нажимаю кнопку исполнения в дебаггере, то на осциллографе вижу нужное переключение битов.

а если сразу исполняю весь код(или запускаю не из дебаггера а после залива проги в чип) то не вижу.

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


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

ну у меня нет даташита на все стм я не могу проверить реистры биты и названия:(...

 

я просто заметил что ситуация очень похожа на то что слишком быстро вырубается передатчик (или даже стираются данные), если есть брейк поинт или выполнение по строкам, то между вырубанием передатчика(стиранием передаваемого байта) и его запуском проходит достаточно времени чтобы все отправилось, а если разом летит, то вырубается до отправки (ну или стирается байт который отправляете или еще что-то)

 

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

 

БЛИН!!!

 

while ( ( (SPI2 -> SR) & 0x2 ) == RESET) - ждете пока бит равен нулю

в коментах пишите //wait until TXE bit is 1, правильно я понимаю что ждать пока 1?

 

ну и как началась отправка вы сразу вылетаете из цикла, и заменяете отправляемый байт 0

 

SPI2 -> DR = d0;

 

готов спорить что написав

SPI2 -> DR = 0xAA; - увидите на выходе AA

 

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


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

Да нет же!

Все правильно сдесь!

 

while ( ( (SPI2 -> SR) & 0x2 ) == RESET)

 

* Если ТХЕ = 0, то (SPI2 -> SR) & 0x2 ) = 0, и 0 = RESET, цикл продолжает исполнятся

* Если ТХЕ = 1, то (SPI2 -> SR) & 0x2 ) = 1, и 0 != RESET, и мы вылетаем из цыкла!

 

Таким образом я и жду пока бит ТХЕ = 1.

 

 

Проблема значит в чем то другом?

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


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

А что за константа RESET?

 

Вот мой вариант (медленный, вообще-то при выдаче группы бацт готовность проверяю только перед очередным байтом и отдельно - в конце блока для снятия CS):

/* передача байта/слова, возврат считанного */
uint_fast16_t hardware_spi_word(
    uint_fast16_t v        /* значение байта для передачи */
    )
{
    (void) SPI1->DR;    /* clear SPI_SR_RXNE in status register */
    SPI1->DR = (v & SPI_DR_DR);

    // дождаться, пока последний байт выйдет из передатчика
    while ((SPI1->SR & SPI_SR_TXE) == 0)
    ;
    while(!(SPI1->SR & SPI_SR_RXNE))    /* Receive buffer Not Empty */
    ;

    return (SPI1->DR & SPI_DR_DR);
    
}

 

Обратите вниманире на первое чтние DR.

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


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

вот моя константа как объявлена: typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus;

 

а зачем делать вот это: SPI1->DR & SPI_DR_DR ?

 

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


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

а зачем делать вот это: SPI1->DR & SPI_DR_DR ?

Забейте на это. Необходимости в этом нет. Наследство от AT91SAM7S.

У Вас заработало?

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

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


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

да нет не заработало, попробовал также один байт и без цикла послать, тоже самое..

 

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


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

ну остается только последнее SPI2 или SPI1

точно через 2 посылаете? может пишите в 1 а статуса ждете от 2, а он всегда пустой?

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


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

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

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

Гость
Ответить в этой теме...

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

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

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

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

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

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