|
STM32F407 Проблемы с SPI, Не отсылается байт сразу после проверки бита ТХЕ в регистре SR |
|
|
|
Apr 21 2013, 05:50
|

Знающий
   
Группа: Свой
Сообщений: 618
Регистрация: 7-06-08
Из: USSR
Пользователь №: 38 121

|
Вот код: Код 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, тоже самое) есть идеи?
--------------------
Нажми на кнопку - получишь результат, и твоя мечта осуществится
|
|
|
|
|
 |
Ответов
(1 - 76)
|
Apr 21 2013, 08:30
|

Знающий
   
Группа: Свой
Сообщений: 618
Регистрация: 7-06-08
Из: USSR
Пользователь №: 38 121

|
вот настройка 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. все же вроде правильно! в чем может быть причина?
--------------------
Нажми на кнопку - получишь результат, и твоя мечта осуществится
|
|
|
|
|
Apr 21 2013, 08:43
|

Знающий
   
Группа: Свой
Сообщений: 618
Регистрация: 7-06-08
Из: USSR
Пользователь №: 38 121

|
Цитата(Golikov A. @ Apr 21 2013, 13:41)  идея такая данные в регистр включили передатчик (данные из приемного регистра передаются в сдвиговый) подождали когда освободиться передающий регистр.
может вы не тот флажок смотрите, проверяете что освободился не передающий (сдвиговый) регистр, а проверяет что приемный свободен (в смысле тот в которые кладут данные, которые потом передаются в сдвиговый?) Вы кажется первый мой пост совсем пропустили. вот же код: Код while ( ( (SPI2 -> SR) & 0x2 ) == RESET) { //wait until TXE bit is 1 } SPI2 -> DR = d0; если после цикла ставлю брейк, а потом повторно нажимаю кнопку исполнения в дебаггере, то на осциллографе вижу нужное переключение битов. а если сразу исполняю весь код(или запускаю не из дебаггера а после залива проги в чип) то не вижу.
--------------------
Нажми на кнопку - получишь результат, и твоя мечта осуществится
|
|
|
|
|
Apr 21 2013, 12:54
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
ну у меня нет даташита на все стм я не могу проверить реистры биты и названия  ... я просто заметил что ситуация очень похожа на то что слишком быстро вырубается передатчик (или даже стираются данные), если есть брейк поинт или выполнение по строкам, то между вырубанием передатчика(стиранием передаваемого байта) и его запуском проходит достаточно времени чтобы все отправилось, а если разом летит, то вырубается до отправки (ну или стирается байт который отправляете или еще что-то) Потому просто предложил проверить правильно ли выбран бит контроля окончания отправки, и правильный ли у него уровень. БЛИН!!! while ( ( (SPI2 -> SR) & 0x2 ) == RESET) - ждете пока бит равен нулю в коментах пишите //wait until TXE bit is 1, правильно я понимаю что ждать пока 1? ну и как началась отправка вы сразу вылетаете из цикла, и заменяете отправляемый байт 0 SPI2 -> DR = d0; готов спорить что написав SPI2 -> DR = 0xAA; - увидите на выходе AA
|
|
|
|
|
Apr 21 2013, 17:37
|

Профессионал
    
Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634

|
А что за константа 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.
|
|
|
|
|
Apr 21 2013, 18:21
|

Знающий
   
Группа: Свой
Сообщений: 618
Регистрация: 7-06-08
Из: USSR
Пользователь №: 38 121

|
Да, как яуже говорил, если например ставлю брейк межу циклом и между отправкой, то все работает (если SPI2 были бы сконфигурированы не верне, не работало бы вообще!)
еще работает тогда, когда я например в дебаггере по очереди пальцем жму на исполнение каждой строки этого кода..
а прогоняя весь код не работает! причем проблема именно в этих двух линиях! но какая именно понять не могу?
еще вот какой вариант работает:
никаких циклов, ничего, ставлю только это: SPI2->DR = d0; НО! перед этой строкоы ставлю брейк!
в дебаггере исполняю, доходит до брейка, и на осциллографе вижу как преже поднятй SCK и нулевой MOSI! Но потом, нажимаю кнопку Run опять, и уже исполняыется вышеописанная команда!И вот вижу свой байт на осциллографе и переключение SCK!
А вот если без брейка... т.е. сразу запустить всю прогу! то только вижу приподнятй SCK и нулевой MOSI!
Это на какие либо мысли толкает? что это может быть?
--------------------
Нажми на кнопку - получишь результат, и твоя мечта осуществится
|
|
|
|
|
Apr 21 2013, 18:41
|

Знающий
   
Группа: Свой
Сообщений: 618
Регистрация: 7-06-08
Из: USSR
Пользователь №: 38 121

|
вот по вашему образцу код мой: Код (void) SPI2->DR; /* clear SPI_SR_RXNE in status register */ // breakpoint here! SPI2->DR = (d0 & SPI_DR_DR);
while ((SPI2->SR & SPI_SR_TXE) == 0) ; Видите коммент где про breakpoint сказано?так вот если ставлю туда брейкпоинт, дохожу до него и опять стартую то работает! если без брейк поинта, то не работает когда исполняется все сразу! не могу понать почему?
--------------------
Нажми на кнопку - получишь результат, и твоя мечта осуществится
|
|
|
|
|
Apr 21 2013, 19:05
|

Знающий
   
Группа: Свой
Сообщений: 618
Регистрация: 7-06-08
Из: USSR
Пользователь №: 38 121

|
естесственно хватает, вот что вижу на осциллографе когда работает: [DELETED]а вот когда не работает: [DELETED]чтото пост большой какойто стал :Р без дебаггера тоже не работает! т.е. если на чип заливаю, и включаю, то не работает! Никакой функции нету! исполняю прямо кодом для простоты! вот один из кодов привожу еще раз, где в комменте указано если там стоит брейк то работает, если нет брейка то не работает. Код (void) SPI2->DR; /* clear SPI_SR_RXNE in status register */ // breakpoint here! SPI2->DR = (d0 & SPI_DR_DR);
while ((SPI2->SR & SPI_SR_TXE) == 0) ; да! я знаю! проблема сократилась! но дело в том что непонятно в чем сейчас дело... все просто...убираю брейк не работает если прогорняыется код сразу! ставлю брейк вижу сначала изображение №2 в посте, потом вновь запускаю как только достиг брейка, и вижу изображение №1 (т.е. рабочее) а если нет брейка, т.е. сразу прогоняыется весь код, то тока изображение №2!
Сообщение отредактировал IgorKossak - Apr 22 2013, 08:01
Причина редактирования: изображения следует прикреплять к сообщению, а не вставлять
--------------------
Нажми на кнопку - получишь результат, и твоя мечта осуществится
|
|
|
|
|
Apr 21 2013, 19:14
|

Знающий
   
Группа: Свой
Сообщений: 618
Регистрация: 7-06-08
Из: USSR
Пользователь №: 38 121

|
Цитата(Golikov A. @ Apr 21 2013, 22:50)  все выглядит каким то чудом. а вот так если сделать
int dummy = SPI2->DR; SPI2->DR = 0xAA; while(1);
что будет? ничего не будет, тоже не работает! а вот если ставлю брейк на линии int dummy = SPI2->DR; исполняю код, дохожу до брейка, затем опять исполняют, то работает! не могу понять в чем дело! Цитата(Genadi Zawidowski @ Apr 21 2013, 23:12)  Так... 1) А что с выходом чипселекта? Сказать что есть и не подкдючаться к нему: const uint_fast32_t cr1bits = SPI_CR1_MSTR | SPI_CR1_SSM | SPI_CR1_SPE | baudrate; const uint_fast32_t cr1bits16w = cr1bits | SPI_CR1_DFF;
0) У STM32F1xxx есть errata: // Silicon errata: // 2.6.7 I2C1 with SPI1 remapped and used in master mode // Workaround: // When using SPI1 remapped, the I2C1 clock must be disabled.
ВЫ не дожидаетесь пока байт передастся (когда примется обратно!). Зачем сократили мой код? Там же это было! да но ведь я же использую SPI2 а не SPI1!
--------------------
Нажми на кнопку - получишь результат, и твоя мечта осуществится
|
|
|
|
|
Apr 21 2013, 19:31
|

