|
DMA - для чего он и как его использовать |
|
|
|
Jan 30 2007, 22:39
|
Участник

Группа: Новичок
Сообщений: 73
Регистрация: 10-01-07
Пользователь №: 24 292

|
Подскажите для чего нужен DMA и если можно пример как его использовать. Пример "фирменный" или свой - в чем "СОЛЬ" DMA ?
|
|
|
|
|
Jan 31 2007, 01:20
|
Участник

Группа: Новичок
Сообщений: 73
Регистрация: 10-01-07
Пользователь №: 24 292

|
Спасибо. подскажите апноут какой нить чтоб посмотреть конкретно.
и еще - этот буфер будет требовать данные или принимть по мере помтупления ? т.е. как передатчик даст ... или по всякому бывает.
и еще - ресь идет о внутренней РАМ или и внешней тоже ?
|
|
|
|
|
Jan 31 2007, 01:45
|
Участник

Группа: Новичок
Сообщений: 73
Регистрация: 10-01-07
Пользователь №: 24 292

|
и какова скорость приема дданных ? например по параллельному интерфейсу в LPC или SAM - во сколько раз медленней такта ?
|
|
|
|
|
Jan 31 2007, 10:27
|

Профессионал
    
Группа: Свой
Сообщений: 1 065
Регистрация: 8-10-05
Из: Kiev, UA
Пользователь №: 9 380

|
Цитата Спасибо. подскажите апноут какой нить чтоб посмотреть конкретно. Нечего там смотреть. Прописываются два регистра - указатель на буфер и количество байт. Для SAM все описание узла страницы на три включая раскладку регистров. Цитата и еще - этот буфер будет требовать данные или принимть по мере помтупления ? т.е. как передатчик даст ... или по всякому бывает. По сути DMA это второй счетчик адреса. Т.е. в обычном режиме идет пересылка IO -> регистры ядра -> RAM, с DMA IO -> RAM (для передачи наоборот) пока не насчитает заданное количество байт. Для IO будет ждать готовности данных, для памяти будет молотить пока свободна шина.
--------------------
Вони шукають те, чого нема, Щоб довести, що його не існує.
|
|
|
|
|
Jan 31 2007, 11:40
|
Участник

Группа: Новичок
Сообщений: 73
Регистрация: 10-01-07
Пользователь №: 24 292

|
большое спасибо за помощь. сижу разбираюсь.
|
|
|
|
|
Jan 31 2007, 23:05
|
Местный
  
Группа: Свой
Сообщений: 459
Регистрация: 15-07-04
Из: g.Penza
Пользователь №: 326

|
zltigo Режим работы контроллера DMA определяется в первую очередь типом используемой накристальной шины. В частности, шина AHB может иметь несколько ведущих и ведомых, и несколько шина адреса данных, подключаемых через мультиплексор. Поэтому время задержки транзакции незначительно, то есть как CPU, так и DMA имеют, в среднем, одинаковые возможности для доступа к ресурсам. Поправите, если не прав. Abakt В режиме DMA не используются ресурсы (регистры, АЛУ и т.п.) на операции пересылки данных.
|
|
|
|
|
Feb 1 2007, 00:40
|

Любитель
    
Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695

|
Цитата(beer_warrior @ Jan 31 2007, 23:35)  А и действительно. Не дадите ли ссылку на доку? Момент ведь весьма принципиальный. Вот что написано в мануале к SAM7S: The Memory Controller has a simple, hard-wired priority bus arbiter that gives the control of the bus to one of the two masters. The Peripheral DMA Controller has the highest priority; the ARM processor has the lowest one. [AT91SAM7S.pdf, 6175G–ATARM–22-Nov-06, page 120] Действительно, курить в сторонке будет процессор, а не DMA...
Сообщение отредактировал sonycman - Feb 1 2007, 00:41
|
|
|
|
|
Feb 1 2007, 12:23
|
Местный
  
Группа: Свой
Сообщений: 211
Регистрация: 9-11-06
Пользователь №: 22 136

