ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Пятница
19 июля
21147 Топик полностью
Михаил Е. (29.01.2005 17:04, просмотров: 1) ответил Михаил Е. на А, вот.
То был 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;