|
Готовность SPI, как определить? |
|
|
|
 |
Ответов
(15 - 29)
|
May 20 2008, 21:59
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(Qwertty @ May 21 2008, 01:50)  Про это выше написано - холостая посылка, только для взвода SPIF. Просто записать в SPDR что попало, при неактивных cs. Я пишу сразу после настройки SPI. Далее примерно так: Спасибо, теперь понял о чем речь, просто для меня такой вариант не очень применим, поэтому и не мог никак въехать про какую такую холостую посылку речь.
|
|
|
|
|
May 21 2008, 12:49
|
Местный
  
Группа: Участник
Сообщений: 246
Регистрация: 4-12-06
Пользователь №: 23 101

|
Цитата(=GM= @ May 20 2008, 17:41)  Откуда вы взяли про 34 цикла, ссылочкой не поделитесь? И что такое SPCR=0x50, в нём вроде используются только 0, 6 и 7 биты? Ссылочкой не поделюсь, т.к. 34 - число, добытое честным экспериментом. Для SPCR=0x50: SPE и MSTR, остальные биты =0, т.е. коэффициент деления 1. Для других коэффициентов, наверное, не 34, поэтому и привёл значение SPCR. AVR Studio это дело симулирует правильно: если между "out SPDR" 34 цикла, передаются байты с промежуткосм в 1 бит. Если меньше - стробы есть, а на линии данных стоит высокий уровеь. Это видел в осциллографе. Частота кварца 20 МГц, МК mega16. Да, разумеется, SPIF взводится по концу передачи байта. Не понимаю, в чём проблема у топикстартера - можно работать в прерывании, можно - опрашивая флаг, как всегда...
|
|
|
|
|
May 22 2008, 17:08
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
Цитата(Qwertty @ May 20 2008, 18:36)  Я делаю с передачей холостого байта при неактивном /cs. Положил в SPDR и пошел готовить следующие данные. Как обойтись без холостой записи надеюсь подскажет GM Подсказываю, вот так, например, можно делать обмен по спи по прерываниям Код spistc: in temp3,spdr ; st x+,temp3 ; spist1: in tmpsta,SREG ; cpi xl,low(eobuf)+1 ;end of buffer? breq spist2 ;yes, it is ld temp3,x ;send current out spdr,temp3 ;byte spist2: out SREG,tmpsta ; reti Принятые байты замещают в буфере переданные. Инициируется обмен вызовом rcall spist1
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
May 22 2008, 21:53
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(=GM= @ May 22 2008, 21:08)  Подсказываю, вот так, например, можно делать обмен по спи по прерываниям Код spistc: in temp3,spdr ; st x+,temp3 ; spist1: in tmpsta,SREG ; cpi xl,low(eobuf)+1 ;end of buffer? breq spist2 ;yes, it is ld temp3,x ;send current out spdr,temp3 ;byte spist2: out SREG,tmpsta ; reti Принятые байты замещают в буфере переданные. Инициируется обмен вызовом rcall spist1 Повторное использование кода(начало посылки через rcall spist1) выглядит красиво. Но к сожалению на С неприменимо, нужно писать отдельно старт транзакции. Ну и для максимума скорости, ИМХО, такое прерывание не очень, при выборе SPI2X(Focs/2) самым большим тормозом становится время входа/выхода в прерывание
|
|
|
|
|
May 22 2008, 23:09
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
Цитата(singlskv @ May 22 2008, 20:53)  Повторное использование кода (начало посылки через rcall spist1) выглядит красиво Спасибо, не бог весть что, конечно, но это я сам придумал. Я бы сказал, что это не повторное использование, а именно запуск передачи пакета байт из буфера. Цитата(singlskv @ May 22 2008, 20:53)  Но к сожалению на С неприменимо, нужно писать отдельно старт транзакции На си можно попробовать задействовать оператор свич на две позиции. Цитата(singlskv @ May 22 2008, 20:53)  Ну и для максимума скорости, такое прерывание не очень, при выборе SPI2X(Focs/2) самым большим тормозом становится время входа/выхода в прерывание Да вроде нет, тело прерывания выполняется максимум за 14МЦ + 6-7 на вход, всего 20-21, а на передачу одного байта по спи на максимальной скорости Fclk/2 требуется минимум 17МЦ. И небольшое увеличение времени передачи пакета окупается большим ПЛЮСОМ: положили данные в буфер, толкнули обмен, занялись другими делами, прошло некое время, проверили указатель буфера, забрали принятые данные и всё. А если не требуется приёма данных, то на прерывание потребуется 17-18МЦ. Так что прерывания будут идти практически непрерывно и проверять ничего не надо (:-). Кстати, в вашем фрагменте снимать флаг прерывания в конце транзакции совсем не обязательно.
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
May 23 2008, 18:46
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(=GM= @ May 23 2008, 03:09)  Спасибо, не бог весть что, конечно, но это я сам придумал. Я бы сказал, что это не повторное использование, а именно запуск передачи пакета байт из буфера. Ну здесь как раз понравилось именно повторное использование, такой запуск вполне стандартен и понятен, но вот то что это удалось красиво вписать прямо в код прерывания.... Цитата На си можно попробовать задействовать оператор свич на две позиции. к сожалению оверхед который при этом будет на С убивает саму идею. Цитата Да вроде нет, тело прерывания выполняется максимум за 14МЦ + 6-7 на вход, всего 20-21, а на передачу одного байта по спи на максимальной скорости Fclk/2 требуется минимум 17МЦ. Я не очень точно выразился говоря про вход/выход из прерывания, то есть вход/выход это первопричина а в сумме на производительность будет больше всего влиять разница в тактах между: in temp3,spdr ; ...... out spdr,temp3 ;byte для Вашего варианта, при непрерывном трансфере большого куска, на передачу одного байта будет >20-21 тактов Цитата И небольшое увеличение времени передачи пакета окупается большим ПЛЮСОМ: положили данные в буфер, толкнули обмен, занялись другими делами, прошло некое время, проверили указатель буфера, забрали принятые данные и всё. А если не требуется приёма данных, то на прерывание потребуется 17-18МЦ. Так что прерывания будут идти практически непрерывно и проверять ничего не надо (:-). Для "общих" случаев обмена по SPI Ваш вариант видимо практически идеален... Для частных, большой вопрос, тот кусочек кода который я привел был частным случаем, я его привел только для того чтобы показать сколько ТОЧНО длится передача по SPI. Цитата Кстати, в вашем фрагменте снимать флаг прерывания в конце транзакции совсем не обязательно. А вот этот вопрос для меня остается загадкой, дело в том что железки на которой работает этот код я никогда не видел более того, в моем коде такие куски повторяются несколько раз подряд, те байтики шлются непрерывно(4 штуки) ну и первоначально предполагалось войти в прерывание и принять 4 байта, а при этом сброс флага обязателен. Ну и в конечном итоге чтение SPSR заменяет всего-лишь еще один "nop"  Потом концепция чуть изменилась, НО, я на самом деле не знаю нужно ли читать SPSR для запуска новой передачи, даташит на этот счет молчит а натурных испытаний не попалось.... Да, еще добавлю на всякий случай, вход в прерывание для SPI есть суть чтение SPSR с сбросом SPIF.
|
|
|
|
|
May 23 2008, 19:15
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(singlskv @ May 23 2008, 21:46)  Ну здесь как раз понравилось именно повторное использование, такой запуск вполне стандартен и понятен, но вот то что это удалось красиво вписать прямо в код прерывания.... Что делает такой вызов небезопасным. Это хак и ничего красивого в этом нет. разве такой старт был бы чем-то хуже? Код .macro StartSpiTransfer ld temp3,x;send current out spdr,temp3;byte .end macro
|
|
|
|
|
May 23 2008, 19:34
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(defunct @ May 23 2008, 23:15)  Что делает такой вызов небезопасным. Это хак и ничего красивого в этом нет. разве такой старт был бы чем-то хуже? Код .macro StartSpiTransfer ld temp3,x;send current out spdr,temp3;byte .end macro Несомненно это хак, но разьве такие варианты не украшают нашу работу ? Ну а если действительно присмотреться, объясните чем Ваш вариант с макросом надежнее чем просто вызов в нужное место ? повторный вход в любом случае Вы не обеспечили....
|
|
|
|
|
May 24 2008, 00:25
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
Цитата(singlskv @ May 23 2008, 17:46)  Для частных, большой вопрос, тот кусочек кода который я привел был частным случаем, я его привел только для того чтобы показать сколько ТОЧНО длится передача по SPI Ну вот, родил специально для вашего частного случая Код ;Обмен данными по SPI на максимальной скорости Fclk/2 spist1: in temp1,spdr ;принятый байт spistc: out spdr,temp2 ;передадим текущий байт st x+,temp1 ;запомним принятый байт andi xl,0x10 ;коррекция указателя ld temp2,x ;прочитаем nop ;следующий байт nop ;из циклического nop ;буфера nop ;период выдачи nop ;байт на Fclk/2 nop ;должен быть nop ;18 МЦ, необходимо nop ;проверить dec bcounter ;все байты? brne spist1 ;нет ret Здесь две особенности, первая то, что работает точно на Fclk/2, вторая - используется циклический буфер на 16 байт (можно настроить на любой размер кратный степени 2), поэтому не надо задумываться, куда писать или откуда читать. Надо только зарядить bcounter<16 и использовать для чтения из буфера команду ld temp1,-x. Немного непривычно, но когда освоишься, получается компактный код. Можно и нулём останавливать передачу, место есть... Вызов, как предложил defunct Код ld temp2,x rcall spistc В железе не проверял, но вроде должно работать.
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Nov 13 2008, 16:47
|
Местный
  
