controller_m30 1 30 мая, 2020 Опубликовано 30 мая, 2020 · Жалоба Ещё варианты: 1. Добавить в конец программы какую-то команду, как в рабочем примере (в той программе после CS_HIGH есть ещё пара строк работы со светодиодом). Например, после CS_HIGH добавить ещё 2-3 команды записи байта - пусть их будет не 6 а 9. Посмотреть что будет с задержкой после 6-й команды. 2. В рабочем примере, в конце текста есть ещё команда Return 0 и кавычка - а есть ли они в переработанном варианте? Может это они влияют на завершение программы с такой задержкой. 3. Переключить в режим 3-pin SPI mode. Всё равно аппаратная нога SS не нужна в данном случае, но может здесь что-то изменится. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Obam 38 30 мая, 2020 Опубликовано 30 мая, 2020 (изменено) · Жалоба Однако, дизассемблер ничего лишнего не указывает. Ну вы б хоть опубликовали дизассм всех вариантов, а то "чёрной магией" про совершенно внятный контроллер повеяло. Изменено 30 мая, 2020 пользователем Obam Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Herz 6 2 июня, 2020 Опубликовано 2 июня, 2020 · Жалоба Да, конечно. Вот я, для наглядности, оформил процедуру инициализации карточки в отдельную функцию: unsigned char Init_SD (void) { volatile unsigned char data; volatile unsigned char i; // initialize SD-card in SPI-mode and reset CS_HIGH; for (i=0; i<10; i++) // for more than 74 cycles { UCB0TXBUF = 0xFF; // send clock pulses at CS high state while (!(UCB0IFG & UCTXIFG)); } for(i=3; i>0; i--); // Delay // SD soft reset sequence (CMD0) data = UCB0RXBUF; // clear RX flag CS_LOW; UCB0TXBUF = 0x40; while (!(UCB0IFG & UCRXIFG)); data = UCB0RXBUF; // clear RX flag UCB0TXBUF = 0; while (!(UCB0IFG & UCRXIFG)); data = UCB0RXBUF; // clear RX flag UCB0TXBUF = 0; while (!(UCB0IFG & UCRXIFG)); data = UCB0RXBUF; // clear RX flag UCB0TXBUF = 0; while (!(UCB0IFG & UCRXIFG)); data = UCB0RXBUF; // clear RX flag UCB0TXBUF = 0; while (!(UCB0IFG & UCRXIFG)); data = UCB0RXBUF; // clear RX flag UCB0TXBUF = 0x95; while (!(UCB0IFG & UCRXIFG)); // USCI_B0 RX buffer ready? UCB0TXBUF = 0xFF; data = UCB0RXBUF; while (!(UCB0IFG & UCRXIFG)); data = UCB0RXBUF; UCB0TXBUF = 0xFF; while (!(UCB0IFG & UCRXIFG)); data = UCB0RXBUF; CS_HIGH; return data; } Здесь переменная-счётчик i используется сначала для отсчёта 10-ти байтов 0xFF, посылаемых при высоком уровне CS, а затем для формирования задержки между этой стадией и следующей, где посылается команда сброса (CMD0) и принимается ответ от карточки. Вызываю её, как и прежде, после настройки модуля eUSCI_B : int main(void) { volatile unsigned int data1, data2; WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer // Disable the GPIO power-on default high-impedance mode // to activate previously configured port settings PM5CTL0 &= ~LOCKLPM5; // eUSCI_B0 Initializing UCB0CTL1 |= UCSWRST; // Enable SW reset P1DIR |= BIT0; // Set P1.0 to output direction P1SEL0 |= BIT0 + BIT1 + BIT2 + BIT3; // P1.0 - P1.3 USCI_B0 option select P3DIR |= BIT0; // P3.0 output direction (CS) UCB0CTLW0 |= UCMSB + UCMST + UCSYNC; // 8-bit SPI mstr, MSB 1st, sync UCB0CTLW0 |= UCMODE1 + UCSSEL1 + UCSTEM; // 4-pin mode, STE low, SMCLK UCB0BRW = 4; // division, clock eq. to BRCLK/4 UCB0STATW = 0; // clear errors UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation data1 = 0xAA; data2 = Init_SD(); И, как видно по осциллограмме ниже, всё выполняется корректно. Здесь красный луч - MOSI, зелёный - MISO, синий - SCLK, жёлтый - CS. Но стоит мне переменную-счётчик i объявить обычной, не volatile, как начинаются чудеса. На следующей осциллограмме видно, что а) пауза между стадиями сократилась, б) пауз между передачей байтов во второй стадии нет совсем, то есть проверка на заполнение приёмного буфера как будто не выполняется, в) сигнал CS возвращается в высокое состояние ещё до того, как закончилась передача, то есть, опять же, не взирая на флаг UCRXIFG. Вот листинги дизассемблера обоих вариантов функции. volatile unsigned char i: Init_SD(): 008000: 8321 DECD.W SP 83 CS_HIGH; 008002: D3D2 0222 BIS.B #1,&PB_PBOUT 84 for (i=0; i<10; i++) // for more than 74 cycles 008006: 43C1 0001 CLR.B 0x0001(SP) 00800a: 90F1 000A 0001 CMP.B #0x000a,0x0001(SP) 008010: 2C0C JHS ($C$L3) 86 UCB0TXBUF = 0xFF; // send clock pulses at CS high state $C$L1: 008012: 40B2 00FF 054E MOV.W #0x00ff,&eUSCI_B0_UCB0TXBUF 87 while (!(UCB0IFG & UCTXIFG)); $C$L2: 008018: B3A2 056C BIT.W #2,&eUSCI_B0_UCB0IFG 00801c: 27FD JEQ ($C$L2) 84 for (i=0; i<10; i++) // for more than 74 cycles 00801e: 53D1 0001 INC.B 0x0001(SP) 008022: 90F1 000A 0001 CMP.B #0x000a,0x0001(SP) 008028: 2BF4 JLO ($C$L1) 90 for(i=3; i>0; i--); // Delay $C$L3: 00802a: 40F1 0003 0001 MOV.B #0x0003,0x0001(SP) 008030: 93C1 0001 TST.B 0x0001(SP) 008034: 2405 JEQ ($C$L5) $C$L4: 008036: 83D1 0001 DEC.B 0x0001(SP) 00803a: 93C1 0001 TST.B 0x0001(SP) 00803e: 23FB JNE ($C$L4) 93 data = UCB0RXBUF; // clear RX flag $C$L5: 008040: 421F 054C MOV.W &eUSCI_B0_UCB0RXBUF,R15 008044: 4FC1 0000 MOV.B R15,0x0000(SP) 94 CS_LOW; 008048: C3D2 0222 BIC.B #1,&PB_PBOUT 95 UCB0TXBUF = 0x40; 00804c: 40B2 0040 054E MOV.W #0x0040,&eUSCI_B0_UCB0TXBUF 96 while (!(UCB0IFG & UCRXIFG)); $C$L6: 008052: B392 056C BIT.W #1,&eUSCI_B0_UCB0IFG 008056: 27FD JEQ ($C$L6) 97 data = UCB0RXBUF; // clear RX flag 008058: 421F 054C MOV.W &eUSCI_B0_UCB0RXBUF,R15 00805c: 4FC1 0000 MOV.B R15,0x0000(SP) 98 UCB0TXBUF = 0; 008060: 4382 054E CLR.W &eUSCI_B0_UCB0TXBUF 99 while (!(UCB0IFG & UCRXIFG)); $C$L7: 008064: B392 056C BIT.W #1,&eUSCI_B0_UCB0IFG 008068: 27FD JEQ ($C$L7) 100 data = UCB0RXBUF; // clear RX flag 00806a: 421F 054C MOV.W &eUSCI_B0_UCB0RXBUF,R15 00806e: 4FC1 0000 MOV.B R15,0x0000(SP) 101 UCB0TXBUF = 0; 008072: 4382 054E CLR.W &eUSCI_B0_UCB0TXBUF 102 while (!(UCB0IFG & UCRXIFG)); $C$L8: 008076: B392 056C BIT.W #1,&eUSCI_B0_UCB0IFG 00807a: 27FD JEQ ($C$L8) 103 data = UCB0RXBUF; // clear RX flag 00807c: 421F 054C MOV.W &eUSCI_B0_UCB0RXBUF,R15 008080: 4FC1 0000 MOV.B R15,0x0000(SP) 104 UCB0TXBUF = 0; 008084: 4382 054E CLR.W &eUSCI_B0_UCB0TXBUF 105 while (!(UCB0IFG & UCRXIFG)); $C$L9: 008088: B392 056C BIT.W #1,&eUSCI_B0_UCB0IFG 00808c: 27FD JEQ ($C$L9) 106 data = UCB0RXBUF; // clear RX flag 00808e: 421F 054C MOV.W &eUSCI_B0_UCB0RXBUF,R15 008092: 4FC1 0000 MOV.B R15,0x0000(SP) 107 UCB0TXBUF = 0; 008096: 4382 054E CLR.W &eUSCI_B0_UCB0TXBUF 108 while (!(UCB0IFG & UCRXIFG)); $C$L10: 00809a: B392 056C BIT.W #1,&eUSCI_B0_UCB0IFG 00809e: 27FD JEQ ($C$L10) 109 data = UCB0RXBUF; // clear RX flag 0080a0: 421F 054C MOV.W &eUSCI_B0_UCB0RXBUF,R15 0080a4: 4FC1 0000 MOV.B R15,0x0000(SP) 110 UCB0TXBUF = 0x95; 0080a8: 40B2 0095 054E MOV.W #0x0095,&eUSCI_B0_UCB0TXBUF 111 while (!(UCB0IFG & UCRXIFG)); // USCI_B0 RX buffer ready? $C$L11: 0080ae: B392 056C BIT.W #1,&eUSCI_B0_UCB0IFG 0080b2: 27FD JEQ ($C$L11) 112 UCB0TXBUF = 0xFF; 0080b4: 40B2 00FF 054E MOV.W #0x00ff,&eUSCI_B0_UCB0TXBUF 113 data = UCB0RXBUF; 0080ba: 421F 054C MOV.W &eUSCI_B0_UCB0RXBUF,R15 0080be: 4FC1 0000 MOV.B R15,0x0000(SP) 114 while (!(UCB0IFG & UCRXIFG)); $C$L12: 0080c2: B392 056C BIT.W #1,&eUSCI_B0_UCB0IFG 0080c6: 27FD JEQ ($C$L12) 115 data = UCB0RXBUF; 0080c8: 421F 054C MOV.W &eUSCI_B0_UCB0RXBUF,R15 0080cc: 4FC1 0000 MOV.B R15,0x0000(SP) 116 UCB0TXBUF = 0xFF; 0080d0: 40B2 00FF 054E MOV.W #0x00ff,&eUSCI_B0_UCB0TXBUF 117 while (!(UCB0IFG & UCRXIFG)); $C$L13: 0080d6: B392 056C BIT.W #1,&eUSCI_B0_UCB0IFG 0080da: 27FD JEQ ($C$L13) 118 data = UCB0RXBUF; 0080dc: 421F 054C MOV.W &eUSCI_B0_UCB0RXBUF,R15 0080e0: 4FC1 0000 MOV.B R15,0x0000(SP) 119 CS_HIGH; 0080e4: D3D2 0222 BIS.B #1,&PB_PBOUT 121 return data; 0080e8: 416C MOV.B @SP,R12 122 } 0080ea: 5321 INCD.W SP 0080ec: 0110 RETA unsigned char i: Init_SD(): 008000: 8321 DECD.W SP 83 CS_HIGH; 008002: D3D2 0222 BIS.B #1,&PB_PBOUT 84 for (i=0; i<10; i++) // for more than 74 cycles 008006: 434F CLR.B R15 008008: 907F 000A CMP.B #0x000a,R15 00800c: 2C0A JHS ($C$L3) 86 UCB0TXBUF = 0xFF; // send clock pulses at CS high state $C$L1: 00800e: 40B2 00FF 054E MOV.W #0x00ff,&eUSCI_B0_UCB0TXBUF 87 while (!(UCB0IFG & UCTXIFG)); $C$L2: 008014: B3A2 056C BIT.W #2,&eUSCI_B0_UCB0IFG 008018: 27FD JEQ ($C$L2) 84 for (i=0; i<10; i++) // for more than 74 cycles 00801a: 535F INC.B R15 00801c: 907F 000A CMP.B #0x000a,R15 008020: 2BF6 JLO ($C$L1) 90 for(i=3; i>0; i--); // Delay $C$L3: 008022: 407F 0003 MOV.B #0x0003,R15 008026: 934F TST.B R15 008028: 2402 JEQ ($C$L5) $C$L4: 00802a: 835F DEC.B R15 00802c: 23FE JNE ($C$L4) 93 data = UCB0RXBUF; // clear RX flag $C$L5: 00802e: 421F 054C MOV.W &eUSCI_B0_UCB0RXBUF,R15 008032: 4FC1 0000 MOV.B R15,0x0000(SP) 94 CS_LOW; 008036: C3D2 0222 BIC.B #1,&PB_PBOUT 95 UCB0TXBUF = 0x40; 00803a: 40B2 0040 054E MOV.W #0x0040,&eUSCI_B0_UCB0TXBUF 96 while (!(UCB0IFG & UCRXIFG)); $C$L6: 008040: B392 056C BIT.W #1,&eUSCI_B0_UCB0IFG 008044: 27FD JEQ ($C$L6) 97 data = UCB0RXBUF; // clear RX flag 008046: 421F 054C MOV.W &eUSCI_B0_UCB0RXBUF,R15 00804a: 4FC1 0000 MOV.B R15,0x0000(SP) 98 UCB0TXBUF = 0; 00804e: 4382 054E CLR.W &eUSCI_B0_UCB0TXBUF 99 while (!(UCB0IFG & UCRXIFG)); $C$L7: 008052: B392 056C BIT.W #1,&eUSCI_B0_UCB0IFG 008056: 27FD JEQ ($C$L7) 100 data = UCB0RXBUF; // clear RX flag 008058: 421F 054C MOV.W &eUSCI_B0_UCB0RXBUF,R15 00805c: 4FC1 0000 MOV.B R15,0x0000(SP) 101 UCB0TXBUF = 0; 008060: 4382 054E CLR.W &eUSCI_B0_UCB0TXBUF 102 while (!(UCB0IFG & UCRXIFG)); $C$L8: 008064: B392 056C BIT.W #1,&eUSCI_B0_UCB0IFG 008068: 27FD JEQ ($C$L8) 103 data = UCB0RXBUF; // clear RX flag 00806a: 421F 054C MOV.W &eUSCI_B0_UCB0RXBUF,R15 00806e: 4FC1 0000 MOV.B R15,0x0000(SP) 104 UCB0TXBUF = 0; 008072: 4382 054E CLR.W &eUSCI_B0_UCB0TXBUF 105 while (!(UCB0IFG & UCRXIFG)); $C$L9: 008076: B392 056C BIT.W #1,&eUSCI_B0_UCB0IFG 00807a: 27FD JEQ ($C$L9) 106 data = UCB0RXBUF; // clear RX flag 00807c: 421F 054C MOV.W &eUSCI_B0_UCB0RXBUF,R15 008080: 4FC1 0000 MOV.B R15,0x0000(SP) 107 UCB0TXBUF = 0; 008084: 4382 054E CLR.W &eUSCI_B0_UCB0TXBUF 108 while (!(UCB0IFG & UCRXIFG)); $C$L10: 008088: B392 056C BIT.W #1,&eUSCI_B0_UCB0IFG 00808c: 27FD JEQ ($C$L10) 109 data = UCB0RXBUF; // clear RX flag 00808e: 421F 054C MOV.W &eUSCI_B0_UCB0RXBUF,R15 008092: 4FC1 0000 MOV.B R15,0x0000(SP) 110 UCB0TXBUF = 0x95; 008096: 40B2 0095 054E MOV.W #0x0095,&eUSCI_B0_UCB0TXBUF 111 while (!(UCB0IFG & UCRXIFG)); // USCI_B0 RX buffer ready? $C$L11: 00809c: B392 056C BIT.W #1,&eUSCI_B0_UCB0IFG 0080a0: 27FD JEQ ($C$L11) 112 UCB0TXBUF = 0xFF; 0080a2: 40B2 00FF 054E MOV.W #0x00ff,&eUSCI_B0_UCB0TXBUF 113 data = UCB0RXBUF; 0080a8: 421F 054C MOV.W &eUSCI_B0_UCB0RXBUF,R15 0080ac: 4FC1 0000 MOV.B R15,0x0000(SP) 114 while (!(UCB0IFG & UCRXIFG)); $C$L12: 0080b0: B392 056C BIT.W #1,&eUSCI_B0_UCB0IFG 0080b4: 27FD JEQ ($C$L12) 115 data = UCB0RXBUF; 0080b6: 421F 054C MOV.W &eUSCI_B0_UCB0RXBUF,R15 0080ba: 4FC1 0000 MOV.B R15,0x0000(SP) 116 UCB0TXBUF = 0xFF; 0080be: 40B2 00FF 054E MOV.W #0x00ff,&eUSCI_B0_UCB0TXBUF 117 while (!(UCB0IFG & UCRXIFG)); $C$L13: 0080c4: B392 056C BIT.W #1,&eUSCI_B0_UCB0IFG 0080c8: 27FD JEQ ($C$L13) 118 data = UCB0RXBUF; 0080ca: 421F 054C MOV.W &eUSCI_B0_UCB0RXBUF,R15 0080ce: 4FC1 0000 MOV.B R15,0x0000(SP) 119 CS_HIGH; 0080d2: D3D2 0222 BIS.B #1,&PB_PBOUT 121 return data; 0080d6: 416C MOV.B @SP,R12 122 } 0080d8: 5321 INCD.W SP 0080da: 0110 RETA Как можно видеть, вся разница в одной-единственной строчке (не считая, конечно, замены ячейки памяти на регистр R15): 00803a: 93C1 0001 TST.B 0x0001(SP) которой во втором варианте нет. Но какое отличие в поведении! Никогда бы не подумал, что такое возможно. Следует вообще все переменные объявлять volatile? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_pv 79 2 июня, 2020 Опубликовано 2 июня, 2020 · Жалоба еррату бы ещё глянуть, там, насколько помню, всегда было отнюдь не пусто по части usci. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Baser 5 2 июня, 2020 Опубликовано 2 июня, 2020 · Жалоба Поскольку у вас проявления глюка меняется от смены порядка команд, попробуйте увеличить разницу между частотой ядра и частотой SPI. Может быть разница в 4 раза мала для нормальной синхронной работы? Хотя никаких намеков на это в документации я не нашел... Или увеличьте частоту ядра или уменьшите скорость SPI. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
controller_m30 1 2 июня, 2020 Опубликовано 2 июня, 2020 · Жалоба Гипотеза, почему могут отличаться программы с переменными типа volatile и переменными обычными, статья. Если смотреть на листинги, в той части где происходит отправка команды 0 на карту - так программы абсолютно одинаковые! Но, зная что программы одинаковые, и сравнивая осциллограммы - появляется мысль, что по программе с обычной переменной таки "прошёлся" оптимизатор. Почему этого не видно на листингах? Возможно потому, что в листингах приведен дизассемблер исходной программы на С, а не итогового машинного кода, который заливается в контроллер. Это только гипотеза, но в контексте приведенной статьи, мне она кажется очень вероятной. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 243 3 июня, 2020 Опубликовано 3 июня, 2020 · Жалоба 14 часов назад, Herz сказал: Но стоит мне переменную-счётчик i объявить обычной, не volatile, как начинаются чудеса. Не чудеса это. МК всё сделал правильно, просто программа у Вас кривая. Посмотрите сами: Сначала отправляете 10 слов, после каждого ожидая только освобождения буфера передатчика (каждый новый принятый байт при этом переписывает поверх предыдущий в буфере приёма). Потом ставите CS=low не дожидаясь завершения передачи (т.е. - не дожидаясь флага RX от последнего слова). В варианте с volatile у Вас там есть задержка перед CS=low, поэтому последнее слово успевает прийти в rx-буфер (переписав предпоследнее) и Вы его удаляете нормально перед CS=low, а в варианте без volatile задержка меньше (а может вообще отсутствовать, так как компилятор вправе вообще удалить цикл for(i=3; i>0; i--)), и чтением rx-буфера перед CS=low удаляется не последнее слово, а предпоследнее из предыдущего цикла. И потом каждым чтением rx-буфера Вы читаете не то что ожидаете, а данные от предыдущей передачи (возможно, а может и текущей - как повезёт в зависимости от задержек, вызываемых всякими ISR). Так что МК и компилятор тут всё сделали правильно, косяк в программе. Нужно везде использовать RX-флаг регистра статуса прерываний, а не TX-флаг. И всё будет ок. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Herz 6 3 июня, 2020 Опубликовано 3 июня, 2020 · Жалоба Для чего же тогда TX-флаг придумали? Да, Вы всё правильно говорите, проблема была в опоздании на один байт очистки приёмного буфера, в невозможности определить, от какого принятого слова установлен флаг RX: от последнего или предыдущего. Потому флаг RX после сброса тут же устанавливался. Мне так и не пришло в голову, как это можно определить. Собственно, для этой цели и была вставлена задержка между первой частью инициализации (с CS=high) и второй, чтобы в буфер приёмника переписалось последнее слово. Увеличение этой задержки путём увеличения i до 5 решило эту проблему. Даже переменную data можно объявлять не- volatile. Хотя это кривое решение, конечно. Идея была в том, чтобы сократить до минимума время инициализации. А если в первой части тоже проверять RX-флаг, то процедура растягивается примерно вдвое за счёт пауз между пересылками тех десяти байтов. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 243 3 июня, 2020 Опубликовано 3 июня, 2020 · Жалоба 1 час назад, Herz сказал: Для чего же тогда TX-флаг придумали? Чтоб було, ведь у всех есть. Ну или для DMA. 1 час назад, Herz сказал: Увеличение этой задержки путём увеличения i до 5 решило эту проблему. Даже переменную data можно объявлять не- volatile. Хотя это кривое решение, конечно. Это называется "выстрелить себе в ногу". Ибо работать будет до следующей перекомпиляции, когда компилятор чуть поумнеет и решит что цикл можно вообще секвестировать. 1 час назад, Herz сказал: Идея была в том, чтобы сократить до минимума время инициализации. А если в первой части тоже проверять RX-флаг, то процедура растягивается примерно вдвое за счёт пауз между пересылками тех десяти байтов. А почему бы не использовать DMA для ускорения? Оно же есть в вашем МК? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Herz 6 3 июня, 2020 Опубликовано 3 июня, 2020 · Жалоба 14 minutes ago, jcxz said: Это называется "выстрелить себе в ногу". Ибо работать будет до следующей перекомпиляции, когда компилятор чуть поумнеет и решит что цикл можно вообще секвестировать. А почему бы не использовать DMA для ускорения? Оно же есть в вашем МК? На сейчас я заменил цикл на __delay_cycles(15); и надеюсь, что компилятор с этим уже ничего делать не станет. А с DMA я ещё работать не умею, не дорос. Намекните, как это изменит ситуацию? Приёмный буфер будет переписываться в память, минуя регистр R15? Так даже если я сбрасываю флаг RX прямо в регистре: UCB0IFG &= ~UCRXIFG; // clear RX flag а не чтением приёмного буфера, занимает это ровно столько же времени. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 243 3 июня, 2020 Опубликовано 3 июня, 2020 · Жалоба 19 часов назад, Herz сказал: А с DMA я ещё работать не умею, не дорос. Намекните, как это изменит ситуацию? Приёмный буфер будет переписываться в память, минуя регистр R15? Так даже если я сбрасываю флаг RX прямо в регистре: UCB0IFG &= ~UCRXIFG; // clear RX flag а не чтением приёмного буфера, занимает это ровно столько же времени. Медленность работы по RX-флагу не из-за выполнения команд процессором, а из-за задержек при передачи данных из сдвигового регистра в буферный и выставления флагов готовности внутри SPI-блока. Имхо. Поэтому сброс RX-флага вместо чтения данных ничего не даст. А DMA изменит ситуацию в том плане, что отдельно программируется передающий DMA-поток (работающий по флагу TX и делающий N записей в буферный регистр), а отдельно - приёмный DMA-поток (работающий по флагу RX и выполняющий те же N пересылок). И программа ждёт завершения приёмного потока. Таким образом - и задержек между байтами лишних не будет и завершение транзакции будет определяться корректно. PS: Если DMA не хочется, то и Ваш цикл можно "прокачать" до работоспособности и быстрой передачи: short c, i, i1; char dummy; i1 = i = 10; do { UCB0TXBUF = 255; do if ((c = UCB0IFG) & UCRXIFG) { dummy = UCB0RXBUF; i1--; } while (!(c & UCTXIFG)); } while (--i); for (; --i1 >= 0; dummy = UCB0RXBUF) while (!(UCB0IFG & UCRXIFG)); За отсутствие ошибок - не ручаюсь, так как нет под рукой компилятора с MSP430. Да и типы переменных может не совсем оптимальны - давно не работал с MSP430. Но смысл думаю ясен. И без всяких непредсказуемых задержек... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Herz 6 3 июня, 2020 Опубликовано 3 июня, 2020 · Жалоба О, спасибо, попробую. С ходу смысл не уловил, надо сосредоточиться. Это в качестве замены первой части, верно? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Obam 38 3 июня, 2020 Опубликовано 3 июня, 2020 · Жалоба DMA не изменит ситуацию, по причине отсутствия наличия оного. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 243 3 июня, 2020 Опубликовано 3 июня, 2020 · Жалоба 2 часа назад, Herz сказал: Это в качестве замены первой части, верно? Да. Того цикла, который выполняется при CS_HIGH. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Herz 6 4 июня, 2020 Опубликовано 4 июня, 2020 · Жалоба 18 hours ago, jcxz said: Но смысл думаю ясен. И без всяких непредсказуемых задержек... Что-то я никак постичь не могу. Там со скобками всё правильно? По-моему, нет... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться