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

 
 
> Готовность SPI, как определить?
777777
сообщение May 20 2008, 08:00
Сообщение #1


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

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



Как определить, что в SPDR можно писать очередной байт? SPIF устанавливается после передачи, но после обработки сбрасывается, и при включении там 0. А есть ли какой бит, по которому можно определить, что передача в данный момент не идет? Т.е. который устанавливается сразу после записи в SPDR?
Go to the top of the page
 
+Quote Post
3 страниц V  < 1 2 3 >  
Start new topic
Ответов (15 - 29)
singlskv
сообщение May 20 2008, 21:59
Сообщение #16


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(Qwertty @ May 21 2008, 01:50) *
Про это выше написано - холостая посылка, только для взвода SPIF. Просто записать в SPDR что попало, при неактивных cs. Я пишу сразу после настройки SPI. Далее примерно так:
Спасибо, теперь понял о чем речь, просто для меня такой
вариант не очень применим, поэтому и не мог никак въехать про какую такую
холостую посылку речь.
Go to the top of the page
 
+Quote Post
=GM=
сообщение May 21 2008, 12:00
Сообщение #17


Ambidexter
*****

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



Цитата(Qwertty @ May 20 2008, 18:36) *
Я делаю с передачей холостого байта при неактивном /cs. Положил в SPDR и пошел готовить следующие данные. Как обойтись без холостой записи, надеюсь, подскажет GM

Рецепта на все случаи нет, чуть позже могу показать один вариант, щас немного занят буду. А для разгона покажите код, где вы выводите данные по эспиай. Вы по прерываниям выводите или по готовности?


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
Maik-vs
сообщение May 21 2008, 12:49
Сообщение #18


Местный
***

Группа: Участник
Сообщений: 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 взводится по концу передачи байта. Не понимаю, в чём проблема у топикстартера - можно работать в прерывании, можно - опрашивая флаг, как всегда...
Go to the top of the page
 
+Quote Post
=GM=
сообщение May 22 2008, 17:08
Сообщение #19


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


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
ILYAUL
сообщение May 22 2008, 17:19
Сообщение #20


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

Группа: Свой
Сообщений: 1 940
Регистрация: 16-12-07
Из: Москва
Пользователь №: 33 339



Не очень понял зачем SREG сохранять


--------------------
Закон Мерфи:

Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
Go to the top of the page
 
+Quote Post
=GM=
сообщение May 22 2008, 21:29
Сообщение #21


Ambidexter
*****

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



Команда cpi портит флаги в прерывании.


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
singlskv
сообщение May 22 2008, 21:53
Сообщение #22


дятел
*****

Группа: Свой
Сообщений: 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)
самым большим тормозом становится время входа/выхода в прерывание
Go to the top of the page
 
+Quote Post
=GM=
сообщение May 22 2008, 23:09
Сообщение #23


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МЦ. Так что прерывания будут идти практически непрерывно и проверять ничего не надо (:-).

Кстати, в вашем фрагменте снимать флаг прерывания в конце транзакции совсем не обязательно.


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
singlskv
сообщение May 23 2008, 18:46
Сообщение #24


дятел
*****

Группа: Свой
Сообщений: 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.
Цитата
Кстати, в вашем фрагменте снимать флаг прерывания в конце транзакции совсем не обязательно.

А вот этот вопрос для меня остается загадкой, дело в том что железки на которой работает этот
код я никогда не видел 07.gif
более того, в моем коде такие куски повторяются несколько раз подряд,
те байтики шлются непрерывно(4 штуки)
ну и первоначально предполагалось войти в прерывание и принять 4 байта, а при
этом сброс флага обязателен.
Ну и в конечном итоге чтение SPSR заменяет всего-лишь еще один "nop" smile.gif
Потом концепция чуть изменилась, НО, я на самом деле не знаю нужно ли читать SPSR
для запуска новой передачи, даташит на этот счет молчит а натурных испытаний не
попалось....

Да, еще добавлю на всякий случай, вход в прерывание для SPI есть суть
чтение SPSR с сбросом SPIF.
Go to the top of the page
 
+Quote Post
defunct
сообщение May 23 2008, 19:15
Сообщение #25


кекс
******

Группа: Свой
Сообщений: 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
Go to the top of the page
 
+Quote Post
singlskv
сообщение May 23 2008, 19:34
Сообщение #26


дятел
*****

Группа: Свой
Сообщений: 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
Несомненно это хак, но разьве такие варианты не украшают нашу работу ?
Ну а если действительно присмотреться, объясните чем Ваш вариант с макросом надежнее
чем просто вызов в нужное место ?
повторный вход в любом случае Вы не обеспечили....
Go to the top of the page
 
+Quote Post
defunct
сообщение May 23 2008, 22:24
Сообщение #27


кекс
******

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



Цитата(singlskv @ May 23 2008, 22:34) *
Ну а если действительно присмотреться, объясните чем Ваш вариант с макросом надежнее
чем просто вызов в нужное место ?
повторный вход в любом случае Вы не обеспечили....

1. он быстрее (меньше тактов занимает).
2. не использует RETI не по месту (определяющее по надежности отличие)
Go to the top of the page
 
+Quote Post
=GM=
сообщение May 24 2008, 00:25
Сообщение #28


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

В железе не проверял, но вроде должно работать.


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
Qwertty
сообщение Nov 13 2008, 16:47
Сообщение #29


Местный
***

Группа: Свой
Сообщений: 408
Регистрация: 21-10-06
Из: Санкт-Петербург
Пользователь №: 21 527



Отпишусь тут. Сегодня помучал SPI. Узнал много нового smile.gif
Не ждать готовности 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 очень полезный флаг....
Go to the top of the page
 
+Quote Post
Maik-vs
сообщение Nov 13 2008, 19:45
Сообщение #30


Местный
***

Группа: Участник
Сообщений: 246
Регистрация: 4-12-06
Пользователь №: 23 101



Цитата(Qwertty @ Nov 13 2008, 19:47) *
Отпишусь тут. Сегодня помучал SPI. Узнал много нового smile.gif
Не ждать готовности SPI можно.
Код
void    SpiMasterTx(uint8_t data)
{
do
  {
   SPDR = data;
  }
  while(SPSR & (1<<WCOL));
}

Такая конструкция оказалась вполне работоспособной. То что писал Maik-vs в 4 сообщении этой темы не подтвердилось - данные в SPDR не портятся. Симулятор студии и реальный осциллограф также это подтверждают.

М-да. Оказывается, "while" теперь переводится "не ждать"... lol.gif
Где я писал, что портятся данные в SPDR? Они НЕ ПЕРЕДАЮТСЯ, если запись в SPDR произошла в течение передачи. Это коллизия называется. А Вы фигачите байт в SPDR пока передача не закончится и с нею коллизия стало быть тоже. Хотя в 6-м посте пеклись, как бы "записать SPDR и продолжить заниматься другими делами." wacko.gif
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 21st July 2025 - 03:02
Рейтинг@Mail.ru


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