|
Цитата(Karl @ Feb 1 2007, 08:49)  Помогите, пожалуйста, с конкретной задачей: Необходимо через ДМА передавать массив в SPI и получать из него ответ (контроллер SAM7S64). Какие операции необходимо произвести? Вот как делаю я (коментарии от специалистов приветствуются  ) Здесь только отсылка, ну и особенности от FreeRTOS, но общий смысл должен быть понятен. Код void SPI_task(void *pvParameters) { unsigned portCHAR i; unsigned portCHAR SPI_buf[8]; ( void ) pvParameters; portENTER_CRITICAL();
AT91F_PMC_EnablePeriphClock(AT91C_BASE_PMC, 1 << AT91C_ID_SPI); AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, AT91C_PA11_NPCS0 | AT91C_PA12_MISO | AT91C_PA13_MOSI | AT91C_PA14_SPCK, 0); AT91F_SPI_Reset(AT91C_BASE_SPI);
AT91C_BASE_SPI->SPI_MR=0x0E0011;//Master mode, fixed select, disable decoder, FDIV=0 (MCK), PCS=1110
AT91F_SPI_CfgCs(AT91C_BASE_SPI, 0, AT91C_SPI_NCPHA | (128 << 8) | 0x04 ); AT91F_SPI_Enable(AT91C_BASE_SPI); AT91F_PDC_Open(AT91C_BASE_PDC_SPI); for(i=0;i<8;i++) SPI_buf[i]=i; portEXIT_CRITICAL();
for(;;)
{ while(AT91F_SPI_SendFrame(AT91C_BASE_SPI,(char*) &SPI_buf[0],8,0,0) == 0) vTaskDelay(portTICK_RATE_MS * 10); i++; SPI_buf[7]=i; vTaskDelay(portTICK_RATE_MS * 1000); } }
|
|
|
|
|
Feb 1 2007, 14:08
|
Местный
  
Группа: Свой
Сообщений: 211
Регистрация: 9-11-06
Пользователь №: 22 136

|
Цитата(Karl @ Feb 1 2007, 13:26)  Спасибо, вроде все понятно. А с приемом Вы не разбирались? Нет, мне пока без надобности. Я на прием PDC использую с ADC. Код надо?
|
|
|
|
|
Feb 1 2007, 16:47
|
Частый гость
 
Группа: Свой
Сообщений: 179
Регистрация: 4-02-05
Пользователь №: 2 429

|
Цитата(Kitsok @ Feb 1 2007, 16:08)  Цитата(Karl @ Feb 1 2007, 13:26)  Спасибо, вроде все понятно. А с приемом Вы не разбирались?
Нет, мне пока без надобности. Я на прием PDC использую с ADC. Код надо? Да, пригодится. Кстати, передача заработала сразу  Спасибо! У меня на SPI АЦП сидит. Так что надо и передачу и прием.
|
|
|
|
|
Feb 1 2007, 19:38
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(sonycman @ Jan 31 2007, 23:40)  The Memory Controller has a simple, hard-wired priority bus arbiter that gives the control of the bus to one of the two masters. The Peripheral DMA Controller has the highest priority; the ARM processor has the lowest one. [AT91SAM7S.pdf, 6175G–ATARM–22-Nov-06, page 120]
Действительно, курить в сторонке будет процессор, а не DMA... Причем по другому для периферийного железа которое не имеет своих буферов и быть не может, например, летит в 100 Mbit интерфейс 1500 байтовый пакет. Куда ему прикажете его девать? Тут уж или терять, или процессор идет на перекур. Без вариантов. Цитата(ASN @ Jan 31 2007, 22:05)  zltigo Режим работы контроллера DMA определяется в первую очередь типом используемой накристальной шины. Определяется, например, свежие LPC23xx имеют два банка памяти и соответственно две шины, что позволяет достаточно независимо работать DMA (в своих 8K) и CPU каждому в своем банке большую часть времени. Обычные ARM7 такого не имеют.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Feb 2 2007, 11:48
|
Местный
  
Группа: Свой
Сообщений: 211
Регистрация: 9-11-06
Пользователь №: 22 136

