|
Программный SPI, реализация на avr |
|
|
|
 |
Ответов
|
Oct 18 2009, 13:27
|

Профессионал
    
Группа: Свой
Сообщений: 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 бит.
|
|
|
|
|
Oct 18 2009, 13:59
|

Участник

Группа: Участник
Сообщений: 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
|
|
|
|
|
Oct 18 2009, 15:04
|

Гуру
     
Группа: Модератор 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.
|
|
|
|
|
Oct 18 2009, 15:37
|

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

|
Цитата(_Pasha @ Oct 18 2009, 19:15)  В тексте программы ничего нету про SDO. Поправьте, плз, чтоб студенты не ошибались  Поправила. Цитата(_Pasha @ Oct 18 2009, 19:15)  И еще (для страшных эстетов) - некая зависимость от тактовой частоты проца. Да-да! Это очень важно! И вовсе не для эстетов. В ассеблерную процедеру есть возможноть натолкать столько nop (пустых операций), чтобы сделать любую дополнительную задержку. Это очень даже может понадобится тогда, когда МК работает на более высокой частоте кварца, чем необходимо, чтобы соблюсти требования ведомого устройства. И тут дело не только в частоте его кварца, сколько в технических требованиях к обмену. Это весьма типичная задача при работе с АЦП, в даташите которых расписаны тайминги на SPI обмен. Ассемблер очень хорош как раз для соблюдения всех этих таймингов и латентного времени между передачей команды и приемом данных. Однако смысл имеет писать на ассемблере только такую интерфейсную часть программы. Полностью переходить на ассемлер не советую - ошибки на нем совершаются гораздо чаще, чем на C, и программировать на нем медленнее.
|
|
|
|
Сообщений в этой теме
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
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|