Знающий
   
Группа: Свой
Сообщений: 618
Регистрация: 7-06-08
Из: USSR
Пользователь №: 38 121

|
попробовал добавление SPI_CR1_DFF, тоже самое, не работает если прогонять код сразу. NSS я не использую! И не используя его но исполняя код по строчкам все работает! Пытатся использовать ег сейчас думаю только усложнит проблему! Ведь ллогически, если сам интерфейс работае в дебаггере когда исполняется по строчкам.. почему он не должен работать когда разом исполняется весь код! вот в чем дело я не думаю чтоэто какое то отношение имеет к NSS. Просто я не могу понять что еще тут может быть? Цитата(Golikov A. @ Apr 21 2013, 23:20)  Не ну тоды магия.
А во придумал!!! А если так? while ( (SPI2->SR & SPI_SR_TXE) ==0 ); int dummy = SPI2->DR; SPI2->DR = 0xAA; while(1);
и как проверить что прием окончен?
Может у вас вызов идет во время приема потому ничего и не работает? А когда перед записью регистра есть брек поинт, проц успевает что-то принять или передать... нет. и так не работает! И нет у меня никакого приема! все просто в тех строчках которые я привел! просто использую пины SCK и MOSI и подключаю их к осциллографу! никакого приема или ччего то еще!
--------------------
Нажми на кнопку - получишь результат, и твоя мечта осуществится
|
|
|
|
|
Apr 21 2013, 19:53
|

Знающий
   
Группа: Свой
Сообщений: 618
Регистрация: 7-06-08
Из: USSR
Пользователь №: 38 121

|
Ну а что там разбиратся? у меня и SSM=1 и SSI = 1 Когда SSM=1 то програмное управление слейвом включено. в таком случае значение бита SSI передается на ногу NSS, и то что на ноге NSS извне игнорируется! Цитата Bit 8SSI:Internal slave select This bit has an effect only when the SSM bit isset. The value of this bit is forced onto the NSS pin and the IO value of the NSS pin is ignored. иными словами этим битом можно ногой NSS управлять. в моемслучае это вообще не принципиально... т.е. с этим я разобрался и это думаю к данной проблеме не имеет отношения. Ил я не прав в чем то?
--------------------
Нажми на кнопку - получишь результат, и твоя мечта осуществится
|
|
|
|
|
Apr 21 2013, 20:41
|

Знающий
   
Группа: Свой
Сообщений: 618
Регистрация: 7-06-08
Из: USSR
Пользователь №: 38 121

|
проц нормально запускается и работает без дебаггера, т.к. я другие рабочие куски вставлял в программу перед своим тестовым кодом. вот как я считываю сейчас регистры: SR,CR1,CR2 кодом своим: Код while ( (SPI2->SR & SPI_SR_TXE) ==0 ); sr_t = SPI2->SR; cr1_t = SPI2->CR1; cr2_t = SPI2->CR2; // breakpoint here! SPI2->DR = 0xAA; и вот что вижу в дебаггере, все вроде нормально CR1=б1101010111 (SSM=1,SSI=1,SPE=1,BR=010,MSTR=1,CPOL=1,CPHA=1) SR=0х2 (т.е. только ТХЕ=1) CR2=0 сделал так как Вы предлагли через USART тоже. вот код: Код while ( (SPI2->SR & SPI_SR_TXE) ==0 ) { while(!(USART3->SR & USART_SR_TXE)); // check if TXE bit is set USART3->DR = (uint8_t)( (SPI2->SR)>>8 ); // sending a byte while(!(USART3->SR & USART_SR_TC)); // check if TC bit is set
while(!(USART3->SR & USART_SR_TXE)); // check if TXE bit is set USART3->DR = (uint8_t)( SPI2->SR); // sending a byte while(!(USART3->SR & USART_SR_TC)); // check if TC bit is set }
while(!(USART3->SR & USART_SR_TXE)); // check if TXE bit is set USART3->DR = (uint8_t)( (SPI2->SR)>>8 ); // sending a byte while(!(USART3->SR & USART_SR_TC)); // check if TC bit is set
while(!(USART3->SR & USART_SR_TXE)); // check if TXE bit is set USART3->DR = (uint8_t)( SPI2->SR); // sending a byte while(!(USART3->SR & USART_SR_TC)); // check if TC bit is set
SPI2->DR = d0; в USART увидел только два полученных байта: 00 02 что говорит о том что, то что внутри while цикла не выполнилось, т.к. ТХЕбыл уже равен 1 (т.е. буфер отправки данных изначально ыл свободен) А затем я получилдва байта 00 02, перед SPI2->DR = d0; как Вы и предлагали изначение 02 говорит что ТХЕ по пренему равен 1, т.е. буфер свободен. но не работает это! на осцилографе вижу подтянутый ввех SCK и нулевой MOSI есть какие идеи?
--------------------
Нажми на кнопку - получишь результат, и твоя мечта осуществится
|
|
|
|
|
Apr 21 2013, 21:04
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
ну тогда только что есть какое то прерывание, которое непонятно как все ставит раком. Потому что я так понимаю данные попавшие в регистр DR должны выдавиться полюбому, а мы видим что они не выдавливаются...
а если в том месте где вы ставите брекпоинт поставить for(volatile int i=0;i<32000;i++) __NOP(); ну вообщем любую тупую задержку, да на побольше, чтобы секунда прям вышла... несколько раз цикл воткните... хотя отправки по уарту уже сделали эту задержку...
А воткните циклы выдачи на уарт значения SR после строчки SPI2->DR = Data; ну так для полноты картины...
думаю что уже все проверили, может чип какой то подгоревший? Фиг же его знает, если бы SPI так странно не работал это бы все заметили...
Есть у меня последняя идея.
Может там какая просадка или помеха по питанию при попытке отправки по SPI, которая реально вешает проц... Циклы выдачи после DR=d0; Должны помочь понять. Если вы ставите брек поинт или медленно идете тока хватает, а если программа быстро летит, что-то проседает и кирдык?
|
|
|
|
|
Apr 21 2013, 21:10
|

Знающий
   
Группа: Свой
Сообщений: 618
Регистрация: 7-06-08
Из: USSR
Пользователь №: 38 121

|
ладно, мне кажется я частичто решил проблему. Сейчас работаю БЕЗ дебаггера, компилирую заливаю на чип включаю плату (хотя в дебаггере поведение такоеже) вот фрагмент кода №1, как уже знаете просто цикл проверки и отправка байта. Код while ( (SPI2->SR & SPI_SR_TXE) ==0 ) {
}
SPI2->DR = d0; А вот фрагмент кода №2 Код for(;;) {
if ((USART3->SR & USART_SR_RXNE)) if (USART3->DR == 0x01) break; } Этот код просто бесконечный цикл, пока с USART3 не будет получена команда 01, как только эта команда получена цикл прерывается, и исполнение программы переходит к фрагменту кода №1 Так вот, компилю, заливаю на флеш. Затем включаю плату, естесственно ничег не происходит т.к. цикл фрагмента кода №2 работает, затем подаю команду 01 с USART3 и немедленно вижу свой байт на осциллографе! Вобщемто заработало на чипе и без дебаггера с брейк поинтами... но просто интерестно, в чем же была проблема? Выходит проблема была в том что когда я подаю питание на плату (и на чип естесственно) то толи порт вывода толи SPI2 периферия еще не успела войти в рабочий режим необходимый для отправки данных? Или чтото вроде того? Что думаете?
--------------------
Нажми на кнопку - получишь результат, и твоя мечта осуществится
|
|
|
|
|
Apr 21 2013, 21:37
|

