реклама на сайте
подробности

 
 
> Программный SPI, реализация на avr
CIIAPTAK
сообщение Oct 18 2009, 13:09
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 27
Регистрация: 22-07-07
Пользователь №: 29 290



Доброго дня уважаемые...
У кого то есть библиотека реализации программного SPI интерфейса на avr?

Нужен именно программный, ибо аппаратный уже занят. Да и девайс разведен уже на на другие выводы Мк.

Заранее вам благодарен.
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
mempfis_
сообщение Oct 18 2009, 13:27
Сообщение #2


Профессионал
*****

Группа: Свой
Сообщений: 1 001
Регистрация: 27-06-06
Пользователь №: 18 409



Цитата(CIIAPTAK @ Oct 18 2009, 16:09) *
Нужен именно программный, ибо аппаратный уже занят. Да и девайс разведен уже на на другие выводы Мк.


Чтож там сложного то:

Код
#define HI(x) SPI_PORT |= (1<<(x))
#define LO(x) SPI_PORT &= ~(1<<(x))

unsigned int SPIWriteWord(unsigned int cmd) {
  unsigned char i;
  unsigned int recv;
  recv = 0;
  LO(SCK);
  LO(nSS);
  for(i=0; i<16; i++) {
    if(cmd&0x8000) HI(SDI); else LO(SDI);
    HI(SCK);
    recv<<=1;    
    if( SPI_PIN&(1<<SDO) ) {
      recv|=0x0001;
    }
    LO(SCK);
    cmd<<=1;
  }
  HI(nSS);
  return recv;
}


Обзовите где нибудь выводы SDI, SDO, SCK. Тут 16битный вариант, сли нужно код легко переделывается на 8 бит.
Go to the top of the page
 
+Quote Post
CIIAPTAK
сообщение Oct 18 2009, 13:59
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 27
Регистрация: 22-07-07
Пользователь №: 29 290



[quote name='mempfis_' date='Oct 18 2009, 17:27' post='663748']
Чтож там сложного то:

Код
#define HI(x) SPI_PORT |= (1<<(x))
#define LO(x) SPI_PORT &= ~(1<<(x))

unsigned int SPIWriteWord(unsigned int cmd) {
  unsigned char i;
  unsigned int recv;
  recv = 0;
  LO(SCK);
  LO(nSS);
  for(i=0; i<8; i++) {
    if(cmd&0x80) HI(SDI); else LO(SDI);
    HI(SCK);
    recv<<=1;    
    if( SPI_PIN&(1<<SDO) ) {
      recv|=0x0001;
    }
    LO(SCK);
    cmd<<=1;
  }
  HI(nSS);
  return recv;
}


Биг спс. Для 8 ми битного, правильно поправил? =)
Это на запись. А как на чтение? В случае двухстороннего обмена.

Сообщение отредактировал CIIAPTAK - Oct 18 2009, 14:05
Go to the top of the page
 
+Quote Post
prottoss
сообщение Oct 18 2009, 14:25
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(CIIAPTAK @ Oct 18 2009, 21:59) *
Это на запись. А как на чтение? В случае двухстороннего обмена.
Мда, тяжелый случайsmile.gif Так это оно и есть - загоняете в функцию байт для записи, автоматом функция вернула то, что прочитала.


--------------------
Go to the top of the page
 
+Quote Post
Xenia
сообщение Oct 18 2009, 15:04
Сообщение #5


Гуру
******

Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237



SPI куда элегантнее программировать на ассемблере, если аппаратно этого сделать по каким-то причинам нельзя. Элегантность заключена в том, что так можно эффективно использовать флаг переноса при сдвигах, строго выдержать меандр по времени (хотя последнее, обычно, не требуется) и сделать правильные задержки. На чистом С такое написать нельзя.
Здесь приведены сочиненные мной процедуры:
void Wr_Reg( char byte); // запись по SPI в регистр АЦП
char Rd_Reg( void); // чтение по SPI регистра АЦП
Вся остальная программа у меня на С, откуда я и вызываю функции Wr_Reg(byte) и Rd_Reg(). Их описание в хидере я только что привела, их тела на ассемблере выглядят так:
Код
        RSEG CODE:CODE:NOROOT(1)

        PUBLIC Wr_Reg
Wr_Reg:
        ldi R17, 8
LoopWrReg:
        sbi PORTD, SCLK; установим SCLK в 1
        rol R16; сдвигаем регистр
        brcs SetSDI
        cbi PORTD, SDI; SDI = 0
        rjmp CliSCLK; 2 clocks
SetSDI:
        sbi PORTD, SDI; SDI = 1
        nop; 1+1 clocks
        nop
CliSCLK:
        cbi PORTD, SCLK; установим SCLK в 0
        dec R17
        brne LoopWrReg; если не 0
        ret

        PUBLIC Rd_Reg
Rd_Reg:
        ldi R17, 8
        clr R16; обнуляем регистр
LoopRdReg:
        sbi PORTD, SCLK; установим SCLK в 1
        nop
        cbi PORTD, SCLK; установим SCLK в 0
        lsl R16; сдвигаем регистр
        sbic PIND, SDO; SDO ?
        ori R16, 1; устанавливаем мл.бит
        dec R17
        brne LoopRdReg; если не 0
        ret

