То был Slave, это Master //***************************************************
//* SPI *
//* Связь с ATMega161 *
//***************************************************
#define SS PORTB_.bit.bit_0 // вывод SS
#define DirSS DDRB_.bit.bit_0 // направление вывода SS
#define DirMOSI DDRB_.bit.bit_2 // направление вывода MOSI
#define SCK PORTB_.bit.bit_1 // тактовые импульсы
class SPI: public Baseclass
{
public:
SPI();
char * operator & (void); // доступ к массиву OutputBuffer
private:
bool GetEvent(const Event,unsigned char x=0,void *Tag=0);
static SPI* SPIPtr; // указатель на UART
char mode; // прием фрейма/пауза
char OutputNum; // счетчик байт
char InputNum; // счетчик байт на прием
char *InputPtr; // указатель на буфер приема
char InputByffer[128]; // буфер приема
char OutputBuffer[128]; // массив на передачу
char *OutputPtr; // указатель на буфер передачи
//*********** Обработка прерываний ******************
#pragma vector=SPI_STC_vect
static __interrupt void SPI_TX() // прерывания
{
char x; // принятый символ
x = SPDR; // взять символ
SPIE = 0; // запретить прерывания SPI
DirSS = 1;
DirMOSI = 1; // направление MOSI - выход
DDRB_.bit.bit_1 = 1; // направление SCK - выход
if(!MSTR) { MSTR = 1; return; }
MSTR = 1; // master
__enable_interrupt(); // разрешить прерывания
//**************** Прием байта **********************
switch (SPIPtr->mode)
{
case 0: if(x) // первый байт фрейма (адрес)
if(xInputByffer)) // если не превышает длину буфера
{
SPIPtr->InputNum = x; // 1-й байт - длина посылки
SPIPtr->InputPtr = SPIPtr->InputByffer; // указатель на начало
SPIPtr->mode = 1; // начало приема фрейма
}
break; // выход
case 1: *(SPIPtr->InputPtr++) = x; // байт в буфер
if(!(--SPIPtr->InputNum))
{
SPIPtr->mode = 0; // конец приема данных
SendEvent // принят фрейм (FrameOfSPI,(char)(SPIPtr->InputPtr-SPIPtr->InputByffer),SPIPtr->InputByffer);
}
break; // выход
}
//************** Передача байта *********************
__delay_cycles(10000l); // задержка, ATMega161 не успевает обрабатывать,
// прерывания разрешены, события обрабатываются
if(SPIPtr->OutputNum) // если есть что передавать
{
SPDR = *(SPIPtr->OutputPtr++); // передать байт
SPIPtr->OutputNum--; // уменьшить счетчик байт
}
else SPDR = 0; // если буфер пуст, передать 0
SS = 0; // Выбор подчиненного
SPIE = 1; // разрешить прерывания
}
};
//************** Конструктор ************************
SPI::SPI()
{
SPIPtr = this; // Указатель на SPI
OutputNum = 0; // кол-во байт на передачу
InputNum = 0; // кол-во байт на прием
mode = 0; // пауза между фреймами
InputPtr = InputByffer; // указатель на начало буфера
OutputPtr = OutputBuffer; // указатель на начало буфера
SS = 1; DirSS = 1;
SPR = 3; // скорость f/128
MSTR = 1; // master
DirMOSI = 1; // направление MOSI - выход
DDRB_.bit.bit_1 = 1; // направление SCK - выход
SPE = 1; // разрешение SPI
SPDR = 0; // инициализация передачи
DirSS = 1; SS = 0; // Выбор подчиненного
SPIE = 1; // разрешить прерывания
}
//******* Доступ к массиву OutputBuffer *************
char * SPI::operator & (void)
{
return OutputBuffer; // адрес массива
}
//********** Обработка событий **********************
bool SPI::GetEvent(Event n,unsigned char x,void *Ptr)
{
switch (n)
{
case WriteToSPI:
OutputPtr = OutputBuffer; // указатель на начало OutputBuffer
OutputNum = *OutputPtr; // кол-во байт на передачу
return StopEvent; // закончить обработку
}
return ContinueEvent; // продолжать обработку
}
//***************************************************
SPI* SPI::SPIPtr; // инициализация указателя
//***************** Создаем объект ******************
SPI Spi;