Знающий
   
Группа: Свой
Сообщений: 618
Регистрация: 7-06-08
Из: USSR
Пользователь №: 38 121

|
да было иначе периферия не работала бы вообще. Вот еще один интересный тест сделал(как вы говорили проверил также статус после записи), вот код (в этот раз убрал бесконечный цикл в начале): Код while ( (SPI2->SR & SPI_SR_TXE) ==0 ) { while(!(USART3->SR & USART_SR_TXE)); // check if TXE bit is set USART3->DR = (uint8_t)( (SPI2->SR)>>8 ); // sending a byte while(!(USART3->SR & USART_SR_TC)); // check if TC bit is set
while(!(USART3->SR & USART_SR_TXE)); // check if TXE bit is set USART3->DR = (uint8_t)( SPI2->SR); // sending a byte while(!(USART3->SR & USART_SR_TC)); // check if TC bit is set }
while(!(USART3->SR & USART_SR_TXE)); // check if TXE bit is set USART3->DR = (uint8_t)( (SPI2->SR)>>8 ); // sending a byte while(!(USART3->SR & USART_SR_TC)); // check if TC bit is set
while(!(USART3->SR & USART_SR_TXE)); // check if TXE bit is set USART3->DR = (uint8_t)( SPI2->SR); // sending a byte while(!(USART3->SR & USART_SR_TC)); // check if TC bit is set
SPI2->DR = d0;
while(!(USART3->SR & USART_SR_TXE)); // check if TXE bit is set USART3->DR = (uint8_t)( (SPI2->SR)>>8 ); // sending a byte while(!(USART3->SR & USART_SR_TC)); // check if TC bit is set
while(!(USART3->SR & USART_SR_TXE)); // check if TXE bit is set USART3->DR = (uint8_t)( SPI2->SR); // sending a byte while(!(USART3->SR & USART_SR_TC)); // check if TC bit is set И вот некоторые наблюдения: 1) Когда я скомпилировал и зашил контроллер, то я не только не увиден на осциллографе свой байт, но я еще и не увидел байты полученные от USART3!! Интерестно нет? 2) Затем перед кодом который показан выше я добавляю фрагмент кода №2из моего предыдущего поста(непрерывный цикл с ожиданием команды от USART3), комилю, заливаю, включаю..естесственно ничего пока не происходит т.к. нет команды от USART3 на прерывание цикла, подаю команду на прерывание цикла, И вижу свой отправленныйбайт на осциллографе! А также вижу уже 4 полученных байта, и вот они: 00 02 до посылки 00 03 после посылки! Как видите интерестно то что после посылки не только TXE=1 но и RXNE=1 что говорит о том что приемник полный.. (хотя странно ничего я не принимаю..) Тем не менее... явно видно то что некоторые периферии почемуто не хотят работать почти сразу после того как чип запустился.. Ну по крайней мере такой вывод можно сделать из этих наблюдений? Если есть какие то еще идеи интерестно было бы узнать Цитата(Golikov A. @ Apr 22 2013, 02:15)  думаю стоит ли у вас микросхема рессета проца? стоит просто ресет кнопка на плате, сбрасывание не помогало ничем
--------------------
Нажми на кнопку - получишь результат, и твоя мечта осуществится
|
|
|
|
|
Apr 22 2013, 03:29
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
 а как SPI должен отличить есть что-то на входе или нет? Входная нога в каком то состоянии, клоки тикают, значит через 8-9 клоков входной регистр наберет значение. В примере кода что вам давали выше, была проверка не только на отправку, ну и на прием, а перед отправкой байта всегда еще происходил забор пришедшего. Такова суть СПИ, как включили клок генератор, так байт не только отправиться но и примется... Кстати вот интересный момент, а где вы включаете клок генератор? Он в STM автоматом что ли включается по записи байта в DR? Думаю что после загрузки первое что надо делать это настроить клоки, дождаться везде выставленных флагов, что все клоковые линии работают как надо, а уж потом инициализировать и включат периферию... Но в целом крайне странное поведение, что после старта и передачи управления в main процессор полурабочий. Там же должен быть еще файл стартапа....
|
|
|
|
|
Apr 22 2013, 03:48
|
Местный
  
Группа: Участник
Сообщений: 226
Регистрация: 10-07-09
Пользователь №: 51 126

|
Цитата(BlackOps @ Apr 22 2013, 00:37)  Интерестно нет? Ничего интересного... подобная тема уже была... SPI работает так, как заявлено в даташите... остальное всё от недопонимания... Цитата Если есть какие то еще идеи интерестно было бы узнать Читать даташит до просветления... в части тактирования ядра, тактирования SPI и работы самого SPI... Исходите из того, что транзакция начинается не сразу после загрузки DR... следовательно... и изменение TXE происходит не сразу...
Сообщение отредактировал HHIMERA - Apr 22 2013, 03:49
|
|
|
|
|
Apr 22 2013, 04:26
|

Знающий
   
Группа: Свой
Сообщений: 618
Регистрация: 7-06-08
Из: USSR
Пользователь №: 38 121

|
Цитата(Golikov A. @ Apr 22 2013, 08:29)  Кстати вот интересный момент, а где вы включаете клок генератор? Он в STM автоматом что ли включается по записи байта в DR? Его я включаю перед тем как начать работать с СПИ. Вот так: Код //============================================================================= // 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); Цитата(Golikov A. @ Apr 22 2013, 08:05)  А тем более упоминания о паузе перед посылкой которая влияет на его работоспособность. Также не нашел никаких битиков говорящих о неработоспособности или о том что еще не вышло время подготовки SPI. тоже самое делал и я после тех двух описанных мною тестов в посте №34 и №32. Согласен, Пустые умные посты типа "все происходит от недопонимания" никому не интерестны, если кто понял и знает в чем именно проблема и желает поделится, буду рад посмотреть, если нет то и постить не стоит. Цитата(HHIMERA @ Apr 22 2013, 07:48)  транзакция начинается не сразу после загрузки DR... следовательно... и изменение TXE происходит не сразу... а это не важно, т.к. я отправляю первый байт, и ТХЕ уже заведомо имеет значение 1. Об этом я тоже писал, Вы видимо не прочли ветку и поспешили дать банальный совет.
--------------------
Нажми на кнопку - получишь результат, и твоя мечта осуществится
|
|
|
|
|
Apr 22 2013, 07:07
|
Местный
  
Группа: Участник
Сообщений: 226
Регистрация: 10-07-09
Пользователь №: 51 126

|
Цитата(Golikov A. @ Apr 22 2013, 07:05)  то увы... Как прочитали - так и работает... увы... Цитата(BlackOps @ Apr 22 2013, 07:26)  Вы видимо не прочли ветку и поспешили дать банальный совет. Угу... Ещё раз... разногласия/разночтения по SPI присутствуют только в F0 и F3...
|
|
|
|
|
Apr 22 2013, 10:39
|
Гуру
     
Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702

|
Цитата(BlackOps @ Apr 22 2013, 08:26)  Его я включаю перед тем как начать работать с СПИ. Вот так: Код //============================================================================= // 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); Где-то есть упоминание (для F4), что между установкой битика включения тактирования блока и работы с блоком должно пройти какое-то время. У меня так FSMC не заработал) Попробую найти это в доках... UPD: STM32F405/407xx and STM32F415/417xx device limitations 2.1.12 Delay after an RCC peripheral clock enabling Description A delay between an RCC peripheral clock enable and the effective peripheral enabling should be taken into account in order to manage the peripheral read/write to registers. This delay depends on the peripheral’s mapping: ● If the peripheral is mapped on AHB: the delay should be equal to 2 AHB cycles. ● If the peripheral is mapped on APB: the delay should be equal to 1 + (AHB/APB prescaler) cycles. Workarounds 1. Use the DSB instruction to stall the Cortex-M CPU pipeline until the instruction is completed. 2. Insert ”n” NOPs between the RCC enable bit write and the peripheral register writes (n = 2 for AHB peripherals, n = 1 + AHB/APB prescaler in case of APB peripherals).
|
|
|
|
|
Apr 22 2013, 11:06
|
Гуру
     
Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702

|
У меня хорошо работает такая инициализация: CODE void __inline init_SPI2(void) { SPI2->CR1 = (0 << SPI_CR1_SPE) | (0 << SPI_CR1_DFF) | (1 << SPI_CR1_SSM) | (1 << SPI_CR1_SSI) | (1 << SPI_CR1_MSTR) | (0 << SPI_CR1_BR);
SPI2->CR2 = (0 << SPI_CR2_RXNEIE) | (0 << SPI_CR2_TXDMAEN) | (1 << SPI_CR2_SSOE);
SPI2->CR1 = (1 << SPI_CR1_SPE) | (0 << SPI_CR1_DFF) | (1 << SPI_CR1_SSM) | (1 << SPI_CR1_SSI) | (1 << SPI_CR1_MSTR) | (0 << SPI_CR1_BR); } И такая отправка/прием Код BYTE sd_send_byte(const BYTE data) { BYTE spib; while((SPI2->SR & (1 << SPI_SR_TXE)) == 0); SPI2->DR = data; while((SPI2->SR & (1 << SPI_SR_RXNE)) == 0); spib = SPI2->DR; return spib; } Правда, битики я объявляю номером, а не маской...
Сообщение отредактировал IgorKossak - Apr 22 2013, 11:18
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
|
|
|
|
|
Apr 22 2013, 12:28
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Я свои SPI в STM32F207 инициализировал так. Тактирование, естественно, задавал раньше, вместе с остальными устройствами. И больше не трогал. CODE /* SPI1 -- связь с SFM M25PE40 8-bit, MSB first, SPEn, Fpclk2 / 4 (15 MHz), Master, CPOL=0, CPHA=0 */ SPI1->CR1 = SPI_CR1_CPHA * 0 | // Clock Phase SPI_CR1_CPOL * 0 | // Clock Polarity SPI_CR1_MSTR * 1 | // Master Selection SPI_CR1_BR_0 * 1 | // Baud Rate Control - fpclk2 / 4 = 15 MHz SPI_CR1_BR_1 * 0 | // SPI_CR1_BR_2 * 0 | // SPI_CR1_SPE * 1 | // SPI Enable SPI_CR1_LSBFIRST * 0 | // Frame Format SPI_CR1_SSI * 1 | // Internal slave select SPI_CR1_SSM * 1 | // Software slave management SPI_CR1_RXONLY * 0 | // Receive only SPI_CR1_DFF * 0 | // Data Frame Format SPI_CR1_CRCNEXT * 0 | // Transmit CRC next SPI_CR1_CRCEN * 0 | // Hardware CRC calculation enable SPI_CR1_BIDIOE * 0 | // Output enable in bidirectional mode SPI_CR1_BIDIMODE * 0; // Bidirectional data mode enable SPI1->CR2 = SPI_CR2_RXDMAEN * 0 | // Rx Buffer DMA Enable SPI_CR2_TXDMAEN * 0 | // Tx Buffer DMA Enable SPI_CR2_SSOE * 0 | // SS Output Enable SPI_CR2_FRF * 0 | // Protocol format - 0: SPI Motorola mode, 1: SPI TI mode SPI_CR2_ERRIE * 0 | // Error Interrupt Enable SPI_CR2_RXNEIE * 0 | // RX buffer Not Empty Interrupt Enable SPI_CR2_TXEIE * 0; // Tx buffer Empty Interrupt Enable // SPI1->CR1 |= SPI_CR1_MSTR | SPI_CR1_SPE; // Разрешить, Мастер /* SPI2 -- конфигурирование EP3C5 CONF_N (NSS) переключается программно */ SPI2->CR1 = SPI_CR1_CPHA * 0 | // Clock Phase SPI_CR1_CPOL * 0 | // Clock Polarity SPI_CR1_MSTR * 1 | // Master Selection SPI_CR1_BR_0 * 0 | // Baud Rate Control - fpclk1 / 2 = 15 MHz SPI_CR1_BR_1 * 0 | // SPI_CR1_BR_2 * 0 | // SPI_CR1_SPE * 1 | // SPI Enable (раньше включалось позже!) SPI_CR1_LSBFIRST * 1 | // Frame Format SPI_CR1_SSI * 1 | // Internal slave select (раньше задавалось!) SPI_CR1_SSM * 1 | // Software slave management SPI_CR1_RXONLY * 0 | // Receive only SPI_CR1_DFF * 0 | // Data Frame Format - 8 bit SPI_CR1_CRCNEXT * 0 | // Transmit CRC next SPI_CR1_CRCEN * 0 | // Hardware CRC calculation enable SPI_CR1_BIDIOE * 0 | // Output enable in bidirectional mode SPI_CR1_BIDIMODE * 0; // Bidirectional data mode enable SPI2->CR2 = SPI_CR2_RXDMAEN * 0 | // Rx Buffer DMA Enable SPI_CR2_TXDMAEN * 0 | // Tx Buffer DMA Enable SPI_CR2_SSOE * 0 | // SS Output Enable (все равно используется GPIO?) SPI_CR2_FRF * 0 | // Protocol format - 0: SPI Motorola mode, 1: SPI TI mode SPI_CR2_ERRIE * 0 | // Error Interrupt Enable SPI_CR2_RXNEIE * 0 | // RX buffer Not Empty Interrupt Enable SPI_CR2_TXEIE * 0; // Tx buffer Empty Interrupt Enable // SPI2->CR1 |= SPI_CR1_SPE;
/* SPI3 -- регистр управления аналоговыми узлами 8-bit, MSB first, SPEn, Fpclk1 / 2 (15MHz), Master, CPOL=0, CPHA=0 74HC595 SCK - Pos, AD5314 SCK - Neg (изменить CPOL) */ SPI3->CR1 = SPI_CR1_CPHA * 0 | // Clock Phase SPI_CR1_CPOL * 0 | // Clock Polarity HC595 SPI_CR1_MSTR * 1 | // Master Selection SPI_CR1_BR_0 * 0 | // Baud Rate Control - fpclk1 / 2 = 15 MHz SPI_CR1_BR_1 * 0 | // SPI_CR1_BR_2 * 0 | // SPI_CR1_SPE * 1 | // SPI Enable SPI_CR1_LSBFIRST * 0 | // Frame Format SPI_CR1_SSI * 1 | // Internal slave select SPI_CR1_SSM * 1 | // Software slave management SPI_CR1_RXONLY * 0 | // Receive only SPI_CR1_DFF * 0 | // Data Frame Format (8 bit) SPI_CR1_CRCNEXT * 0 | // Transmit CRC next SPI_CR1_CRCEN * 0 | // Hardware CRC calculation enable SPI_CR1_BIDIOE * 0 | // Output enable in bidirectional mode SPI_CR1_BIDIMODE * 0; // Bidirectional data mode enable SPI3->CR2 = SPI_CR2_RXDMAEN * 0 | // Rx Buffer DMA Enable SPI_CR2_TXDMAEN * 0 | // Tx Buffer DMA Enable SPI_CR2_SSOE * 0 | // SS Output Enable SPI_CR2_FRF * 0 | // Protocol format - 0: SPI Motorola mode, 1: SPI TI mode SPI_CR2_ERRIE * 0 | // Error Interrupt Enable SPI_CR2_RXNEIE * 0 | // RX buffer Not Empty Interrupt Enable SPI_CR2_TXEIE * 0; // Tx buffer Empty Interrupt Enable
|
|
|
|
|
Apr 22 2013, 21:04
|

Знающий
   
Группа: Свой
Сообщений: 618
Регистрация: 7-06-08
Из: USSR
Пользователь №: 38 121

|
Цитата(Golikov A. @ Apr 22 2013, 19:56)  в нем утверждается что если поставить SSM, чтобы устройство было мастером необходимо поставить и SSI, это будет двигать уровень NSS, тоже говорит и реф мануал... так это и я говорил вот в этом посте, ссылаясь на даташит: http://electronix.ru/forum/index.php?showt...t&p=1156434Цитата(Golikov A. @ Apr 22 2013, 20:28)  не понятно почему пауза перед записью в регистр помогала решить проблему... может все таки что-то схемное... да нет там ничего сложного в схеме, цепляю выводи к осциллографу и все. А плата стандартная дискавери. Golikov A. за линк спасибо, пройдусь по нему тоже. Genadi Zawidowski: использование только SSM без SSI проблему тоже не решало.
--------------------
Нажми на кнопку - получишь результат, и твоя мечта осуществится
|
|
|
|
|
Apr 23 2013, 04:26
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
Цитата(ViKo @ Apr 23 2013, 08:11)  Я так и не увидел ответа, что SPI не работал из-за того, что тактовая частота на модуль SPI подавалась непосредственно перед его использованием. потому что это не так. перед отправкой байта пробовали втыкать посылку по уарт явно больше 2 тактов шины после отправки ставили while(1) на случай если бит TXE ставиться с задержкой. пробовали ждать ТХЕ до отправки он в 1 и ситуация таже. нужна достаточно долгая пауза перед стартом, непонятно почему. Я ставлю на то что либо какие то клоки стабилизируются (не понятно почему тогда УАРТ работает), или что-то заряжается... вообщем ситуация странная о чем мы все и говорим...
|
|
|
|
|
Apr 23 2013, 07:41
|

Знающий
   
Группа: Свой
Сообщений: 618
Регистрация: 7-06-08
Из: USSR
Пользователь №: 38 121

|
Цитата(Golikov A. @ Apr 23 2013, 08:26)  нужна достаточно долгая пауза перед стартом, непонятно почему. Я ставлю на то что либо какие то клоки стабилизируются (не понятно почему тогда УАРТ работает), в этом посте: http://electronix.ru/forum/index.php?showt...t&p=1156458я как раз таки хотел сказать в пункте 1), что отправка байта с УАРТ тоже не сработала! пришлось поставить непрерывный цикл, и ждать команды от того же уарта (приема от него байта команды) который прерывает цикл, а дальше код исполняет ту процедуру с отправкой байта в СПИ. Цитата(Genadi Zawidowski @ Apr 23 2013, 10:16)  Если вход NSS перед началом передачи где-то около "0", то и не передаст. Если успел зарядиться - то прокатывает. Я "ставлю" на это. Я не думаю что это так, потомучто я сделал такой тест: Подключил к осциллографу не только SCK/MOSI, но еще и NSS. И включил передачю байта разумеется в режиме в котором у меня работает нормально, т.е. байт я вижу на осциллографе.. а вот НСС всегда нулевой! Даже не дернулся во время передачи! (хотя байт сам передался как надо я ето вижу на дисплее осциллографа) хотя это странно у меня же и SSM и SSI поставлены как 1...
--------------------
Нажми на кнопку - получишь результат, и твоя мечта осуществится
|
|
|
|
|
Apr 23 2013, 09:37
|
Местный
  
Группа: Участник
Сообщений: 226
Регистрация: 10-07-09
Пользователь №: 51 126

|
Детский сад... гадание пальцем на манной каше... Да не так это всё делается... по хорошему... Выкладывается проект со всеми настройками, по самому минимуму и без всяких излишеств... типа УАРТ и прочей хрени... когда ещё глюк "имеет место быть"...
|
|
|
|
|
Apr 23 2013, 10:11
|
Частый гость
 
Группа: Свой
Сообщений: 116
Регистрация: 2-03-07
Из: Украина
Пользователь №: 25 826

|
Цитата(ViKo @ Apr 23 2013, 12:41)  Имею Дискавери F4, Кейл. Могу проверить. И осциллограф - Agilent.  Вобщем, щас загрузил кусочек ТС к себе на плату (скопировал и вставил с первого поста) с STM405, все работает Не выложена инициализация портов. Так что, гдето в другом месте лажа. Прошу прощения не первый, а с настройкой SPI
|
|
|
|
|
Apr 23 2013, 19:46
|

Знающий
   
Группа: Свой
Сообщений: 618
Регистрация: 7-06-08
Из: USSR
Пользователь №: 38 121

|
Короче,чтобы начать плностью с нуля, пошел взял новую плату Дискавери, девственную, вскрыл упаковку подключил только ноги PB13,PB14 к осциллографу. Переписал новый проект, выкинул все, оставил только SPI2 работающий на: PB12 - NSS PB13 - SCK PB14 - MISO (не использую в тесте) PB15 - MOSI Проект прикреплен к сообщению. Загружаю простой код.. и работает сразу... Не нужно теперь очень долгую задержку ставить. Новый тестовый проект скопирован из старого, только часть SPI2 и все. Значит в старом проекте проблема усугублялась тем чтоподключены и другие устройства к порту были (PWM - просто вывод напины,I2C1 - подключены 2 сенсора) Я не думаю хотя что в старой плате дискавери был дефект, т.к. тогда не рабтало бы вообще. Сорее всего проблемабыла с включением нескольких периферий на одном порту сразу, другого ничего не может быть. Вот что я отработал в новом проекте: 1) SSM=0,SSI=0 Включил, естессвтенно не сработало 2) SSM=0,SSI=0, Подтянул 1 к выводу NSS (PB12) как посоветовали. Сработало, сразу после включения вижу байт на осциллографе 3) SSM=1,SSI=1, ничего не подтянуто к NSS Сработало тоже, сразу после включения вижу байт на осциллографе Прикрепленный проект содержит конфигурацию №3 Теперь у меня вопрос по конфигурации №3: Почему после и во время того как я увидел свой байт на осциллографе NSS (PB12) ни разу не поднялся на уровень "1"? Ведь у меня же стоит SSM=1,SSI=1... Почему NSS не равен "1" на ножке PB12? Проверяю тестером и осциллографом, он всегда 0 Пробовал включать SSOE в регистре СR2 всеравно пин NSS всегда 0Да, я вижу вы говорили про настройки ног, вот как настроены они был для порта B в старом проекте: (К данному прикрепленному тестовому проекту отношения не имеет!!, NSS и MISO были закомментированы позже)CODE //============================================================================= // GPIOB configuration //=============================================================================
// enable GPIOB clock RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
// Alternate Function GPIOB->MODER = 0; // clear moder register GPIOB->MODER |= ( //GPIO_MODER_MODER12_1 | // Alternate Function, SPI2 NSS GPIO_MODER_MODER13_1 | // Alternate Function, SPI2 SCK //GPIO_MODER_MODER14_1 | // Alternate Function, SPI2 MISO GPIO_MODER_MODER15_1 | // Alternate Function, SPI2 MOSI
GPIO_MODER_MODER9_1 | // Alternate Function, I2C1, SDA GPIO_MODER_MODER8_1 | // Alternate Function, I2C1, SCL
GPIO_MODER_MODER4_1 | // AF, PWM_OUT1, TIM3_CH1 GPIO_MODER_MODER5_1 | // AF, PWM_OUT2, TIM3_CH2 GPIO_MODER_MODER0_1 | // AF, PWM_OUT3, TIM3_CH3 GPIO_MODER_MODER1_1 | // AF, PWM_OUT4, TIM3_CH4 GPIO_MODER_MODER6_1 | // AF, PWM_IN5, TIM4_CH1 GPIO_MODER_MODER7_1 // AF, PWM_IN6, TIM4_CH2 );
// Output type GPIOB->OTYPER = 0; // clear otype register GPIOB->OTYPER |= // push-pull if 0 ( GPIO_OTYPER_OT_8 | // Open-Drain, I2C1, SCL GPIO_OTYPER_OT_9 // OPen-Drain, I2C1, SDA );
// Speed type GPIOB->OSPEEDR = 0; // clear ospeedr register GPIOB->OSPEEDR |= ( //GPIO_OSPEEDER_OSPEEDR12_1 | // SPI2 NSS 50MH GPIO_OSPEEDER_OSPEEDR13_1 | // SPI2 SCK, 50MHz //GPIO_OSPEEDER_OSPEEDR14_1 | // SPI2 MISO 50MH GPIO_OSPEEDER_OSPEEDR15_1 | // SPI2 MOSI 50MH
GPIO_OSPEEDER_OSPEEDR4_1 | // PWM_OUT1, TIM3_CH1, 50MHz GPIO_OSPEEDER_OSPEEDR5_1 | // PWM_OUT2, TIM3_CH2, 50MHz GPIO_OSPEEDER_OSPEEDR0_1 | // PWM_OUT3, TIM3_CH3, 50MHz GPIO_OSPEEDER_OSPEEDR1_1 | // PWM_OUT4, TIM3_CH4, 50MHz GPIO_OSPEEDER_OSPEEDR6_1 | // PWM_IN5, TIM4_CH1, 50MHz GPIO_OSPEEDER_OSPEEDR7_1 // PWM_IN6, TIM4_CH2, 50MHz );
// Push/Pull GPIOB->PUPDR = 0; // clear pupdr register GPIOB->PUPDR |= ( GPIO_PUPDR_PUPDR8_0 | // Pull-Up, I2C1, SCL GPIO_PUPDR_PUPDR9_0 | // Pull-Up, I2C1, SDA GPIO_PUPDR_PUPDR4_0 | // Pull-Up, PWM_OUT1, TIM3_CH1 GPIO_PUPDR_PUPDR5_0 | // Pull-Up, PWM_OUT2, TIM3_CH2 GPIO_PUPDR_PUPDR0_0 | // Pull-Up, PWM_OUT3, TIM3_CH3 GPIO_PUPDR_PUPDR1_0 | // Pull-Up, PWM_OUT4, TIM3_CH4 GPIO_PUPDR_PUPDR6_0 | // Pull-Up, PWM_IN5, TIM4_CH1 GPIO_PUPDR_PUPDR7_0 // Pull-Up, PWM_IN6, TIM4_CH2 );
// Alternate Function pins GPIOB->AFR[1] = 0; // clear AFR_H register GPIOB->AFR[1] |= ( (4 << ((8 - 8) << 2)) | // I2C1 SCL, AF4 (4 << ((9 - 8) << 2)) | // I2C1 SDA, AF4
//(5 << ((12 - 8) << 2)) | // SPI2 NSS, AF5 (5 << ((13 - 8) << 2)) | // SPI2 SCK, AF5 //(5 << ((14 - 8) << 2)) | // SPI2 MISO, AF5 (5 << ((15 - 8) << 2)) // SPI2 MOSI, AF5
);
GPIOB->AFR[0] = 0; // clear AFR_L register GPIOB->AFR[0] |= ( (2 << ((4 - 0) << 2)) | // PWM_OUT1, TIM3_CH1, AF2 (2 << ((5 - 0) << 2)) | // PWM_OUT2, TIM3_CH2, AF2 (2 << ((0 - 0) << 2)) | // PWM_OUT3, TIM3_CH3, AF2 (2 << ((1 - 0) << 2)) | // PWM_OUT4, TIM3_CH4, AF2 (2 << ((6 - 0) << 2)) | // TIM4_CH1, AF2 (2 << ((7 - 0) << 2)) // TIM4_CH2, AF2 );
--------------------
Нажми на кнопку - получишь результат, и твоя мечта осуществится
|
|
|
|
|
Apr 24 2013, 03:41
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
а где варианта SSM =1, SSI = 0? вроде как инструкция об этом говорит. SSM = 1, SSI - задает состояние NSS, или нет? еще вот такая приписка Когда NSS разрешено работать в качестве выхода (SSM = 0, SSOE = 1), эта конфигурация используется только в режиме Master. Когда ведущее устройство начинает соединение, NSS переводится в состояние низкого уровня, и поддерживается в этом состоянии до момента деактивации модуля SPI. и остается теперь потихоньку добавлять периферию прошлого проекта и смотреть какой модуль убъет СПИ
|
|
|
|
|
Apr 24 2013, 04:13
|