Связь осуществляется через порт D, который можно заменить на любой другой. SDI, SDO и SCLK по назначению соответствуют MOSI, MISO и СLK.
Суть не меняется, если вместо АЦП будет какое-то другое устройство.
P.S. Проект на IAR EWAVR, в котором имеется один ассемблерный файл (этот), а остальные на C. Микроконтроллер ATtiny2313.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Oct 18 2009, 15:15
Сообщение #6


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(Xenia @ Oct 18 2009, 18:04) *

В тексте программы ничего нету про SDO. Поправьте, плз, чтоб студенты не ошибалисьsmile.gif
И еще (для страшных эстетов) - некая зависимость от тактовой частоты проца.
Go to the top of the page
 
+Quote Post
Xenia
сообщение Oct 18 2009, 15:37
Сообщение #7


Гуру
******

Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237



Цитата(_Pasha @ Oct 18 2009, 19:15) *
В тексте программы ничего нету про SDO. Поправьте, плз, чтоб студенты не ошибалисьsmile.gif


Поправила.

Цитата(_Pasha @ Oct 18 2009, 19:15) *
И еще (для страшных эстетов) - некая зависимость от тактовой частоты проца.


Да-да! Это очень важно! И вовсе не для эстетов. В ассеблерную процедеру есть возможноть натолкать столько nop (пустых операций), чтобы сделать любую дополнительную задержку. Это очень даже может понадобится тогда, когда МК работает на более высокой частоте кварца, чем необходимо, чтобы соблюсти требования ведомого устройства. И тут дело не только в частоте его кварца, сколько в технических требованиях к обмену. Это весьма типичная задача при работе с АЦП, в даташите которых расписаны тайминги на SPI обмен.
Ассемблер очень хорош как раз для соблюдения всех этих таймингов и латентного времени между передачей команды и приемом данных. Однако смысл имеет писать на ассемблере только такую интерфейсную часть программы. Полностью переходить на ассемлер не советую - ошибки на нем совершаются гораздо чаще, чем на C, и программировать на нем медленнее.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Oct 18 2009, 15:56
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(Xenia @ Oct 18 2009, 23:37) *
Вот мой вариант софтового/железного SPI, с задержками без всякого ассемблера.
Код
/*****************************************************************************
Обмен данными по SPI
записывает в SPI порт данные wr_data и возвращает прочитанные при обмене данные
******************************************************************************/
UCHAR ExSPI(UCHAR wr_data)
{    
      // проверяем джампер low_sck
      if(ISP_PIN & (1 << PIN_LOW_SCK)) // не замкнут, аппаратный SPI
    {    
          SPI_ON();    // включаем SPI
          SPDR = wr_data;    // загружаем SPI данными
        while(!(SPSR & (1<<SPIF))){};    // ждем окончания передачи
        return SPDR;    // возвращаем принятые данные
    }
    else // иначе софтверный SPI
    {    
          UCHAR rd_data;
        SPI_OFF();    // выключаем аппаратный SPI
          for(UCHAR i = 0; i < 8; i++)
        {    
              // отправляем старший бит отправляемого байта
              if(0 != (wr_data & 0x80))
                ISP_PORT |= (1 << PIN_MOSI); // = 1
            else
                ISP_PORT &= ~(1 << PIN_MOSI);    // = 0

            // подготавливаем следующий бит
            wr_data <<=1;

            // принимаем очередной (начиная со старшего) бит
            // принимаемого байта
            rd_data <<= 1;
            if(0 != (ISP_PIN & (1 << PIN_MISO)))
                rd_data++; // устанавливаем единичный бит, если высокий принимаемый уровень

            // формируем импульс на выводе SCK МК
            ISP_PORT |= (1 << PIN_SCK);    // высокий
            __delay_cycles(LOW_SCK_DELEY); // задержка
            ISP_PORT &= ~(1 << PIN_SCK);    // низкий
            __delay_cycles(LOW_SCK_DELEY); // задержка
        }

        return rd_data;
    }
}


--------------------
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- CIIAPTAK   Программный SPI   Oct 18 2009, 13:09
||- - zltigo   Цитата(Xenia @ Oct 18 2009, 18:04) SPI ку...   Oct 18 2009, 15:45
||- - Xenia   Цитата(zltigo @ Oct 18 2009, 19:45) А отк...   Oct 18 2009, 16:06
||- - zltigo   Цитата(Xenia @ Oct 18 2009, 19:03) Я не д...   Oct 18 2009, 16:08
||- - Xenia   Цитата(zltigo @ Oct 18 2009, 20:08) Я же ...   Oct 18 2009, 16:27
||- - zltigo   Цитата(Xenia @ Oct 18 2009, 19:27) У вас ...   Oct 18 2009, 16:41
||- - _Pasha   Цитата(Xenia @ Oct 18 2009, 19:27) Язык д...   Oct 18 2009, 16:56
||- - ReAl   Цитата(Xenia @ Oct 18 2009, 19:27) У вас ...   Oct 18 2009, 18:22
|- - mempfis_   КодБиг спс. Для 8 ми битного, правильно поправил? ...   Oct 19 2009, 07:13
- - Rst7   Кстати, как по мне, все это очень медленно Если и...   Oct 18 2009, 18:30
|- - Xenia   Цитата(Rst7 @ Oct 18 2009, 22:30) Кстати,...   Oct 18 2009, 19:15
- - Rst7   ЦитатаТак и я о том, Причем тут "и я"? ...   Oct 18 2009, 21:17


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 30th July 2025 - 06:07
Рейтинг@Mail.ru


Страница сгенерированна за 0.01491 секунд с 7
ELECTRONIX ©2004-2016