Даю вырезки для работы с SPI LPC213x. Подойдёт и ко многим другим. С AT91 не знаком, так что немного переделаете. Вообще, процедуры написаны так, чтобы максимально использовать скорость процессора. То есть во время передачи байта можно выполнять другие действия.
Процедуры инициализации:
#define PCLKFREQ 14745600*4
void LPC213xInitSPI0Master() { PINSEL0 = (PINSEL0 & ~0xff00) | 0x1500; // for SCK0, MISO, MOSI, SSEL- SPCCR0 = PCLKFREQ / 921600; // скорость = 0.6912 MHz (~80 КБ/сек) SPCR0 = 0x20; if (SPSR0) {}; // просто чтение для сброса флага SPIF SPDR0 = '!'; // это чтобы изначально бит SPIF (TDRE) установился }
void txByteSPI0(long byte) { if (SPSR0) {} // просто чтение для сброса флага SPIF SPDR0 = byte; }
long rxtxByteSPI0(long byte) { for(uInt i=0; i<0x10000; i++) // 1/50 sec - это на всякий случай. Всё бывает на свете! if (SPSR0_bit.SPIF) // это бит завершения передачи байта в мастере (и приёма в слэйве) { long j = SPDR0; if (byte >= 0) SPDR0 = byte; return(j); } LPC213xInitSPI0Master(); return(0); }
Рабочие процедуры:
void READ_ADS1218(uInt cmd, uInt cnt, uByte *ptr) { _ON_CS_ADS1218; txByteSPI(cmd); rxtxByteSPI(cnt-1); _WAIT(_50Tosc); rxtxByteSPI(0); while (cnt--) if (cnt) *ptr++ = rxtxByteSPI(0); else *ptr = rxtxByteSPI(-1); // завершение передачи _OFF_CS_ADS1218; }
Пояснение: В моей схеме был режим мастер, а вывод SSEL вообще не использовался. Сначала вручную сбрасывается сигнал ~CS на нужное внешнее устройство. Затем вызывается процедура передачи первого байта без анализа флагов (txByteSPI0(long byte)). После сколько угодно раз процедуру уже анализирующую флаги (rxtxByteSPI0(long byte)). Однако в конце нужно вызывать её же с параметром (-1). Она при этом ничего не передаёт, а просто ждёт завершения передачи последнего байта. После этого уже можно обратно вручную устанавливать вывод ~CS в еденицу (_OFF_CS_ADS1218).
Если не выжимать из процессора максимум скорости, то можно было бы сделать немного попроще. Но мне так больше нравится.
Если нужно просто выкинуть в SPI 6 байт то вот пример:
void Write6bytesSPI(uByte *ptr) { _ON_CS_ADS1218; txByteSPI(*ptr++); for (uInt i=0; i<5; i++) // здесь выкинуть именно 5, а не 6 байт. т.к. один уже выкинут rxtxByteSPI(*ptr++); rxtxByteSPI(-1); // завершение передачи _OFF_CS_ADS1218; }
Кстати, процедура (rxtxByteSPI0(long byte)) передаёт новый байт в SPI, но возвращает как бы предыдущий принятый байт. Осторожно!
--------------------
Заблуждаться - Ваше законное право :-)
|