Группа: Свой
Сообщений: 408
Регистрация: 21-10-06
Из: Санкт-Петербург
Пользователь №: 21 527

|
Отпишусь тут. Сегодня помучал SPI. Узнал много нового  Не ждать готовности SPI можно. Код void SpiMasterTx(uint8_t data) { do { SPDR = data; } while(SPSR & (1<<WCOL)); } Такая конструкция оказалась вполне работоспособной. То что писал Maik-vs в 4 сообщении этой темы не подтвердилось - данные в SPDR не портятся. Симулятор студии и реальный осциллограф также это подтверждают. Ждать приходится только при чтении: Код uint8_t SpiMasterTxRx(uint8_t data) { do { SPDR = data; } while(SPSR & (1<<WCOL)); while(!(SPSR & (1<<SPIF))); return SPDR; } Оказывается WCOL очень полезный флаг....
|
|
|
|
|
Nov 13 2008, 19:45
|
Местный
  
Группа: Участник
Сообщений: 246
Регистрация: 4-12-06
Пользователь №: 23 101

|
Цитата(Qwertty @ Nov 13 2008, 19:47)  Отпишусь тут. Сегодня помучал SPI. Узнал много нового  Не ждать готовности SPI можно. Код void SpiMasterTx(uint8_t data) { do { SPDR = data; } while(SPSR & (1<<WCOL)); } Такая конструкция оказалась вполне работоспособной. То что писал Maik-vs в 4 сообщении этой темы не подтвердилось - данные в SPDR не портятся. Симулятор студии и реальный осциллограф также это подтверждают. М-да. Оказывается, "while" теперь переводится "не ждать"... Где я писал, что портятся данные в SPDR? Они НЕ ПЕРЕДАЮТСЯ, если запись в SPDR произошла в течение передачи. Это коллизия называется. А Вы фигачите байт в SPDR пока передача не закончится и с нею коллизия стало быть тоже. Хотя в 6-м посте пеклись, как бы "записать SPDR и продолжить заниматься другими делами."
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|