|
Это инициализация Код #define NCHANNELS 8
extern volatile unsigned portSHORT sADC_RAW[NCHANNELS*2]; #define TRGEN (0x0) // Hardware triggering #define TRGSEL (0x0) // Use a Timer output signal (on rising edge) from TIOA0 (for this example) #define LOWRES (0x0) // 8-bit result output #define SLEEP (0x0) // Normal Mode #define PRESCAL (0x0f) // Max value #define STARTUP (0xc) // This time period must be higher than 20 ╣s and not 20 ms #define SHTIM (0x2) // Must be higher than 3 ADC clock cycles but depends on output // impedance of the analog driver to the ADC input
void InitADC(void) {
// Reset ADC AT91F_ADC_SoftReset (AT91C_BASE_ADC);
// Open PDC for ADC AT91F_PDC_Open (AT91C_BASE_PDC_ADC);
// Configure PDC for 2 buffers NCHANNELS bytes long each (Warning! Depends on LOWRES bit) AT91F_PDC_ReceiveFrame ( AT91C_BASE_PDC_ADC , (char *) &sADC_RAW[0], NCHANNELS, (char *) &sADC_RAW[NCHANNELS], NCHANNELS);
// Configure ADC AT91F_ADC_CfgModeReg (AT91C_BASE_ADC, (SHTIM << 24) | (STARTUP << 16) | (PRESCAL << 8) | (SLEEP << 5) | (LOWRES <<4) | (TRGSEL << 1) | (TRGEN ) );
// Enable all 8 channes AT91F_ADC_EnableChannel(AT91C_BASE_ADC, (1<<NCHANNELS) - 1);
// Fire conversion AT91F_ADC_StartConversion(AT91C_BASE_ADC); } А это собственно работа Код // Check what buffer to use from ADC if (AT91C_BASE_PDC_ADC->PDC_RCR == 0) { ptrADC_RAW=NCHANNELS; AT91F_PDC_ReceiveFrame ( AT91C_BASE_PDC_ADC , (char *) &sADC_RAW[0], NCHANNELS, (char *) &sADC_RAW[NCHANNELS], NCHANNELS); } else { ptrADC_RAW=0; }
// Re-fire conversion AT91F_ADC_StartConversion(AT91C_BASE_ADC); Тут возможно следовало бы использовать библиотечные функции, но я не запарился и читаю напрямую PDC_RCR. ptrADC_RAW нужен для того, чтобы знать, в какой части буфера лежат свежие данные: Код // Convert 10-bit wide ADC results into 8-bit wide // Clean target array for(i=0;i<(NCHANNELS*10/8);i++) ucAxes[i]=0;
// Do bit manipulations // The trick with +0x0200 & 0x03ff is - we need negative 10-bit wide number for(i=0;i<(NCHANNELS*10);i++) { ucAxes[i/8] += (((((sADC_RAW[ptrADC_RAW+(i/10)] + 0x0200)&0x03ff)>> (i%10)) & 0x01) << (i%8)); }
Сообщение отредактировал Kitsok - Feb 2 2007, 11:51
|
|
|
|
|
Feb 6 2007, 15:28
|
Местный
  
Группа: Свой
Сообщений: 211
Регистрация: 9-11-06
Пользователь №: 22 136

|
Цитата(Karl @ Feb 6 2007, 13:16)  Можно ли одновременно передавать массив данных в SPI через ДМА и получать данные из SPI через тот же ДМА? Что-то у меня не получается такой обмен... Передача идет, а прием - нет. Ну вообще, PDA - штука двунаправленная, но конкретику надо смотреть в даташите и всяких примерах. Я не реализовывал двунаправленную передачу по SPI.
|
|
|
|
|
Feb 7 2007, 08:44
|
Частый гость
 
Группа: Свой
Сообщений: 179
Регистрация: 4-02-05
Пользователь №: 2 429

|
Цитата(Kitsok @ Feb 6 2007, 17:28)  Цитата(Karl @ Feb 6 2007, 13:16)  Можно ли одновременно передавать массив данных в SPI через ДМА и получать данные из SPI через тот же ДМА? Что-то у меня не получается такой обмен... Передача идет, а прием - нет.
Ну вообще, PDA - штука двунаправленная, но конкретику надо смотреть в даташите и всяких примерах. Я не реализовывал двунаправленную передачу по SPI. Спасибо, вроде разобрался. Заработало.
|
|
|
|
|
Feb 12 2007, 19:01
|
Местный
  
Группа: Свой
Сообщений: 211
Регистрация: 9-11-06
Пользователь №: 22 136

|
Цитата(Karl @ Feb 7 2007, 08:44)  Спасибо, вроде разобрался. Заработало. Добрый день! А можете код показать? Удалось ли принимать данные с использованием PDC?
|
|
|
|
|
Feb 15 2007, 07:26
|
Частый гость
 
Группа: Свой
Сообщений: 179
Регистрация: 4-02-05
Пользователь №: 2 429

|
Цитата(Kitsok @ Feb 12 2007, 21:01)  Цитата(Karl @ Feb 7 2007, 08:44)  Спасибо, вроде разобрался. Заработало.
Добрый день! А можете код показать? Удалось ли принимать данные с использованием PDC? Да, передачу и прием по PDC организовать удалось. Проблемы, как оказалось, были не с PDC, а с некорректной работой с SPI. Инициализация SPI: Код void SPI_ini(void) {
AT91F_SPI_Reset(AT91C_BASE_SPI); //delay_ms(5); // Инициализация SPI. Запустим на работу с частотой примерно 2,5 МГц // Конфигурация канала АЦП (2 канал) AT91F_PMC_EnablePeriphClock(AT91C_BASE_PMC, 1 << AT91C_ID_SPI); // Тактирование на SPI AT91F_SPI_CfgMode(AT91C_BASE_SPI, 1<<0| //Интерфейс работает в режиме ведущего. 0<<1| //Фиксированный выбор корпуса внешнего периферийного устройства. 0<<2| //PCSDEC: Декодирование выбора корпуса 0 = Периферийные устройства непосредственно подключены к выводам выбора корпуса. 0<<4| //MODFDIS: Определение ошибки режима работы 0 =Определение ошибки режима работы запрещено. 0<<7| // Зацикливание 0 - отключено 0xb<<16); // PCS: Выбор корпуса периферии Корпус 3 AT91F_SPI_CfgCs(AT91C_BASE_SPI,2, AT91C_SPI_BITS_8| // 8 бит в пакете 400<<8| // Частота SPI в 20 наза меньше MCK (необходимо не более 2,5 МГц) 2<<16| // Задержка перед выдачей тактовой частоты 0<<24| // Задержка между последовательными передачами данных 1<<1);
AT91F_SPI_Enable(AT91C_BASE_SPI); AT91F_PDC_Open(AT91C_BASE_PDC_SPI); } Собственно работа: Код for(;;)
{ while(AT91F_SPI_SendFrame(AT91C_BASE_SPI,(char*) &SPI_buf_TX[0],sizeof(SPI_buf_TX),0,0) == 0); u08 a = AT91F_SPI_ReceiveFrame(AT91C_BASE_SPI,(char*) &SPI_buf_RX[0],sizeof(SPI_buf_TX),0,0); // Ожидаем, пока приемный буфер заполнится. В дальнейшем включу на прерывание. while(!( a = AT91C_BASE_SPI->SPI_SR & AT91C_SPI_ENDRX)); ... ... ... }
|
|
|
|
|
Feb 15 2007, 19:59
|

Профессионал
    
Группа: Свой
Сообщений: 1 065
Регистрация: 8-10-05
Из: Kiev, UA
Пользователь №: 9 380

|
Цитата Собственно работа: Код for(;;)
{ while(AT91F_SPI_SendFrame(AT91C_BASE_SPI,(char*) &SPI_buf_TX[0],sizeof(SPI_buf_TX),0,0) == 0); u08 a = AT91F_SPI_ReceiveFrame(AT91C_BASE_SPI,(char*) &SPI_buf_RX[0],sizeof(SPI_buf_TX),0,0); // Ожидаем, пока приемный буфер заполнится. В дальнейшем включу на прерывание. while(!( a = AT91C_BASE_SPI->SPI_SR & AT91C_SPI_ENDRX)); ... ... ... } Кстати абсолютно не вижу кайфа в такой конструкции. ДМА гонит данные, ядро ожидает завершения. Точно так же можно использовать и программные счетчик и указатель. Чтобы действительно получить выигрыш, флажок завершения приема/передачи надо прицепить к прерыванию. В таком случае действительно ДМА будет жить своей жизнью, а ядро отвлекаться на подготовку/обработку данных один раз на фрейм, а в остальное время заниматься чем-то полезным.
--------------------
Вони шукають те, чого нема, Щоб довести, що його не існує.
|
|
|
|
|
Feb 16 2007, 09:29
|
Частый гость
 
Группа: Свой
Сообщений: 179
Регистрация: 4-02-05
Пользователь №: 2 429

|
Цитата(beer_warrior @ Feb 15 2007, 21:59)  Цитата Собственно работа: Код for(;;)
{ while(AT91F_SPI_SendFrame(AT91C_BASE_SPI,(char*) &SPI_buf_TX[0],sizeof(SPI_buf_TX),0,0) == 0); u08 a = AT91F_SPI_ReceiveFrame(AT91C_BASE_SPI,(char*) &SPI_buf_RX[0],sizeof(SPI_buf_TX),0,0); // Ожидаем, пока приемный буфер заполнится. В дальнейшем включу на прерывание. while(!( a = AT91C_BASE_SPI->SPI_SR & AT91C_SPI_ENDRX)); ... ... ... } Кстати абсолютно не вижу кайфа в такой конструкции. ДМА гонит данные, ядро ожидает завершения. Точно так же можно использовать и программные счетчик и указатель. Чтобы действительно получить выигрыш, флажок завершения приема/передачи надо прицепить к прерыванию. В таком случае действительно ДМА будет жить своей жизнью, а ядро отвлекаться на подготовку/обработку данных один раз на фрейм, а в остальное время заниматься чем-то полезным. А Вы прочитайте внимательнее комментарии. Я выложил кусок тестовой програмки. Так проще разобраться в коде тем, кто будет смотреть. Реально у меня все на прерываниях.
|
|
|
|
|
Feb 16 2007, 11:46
|
Местный
  
Группа: Свой
Сообщений: 211
Регистрация: 9-11-06
Пользователь №: 22 136

|
Цитата(beer_warrior @ Feb 15 2007, 19:59)  Кстати абсолютно не вижу кайфа в такой конструкции. ДМА гонит данные, ядро ожидает завершения. Точно так же можно использовать и программные счетчик и указатель. Чтобы действительно получить выигрыш, флажок завершения приема/передачи надо прицепить к прерыванию. В таком случае действительно ДМА будет жить своей жизнью, а ядро отвлекаться на подготовку/обработку данных один раз на фрейм, а в остальное время заниматься чем-то полезным. Ну почему-же нету кайфа. Я например под FreeRTOS клепаю, так у меня, пока данные не готовы, будет отдаваться выполнение другим задачам  Другой вопрос меня интересует, может доку не внимательно читал. Вот допустим, я так сделал железо, что один и тот-же ChipSelect у меня работает и на передачу и на прием (разнос по сигналами MOSI/MISO). Запускаю я одновременно и передачу и прием. SPI может дупелксно и передавать и принимать?
|
|
|
|
|
Feb 16 2007, 12:39
|

читатель даташитов
   
Группа: Свой
Сообщений: 853
Регистрация: 5-11-06
Из: Днепропетровск
Пользователь №: 21 999

|
Цитата(Kitsok @ Feb 16 2007, 10:46)  Другой вопрос меня интересует, может доку не внимательно читал.
Вот допустим, я так сделал железо, что один и тот-же ChipSelect у меня работает и на передачу и на прием (разнос по сигналами MOSI/MISO). Запускаю я одновременно и передачу и прием. SPI может дупелксно и передавать и принимать? The SPI is a full duplex serial interface, designed to be able to handle multiple masters and slaves connected to a given bus. Это иэ доки на LPC2194. Одновременно сдвигаются и регистр приема, и регистр передачи.
|
|
|
|
|
Feb 16 2007, 12:53
|
Частый гость
 
Группа: Свой
Сообщений: 179
Регистрация: 4-02-05
Пользователь №: 2 429

|
Цитата(Kitsok @ Feb 16 2007, 13:46)  Вот допустим, я так сделал железо, что один и тот-же ChipSelect у меня работает и на передачу и на прием (разнос по сигналами MOSI/MISO). Запускаю я одновременно и передачу и прием. SPI может дупелксно и передавать и принимать? SPI работает в дуплексном режиме. По каждому тактовому сигналу один битик передается и один принимается.
|
|
|
|
|
Feb 20 2007, 01:03
|
Местный
  
Группа: Свой
Сообщений: 211
Регистрация: 9-11-06
Пользователь №: 22 136

|
Цитата(Karl @ Feb 16 2007, 12:53)  SPI работает в дуплексном режиме. По каждому тактовому сигналу один битик передается и один принимается. А вот тут возникает интересный вопрос с ChipSelect - если в процессе передачи я меняю адрес устройства для приема, то что будет, старый PCS так и останется активным и новый PCS станет активным, или нет?
|
|
|
|
|
Feb 20 2007, 06:54
|
Частый гость
 
Группа: Свой
Сообщений: 179
Регистрация: 4-02-05
Пользователь №: 2 429

|
Цитата(Kitsok @ Feb 20 2007, 03:03)  Цитата(Karl @ Feb 16 2007, 12:53) 
SPI работает в дуплексном режиме. По каждому тактовому сигналу один битик передается и один принимается.
А вот тут возникает интересный вопрос с ChipSelect - если в процессе передачи я меняю адрес устройства для приема, то что будет, старый PCS так и останется активным и новый PCS станет активным, или нет? Изменяемый выбор периферийного устройства позволяет вести буферизованную передачу данных с различными периферийными устройствами без перепрограммирования содержимого регистра управления режимом работы. Информация записывается в передающий регистр данных словом в 32-битной ширины, и содержит передаваемые данные и номер периферийного устройства, которому они предназначены. При использовании контроллера ПДП периферии (PDC) в этом режиме необходимы 32 - битные буферы, с хранением данных в LSB и полями PCS и LASTXFER в MSB. Интерфейс может управлять количеством бит данных, передаваемых по линиям MISO и MOSI за один сеанс передачи (8 или 16) с помощью регистров управления выбором корпуса. Если исходить из размера выделяемой под буфера памяти, это не самый оптимальный способ, но он предоставляет очень эффективные возможности для обмена данных с несколькими периферийными устройствами без занятия процессора.
|
|
|
|
|
Feb 20 2007, 12:23
|
Местный
  
Группа: Свой
Сообщений: 211
Регистрация: 9-11-06
Пользователь №: 22 136

|
Всем привет!
Вчера вперся в непонятную проблему, решения (кроме совсем тупого) пока не нашел.
Итак, вывод данных у меня сделан с помощью 74HC595, ввод - 74НС165. Висят на одном CS, точноо, к '165 CS вообще не подключен. В настройках CPOL=0, NCPHA = 1.
Делаю пока без PDC, потому что не могу элементарно найти глюк.
Отсылаю байт, жду, принимаю байт. Отсылка работает нормально, '595 принимает байт, на выводах все, что нужно. А вот при приеме затесывается лишняя единичка в начале (LSB). Т.е. у '165 все входы подтянуты к земле, однако принимаю я 0х01.
Меняю CPOL=1, начинает работать ввод, но теряется один бит на выводе.
Учитался даташитов, не могу понять, что не так.
Тупое решение проблемы - раздельный вывод и ввод, т.е. менять CSR между циклом вывода и ввода. Но это значет, что прощай дуплекс, сначала 40 мс ждем пока все данные улетят в вывод, потом столько-же, пока данные прилетят со ввода. Что делать - не понятно...
|
|
|
|
|
Feb 20 2007, 18:01
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(Dron_Gus @ Feb 20 2007, 16:21)  Значит для чтения нужно "гнать" какие-нить левые данныеи и "туда"? И абсолютно безразлично какие? Т.е. я могу настроить блок PDC на передачу на тот же буфер, что и приемник, например? Да. Цитата(Kitsok @ Feb 20 2007, 11:23)  Отсылка работает нормально, '595 принимает байт, на выводах все, что нужно. А вот при приеме затесывается лишняя единичка в начале (LSB). Т.е. у '165 все входы подтянуты к земле, однако принимаю я 0х01. Увы, так и есть. 595 защелкивает по фронту тактового импульса, 165 выдает первый бит по этому же фронту, т.е. уже после чтения в SPI. Вот и получается сдвиг на бит. К сожалению, в SPI нет режима, в котором данные выставляются по фронту а читаются по срезу. Можно включить инвертор в цепь CLK одного из регистров, может и поможет - надо помедитировать над времянкой.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|