Знающий
   
Группа: Свой
Сообщений: 618
Регистрация: 7-06-08
Из: USSR
Пользователь №: 38 121

|
Цитата(Golikov A. @ Apr 24 2013, 08:41)  Когда NSS разрешено работать в качестве выхода (SSM = 0, SSOE = 1), эта конфигурация используется только в режиме Master. Когда ведущее устройство начинает соединение, NSS переводится в состояние низкого уровня, и поддерживается в этом состоянии до момента деактивации модуля SPI. Попробовал этот вариант тоже. Тогда байт не передается, мне нужно вручную проводом подтянуть NSS к "1" чтобы заработало (ну и тогда естесственно NSS никогда на ноль естесственно не подтягивается стоит как 1 всегда, даже когда выключаю модуль) Цитата(Golikov A. @ Apr 24 2013, 08:41)  а где варианта SSM =1, SSI = 0? Тогда вообще не работает. Простенькй проект прикрепил (работающий: SSM=1,SSI=1,SSOE=0) если хотите можете проверить.
--------------------
Нажми на кнопку - получишь результат, и твоя мечта осуществится
|
|
|
|
|
Apr 24 2013, 05:05
|

Знающий
   
Группа: Свой
Сообщений: 618
Регистрация: 7-06-08
Из: USSR
Пользователь №: 38 121

|
Я не пойму немного, разве целью установки SSOE=1 не является автоматическое управление пином NSS? т.е.сделать так, чтобы этот пин сам подтягивался на 0 во время транзакции и возвращался на 1 когда транзакция закончена? как можно достичь такoго поведения? И еще, вы говорите SSOE=1 и управляй пином NSS через GPIO.. но ведь пин PB12 (NSS) настроен как Alternate Function... ? (тестовыйпроект выложен в этом посте если что: http://electronix.ru/forum/index.php?showt...&p=1157091)
--------------------
Нажми на кнопку - получишь результат, и твоя мечта осуществится
|
|
|
|
|
Apr 24 2013, 07:45
|

Знающий
   
Группа: Свой
Сообщений: 618
Регистрация: 7-06-08
Из: USSR
Пользователь №: 38 121

|
Цитата(adnega @ Apr 24 2013, 11:22)  Никто не мешает изменить его на OUT_PP. Вообще разные бывают случаи и управлять NSS "автоматом" можно только в простейших из них. Например, при инициализации SD карт по SPI вначале нужно передать 0xFF 74 раза при NSS=1. Ну вобщем сейчас я поменял NSS на General Purpose Pin, и захотел чтобы этот пин был 0 во время транзакции и 1 когда нет транзакции. решил установить его в начале 1, затем перед транзакцией на 0, потом проверить биты TXE и BSY а затем опять выставить в 1. Проблема была в том, что TXE и BSY видимо выставляются почти сразу после того как сдвиговый регистр загружен, и если после этого выставлять пин на 1 то получается слишком рано, чуть ли не у начала реальной транзакции ( а не в конце). поетому поставил небольшой цикл for, чтобы отрегулировать задержку. короче, сейчас работает вобщемто так как я хочу, но ставить задержку на GPIO SS пин чтобы подогнать его так чтобы он был 0 только во время транзакции это просто уродство какоето, неужели просто нету более красивого или эффективного решения? для справки, мне надо чтобы этот SS (NSS) пин вел себя как сигнал LE вот на этой диаграмме: http://i.imgur.com/EV9flrf.jpgвот еще такое решение, проверка RXNE, чтение DR затем проверка BSY, затем уже поднять вручную пин на 1 CODE GPIOB->ODR |= GPIO_ODR_ODR_12;
//////////////// SPI2 Communication Routine /////////////////////////////////// while ( ( (SPI2 -> SR) & SPI_SR_TXE ) == RESET) { // wait until TXE bit is 1 } GPIOB->ODR &= !GPIO_ODR_ODR_12;
SPI2 -> DR = d0;
while ( //( ( (SPI2 -> SR) & SPI_SR_TXE ) == RESET) && (( (SPI2 -> SR) & SPI_SR_RXNE ) == RESET) ) {
}
dd = SPI2->DR;
while ( //( ( (SPI2 -> SR) & SPI_SR_TXE ) == RESET) && (( (SPI2 -> SR) & SPI_SR_BSY ) == SET) ) {
}
GPIOB->ODR |= GPIO_ODR_ODR_12; так более красиво как то (не нужно циклы вставлять..)
Сообщение отредактировал IgorKossak - Apr 24 2013, 08:44
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
--------------------
Нажми на кнопку - получишь результат, и твоя мечта осуществится
|
|
|
|
|
Apr 24 2013, 11:44
|
Местный
  
Группа: Участник
Сообщений: 226
Регистрация: 10-07-09
Пользователь №: 51 126

|
Всё это, конечно... очень интересно... "А был ли мальчик?"(С) А глюк то... где??? Неужто самоликвидировался???
|
|
|
|
|
Apr 24 2013, 13:52
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
Цитата(HHIMERA @ Apr 24 2013, 15:44)  Всё это, конечно... очень интересно... "А был ли мальчик?"(С) А глюк то... где??? Неужто самоликвидировался??? если коротко ТС взял другую плату дискавери, и залил туда проект с одним лишь СПИ, без прочей периферии, и глюк пропал. Предложение по одному добавлять остальную периферию и найти какой модуль рушит СПИ одобрения не встретило. Потому до конца не ясно что же является причиной плата или остальная периферия.
|
|
|
|
|
May 2 2013, 03:51
|

Знающий
   
Группа: Свой
Сообщений: 618
Регистрация: 7-06-08
Из: USSR
Пользователь №: 38 121

|
Пишу с опозданием надобыло кое какие проекты сдавать и платы делать. Во первых я не заявлял что нашел глюк, тема четко говорит "проблемы с СПИ", а проблемы могут быть по разым причинам, в том числе и по причине моей ошибки. Сделал вот что: 1) После того как убедился что на новой голой плате проект СПИ заработал, я переписал старый проект по новому, и прогнал его тоже на новой плате - Заработало. 2) Старую платуполностью отсоеденил от всего что было соеденено, прогнал тот же епределанный проект - Заработало. 3) Начал присоеденять по очереди остальную перферию - Заработало с присоединенной всей периферией (Uart,PWM,I2C) 4) После того как СПИ проект с подсоединенной но не активизированной программно периферией заработал, я ее начал по очереди активизировать, в итоге проект был доведен до "оригиального" состояния, и тоже заработал под "заработал" я имею ввиду что сразу при включении не надо долго ждать и я вижу свои байты на осциллографе. Единственное что я заметил в результате всего этого это задержка SCK на примерно 1500нс когда все нижеприведенные функции не заккоментированны. Когда закомментированны две последние функции включения i2c и usart3 то задержка подтянутого SCK не более 400нс Когда закомментирован только usart3 то задержка SCk перед его переключением и посылкой байта 900нс Когда все нижеприведенные функции включены (не закомментированны) то задержка SCK перед его переключением и посылкой байта 1500нс При этом: Если включить всеэти функции (не комментировать их) и включить цикл задержки длинной после включения платы, а потом подать через тот же Usart3 команду на посылку байта по SPI, то байт отсылается сразу и SCK не задерживается (сразу начинает пиерелючатся) Вот моя последовательность включения программно периферии: Код config_gpio_all(); // configure all GPIOs config_pwm_io(); // configure Input and Output PWM channels config_spi_all(); // config all peripherals using SPI config_i2c_all(); // config all peripherals using I2C config_usart3(); // configure USART3 А вот код каждой функции: CODE uint32_t config_gpio_all(void) { //============================================================================= // GPIOB configuration //=============================================================================
// enable GPIOB clock RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
// Alternate Function GPIOB->MODER = 0; // clear moder register GPIOB->MODER |= ( GPIO_MODER_MODER12_1 | // Alternate Function, SPI2 NSS GPIO_MODER_MODER13_1 | // Alternate Function, SPI2 SCK GPIO_MODER_MODER14_1 | // Alternate Function, SPI2 MISO GPIO_MODER_MODER15_1 | // Alternate Function, SPI2 MOSI
GPIO_MODER_MODER9_1 | // Alternate Function, I2C1, SDA GPIO_MODER_MODER8_1 | // Alternate Function, I2C1, SCL
GPIO_MODER_MODER4_1 | // AF, PWM_OUT1, TIM3_CH1 GPIO_MODER_MODER5_1 | // AF, PWM_OUT2, TIM3_CH2 GPIO_MODER_MODER0_1 | // AF, PWM_OUT3, TIM3_CH3 GPIO_MODER_MODER1_1 | // AF, PWM_OUT4, TIM3_CH4 GPIO_MODER_MODER6_1 | // AF, PWM_IN5, TIM4_CH1 GPIO_MODER_MODER7_1 // AF, PWM_IN6, TIM4_CH2 );
// Output type GPIOB->OTYPER = 0; // clear otype register GPIOB->OTYPER |= // push-pull if 0 ( GPIO_OTYPER_OT_8 | // Open-Drain, I2C1, SCL GPIO_OTYPER_OT_9 // OPen-Drain, I2C1, SDA );
// Speed type GPIOB->OSPEEDR = 0; // clear ospeedr register GPIOB->OSPEEDR |= ( GPIO_OSPEEDER_OSPEEDR12_1 | // SPI2 NSS 50MH GPIO_OSPEEDER_OSPEEDR13_1 | // SPI2 SCK, 50MHz GPIO_OSPEEDER_OSPEEDR14_1 | // SPI2 MISO 50MH GPIO_OSPEEDER_OSPEEDR15_1 | // SPI2 MOSI 50MH
GPIO_OSPEEDER_OSPEEDR4_1 | // PWM_OUT1, TIM3_CH1, 50MHz GPIO_OSPEEDER_OSPEEDR5_1 | // PWM_OUT2, TIM3_CH2, 50MHz GPIO_OSPEEDER_OSPEEDR0_1 | // PWM_OUT3, TIM3_CH3, 50MHz GPIO_OSPEEDER_OSPEEDR1_1 | // PWM_OUT4, TIM3_CH4, 50MHz GPIO_OSPEEDER_OSPEEDR6_1 | // PWM_IN5, TIM4_CH1, 50MHz GPIO_OSPEEDER_OSPEEDR7_1 // PWM_IN6, TIM4_CH2, 50MHz );
// Push/Pull GPIOB->PUPDR = 0; // clear pupdr register GPIOB->PUPDR |= ( GPIO_PUPDR_PUPDR8_0 | // Pull-Up, I2C1, SCL GPIO_PUPDR_PUPDR9_0 | // Pull-Up, I2C1, SDA GPIO_PUPDR_PUPDR4_0 | // Pull-Up, PWM_OUT1, TIM3_CH1 GPIO_PUPDR_PUPDR5_0 | // Pull-Up, PWM_OUT2, TIM3_CH2 GPIO_PUPDR_PUPDR0_0 | // Pull-Up, PWM_OUT3, TIM3_CH3 GPIO_PUPDR_PUPDR1_0 | // Pull-Up, PWM_OUT4, TIM3_CH4 GPIO_PUPDR_PUPDR6_0 | // Pull-Up, PWM_IN5, TIM4_CH1 GPIO_PUPDR_PUPDR7_0 // Pull-Up, PWM_IN6, TIM4_CH2 );
// Alternate Function pins GPIOB->AFR[1] = 0; // clear AFR_H register GPIOB->AFR[1] |= ( (4 << ((8 - 8) << 2)) | // I2C1 SCL, AF4 (4 << ((9 - 8) << 2)) | // I2C1 SDA, AF4
(5 << ((12 - 8) << 2)) | // SPI2 NSS, AF5 (5 << ((13 - 8) << 2)) | // SPI2 SCK, AF5 (5 << ((14 - 8) << 2)) | // SPI2 MISO, AF5 (5 << ((15 - 8) << 2)) // SPI2 MOSI, AF5
);
GPIOB->AFR[0] = 0; // clear AFR_L register GPIOB->AFR[0] |= ( (2 << ((4 - 0) << 2)) | // PWM_OUT1, TIM3_CH1, AF2 (2 << ((5 - 0) << 2)) | // PWM_OUT2, TIM3_CH2, AF2 (2 << ((0 - 0) << 2)) | // PWM_OUT3, TIM3_CH3, AF2 (2 << ((1 - 0) << 2)) | // PWM_OUT4, TIM3_CH4, AF2 (2 << ((6 - 0) << 2)) | // TIM4_CH1, AF2 (2 << ((7 - 0) << 2)) // TIM4_CH2, AF2 );
//============================================================================= // GPIOD configuration //============================================================================= // enable GPIOD clock ((RCC_TypeDef *)(RCC_BASE))->AHB1ENR |= RCC_AHB1ENR_GPIODEN;
// Alternate Function ((GPIO_TypeDef *)(GPIOD_BASE))->MODER |= (GPIO_MODER_MODER9_1 | // Alternate Function, USART3_RX GPIO_MODER_MODER8_1 ); // Alternate Function, USART3_TX
// Output type ((GPIO_TypeDef *)(GPIOD_BASE))->OTYPER |= 0;// push-pull if 0 //(GPIO_OTYPER_OT_8 | // Open-Drain, I2C1, SCL //GPIO_OTYPER_OT_9); // OPen-Drain, I2C1, SDA
// Speed type ((GPIO_TypeDef *)(GPIOD))->OSPEEDR |= (GPIO_OSPEEDER_OSPEEDR8_1 | // USART3 TX 50 MHz GPIO_OSPEEDER_OSPEEDR9_1); // USART3 RX 50 MHz
// Push/Pull for USART3 ((GPIO_TypeDef *)(GPIOD_BASE))->PUPDR |= ( GPIO_PUPDR_PUPDR8_0 | // Pull-Up, USART3 TX GPIO_PUPDR_PUPDR9_0 // Pull-Up, USART3 RX );
((GPIO_TypeDef *)(GPIOD_BASE))->AFR[1] |= ( (7 << ((8 - 8) << 2)) | // USART3 TX, AF7 (7 << ((9 - 8) << 2)) ); // USART3 RX, AF7
return 0; }
CODE uint32_t config_pwm_io(void) { //============================================================================= // set up PWM Output on TIM3 channels //=============================================================================
// enable TIM3 clock RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
// set the prescaler for 2MHz clock count // fpclk = 42MHz, TIM3_clk = 2*fpclk = 84MHz // CK_CNT = TIM3_clk / (PSC + 1) // PSC = TIM3_clk / CK_CNT - 1 TIM3->PSC = 41; // 84MHz/2MHz - 1 = 41
// set the Auto Reload Register // Needed period = (1/CK_CNT) * ARR TIM3->ARR = 30000; // PWM_period = 15ms / (1/2MHz)
// clear CR2 TIM3->CR2 = 0;
TIM3->CCR1 = 3000; // 10% duty cycle, for CH1 TIM3->CCR2 = 3000; // 10% duty cycle, for CH2 TIM3->CCR3 = 3000; // 10% duty cycle, for CH3 TIM3->CCR4 = 3000; // 10% duty cycle, for CH4
// set output compare mode 1. TIM3->CCMR1 |= TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | // CH1 TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_1; // CH2
TIM3->CCMR2 |= TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1 | // CH3 TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4M_1; // CH4
// enable Output compare TIM3->CCER |= TIM_CCER_CC1E; //CH1 TIM3->CCER |= TIM_CCER_CC2E; //CH2 TIM3->CCER |= TIM_CCER_CC3E; //CH3 TIM3->CCER |= TIM_CCER_CC4E; //CH4
// enable TIM3 TIM3->CR1 |= TIM_CR1_CEN;
return 0; }
CODE uint32_t config_spi_all(void) {
//============================================================================= // SPI1 Related configuration //============================================================================= // enable SPI2 clock RCC->APB1ENR |= RCC_APB1ENR_SPI2EN;
// configure SPI2 SPI2 -> CR1 |= (SPI_CR1_SPE | SPI_CR1_CPOL | SPI_CR1_CPHA | SPI_CR1_MSTR | SPI_CR1_BR_1 | SPI_CR1_SSM | SPI_CR1_SSI);
//SPI2->CR2 |= (SPI_CR2_SSOE);
return 0; }
CODE uint32_t config_i2c_all(void) {
//============================================================================= // I2C1 Related configuration //============================================================================= // enable I2C1 clock ((RCC_TypeDef *) (RCC_BASE))->APB1ENR |= RCC_APB1ENR_I2C1EN;
// 1) configure I2C_CR2 I2C1 -> CR2 |= (I2C_CR2_FREQ_5 | I2C_CR2_FREQ_3 | I2C_CR2_FREQ_1); // APB1 clock is 42MHz
// 2) Configure Clock Control Register, I2C_CCR // For 100KHz, APB1clk=42MHz, T_high = T_low = (1/42MHz)*210 = 5us // For Fast mode, T_high = 9*(1/42MHz)*CCR = 0.8us, // T_low = 16*(1/42MHz)*CCR = 1.5us, // CCR = 4, F/S = 1, DUTY = 1, I2C_CCR = 0xc004 I2C1 -> CCR = 0xc004; // 0xd2, d210 for 100KHz,
// 3) Configure I2C_TRISE, Rise Time register I2C1 -> TRISE = 0x2b; // 0x2b, d42 (42 + 1)
// 4) enable I2C1 peripheral I2C1 -> CR1 |= (I2C_CR1_PE);
return 0; }
CODE uint32_t config_usart3(void) {
//============================================================================= // USART3 Related configuration //============================================================================= // enable I2C1 clock RCC->APB1ENR |= RCC_APB1ENR_USART3EN;
// 1) Setting UE, amd M bits USART3-> CR1 |= 0x2000; // UE = 1
// 2) Programming number of stop bits if needed
// 3) Enable DMA if needed
// 4) set the Baud Rate // BAUD = fck / ( 8 * (2 - OVER8) * USARTDIV ) // fck = 42MHz, // OVER8 = 0 // Choose BAUD = 115200 // then: USARTDIV = fck / ( 8 * (2 -OVER8) * BAUD = 22.75 // BRR = (22 << 4) | ( 0.75 * 16) = 364, // or: BRR = fck / BAUD = 42MHz / 115200 = 364 USART3->BRR = 364;
// enable transmitter USART3->CR1 |= USART_CR1_TE;
// enable receiver USART3->CR1 |= USART_CR1_RE;
return 0; }
Короче вывод такой что если сразу после включения всей периферии в приведенном коде посылать байт по SPI то буден задержкав 1500нс, но байт по любому отсылается. p.s. задача поднятия пина SS после передачи байта тоже решена программным путем. Никакие эксперименты с битами SSOE SSI SSM ни следование мануалу не привело к тому чтобыstm32 сам поднимал пин SS вверх после успешной отправки байта. (как я уже написал...после отправки читаю прием а потом уже BSY и вручную поднимаю его сам) (почти тоже самое что в теме приведенной Viko) а так вобщем работает все.
--------------------
Нажми на кнопку - получишь результат, и твоя мечта осуществится
|
|
|
|
|
  |
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|