Обсуждаем контроллеры компании Atmel.
Ответить

Re: Вопрос по SPI на asm

Вт сен 06, 2016 16:46:13

Всем спасибо, за участие... много интересного узнал... следующий этап - реализация в железе, но это другая история...

Re: Вопрос по SPI на asm

Вт сен 06, 2016 17:22:47

roman.com писал(а):-измерил датчик 1
-обработал данные
-закинул в SPI... SPI автоматом передает. А я измеряю следующие датчики...
...
-измерил датчик N
-обработал данные
-закинул в SPI... SPI автоматом передает. А я измеряю следующие датчики...

То есть, если у Вас 10 одинаковых датчиков, Вы линейно 10 раз повторите код опроса датчика, код обработки данных и код передачи по SPI?
Вопросов больше не имею...

Re: Вопрос по SPI на asm

Вт сен 06, 2016 17:59:14

:)))
Нет, в цикле.

N++; // где N - номер датчика.

Хотя... кому как больше нравится))

Re: Вопрос по SPI на asm

Ср сен 07, 2016 04:33:45

Alkul писал(а):То есть, если у Вас 10 одинаковых датчиков, Вы линейно 10 раз повторите код
roman.com писал(а):Нет, в цикле.

Тогда у Вас проблемы с терминологией.
Вы сами написали:
roman.com писал(а):Ну и нафига эта мне головная боль с подпрограммами при линейном алгоритме?

По определению, линейный алгоритм - это алгоритм, не содержащий циклов и ветвлений.

Re: Вопрос по SPI на asm

Ср сен 07, 2016 10:25:51

Видимо меня не так поняли... ))

Alkul писал(а):Тогда у Вас проблемы с терминологией.

У меня нет проблем с терминологией. Я попытался ответить на вопрос vit007
vit007 писал(а):Значит аппаратный SPI работает параллельно программе, может поэтому и надо ждать появления флаг, а то как понять когда собирать данный со слейва...

Я показал на примере линейного алгоритма как понять когда собирать данный со слейва.

Затем Вы меня спросили
Alkul писал(а):То есть, если у Вас 10 одинаковых датчиков, Вы линейно 10 раз повторите код опроса датчика, код обработки данных и код передачи по SPI?

Т.е. я так понял Вы меня спросили: буду ли я использовать в своей программе линейный алгоритм? Я Вам ответил - нет. Если мне нужно будет измерить 10 датчиков и отправить 10 байт на индикатор, то я для этого использую цикл.

А Вы, как я понял, для того что бы измерить 10 датчиков и отправить 10 байт на индикатор, предлагаете использовать подпрограмму ?))

Re: Вопрос по SPI на asm

Ср сен 07, 2016 18:27:11

roman.com писал(а):Т.е. я так понял Вы меня спросили: буду ли я использовать в своей программе линейный алгоритм? Я Вам ответил - нет. Если мне нужно будет измерить 10 датчиков и отправить 10 байт на индикатор, то я для этого использую цикл.

Хм-м... Перечитайте еще раз свое сообщение
Вы сказали:
roman.com писал(а):А если у меня простой линейный алгоритм? Например есть куча датчиков, их надо вывести на экран...

То есть, у вас опрос "кучи датчиков" делается в линейном алгоритме? Я читаю, как написано. Если и есть проблемы, то это не у меня с пониманием, а у Вас с изложением.

roman.com писал(а):А Вы, как я понял, для того что бы измерить 10 датчиков и отправить 10 байт на индикатор, предлагаете использовать подпрограмму ?))

Именно так. Подпрограмма опроса датчика, подпрограмма отправки данных на индикатор. Если участок кода используется в программе более одного раза, имеет смысл выделить его в подпрограмму.
Надо уметь видеть в программе главное и вспомогательное. Главное - это общий алгоритм. Если Вы загромождаете второстепенными действиями основную часть алгоритма, Вы, во-первых, делаете его менее читаемым. То есть, усложняете себе же программирование. Во-вторых, очень удобно делать отладку кода, двигаясь от простого к сложному. Когда простейшая подпрограмма отлажена, ничто не мешает включить её в более сложную.
Вы сказали
предлагаете использовать подпрограмму ?

так, как будто для этого нужно письменный запрос в Atmel подавать. Уверяю Вас, использование команд CALL/RCALL - RET совершенно бесплатное. И механизм подпрограмм более гибок, чем механизм циклов.

Под спойлером пример работы с датчиком DS18S20. В моей программе это работает так - в нужный момент датчику посылается команда начать измерения. Таймер по прерываниям отсчитывает 2-ух миллисекундные квантили времени. Когда с момента посылки команды начать измерения проходит время, необходимое датчику на выполнение преобразования, в обработчике прерывания таймера устанавливается бит, означающий необходимость выполнить чтение результата измерения. В основной программе циклически проверяется этот бит, и если он установлен, то вызывается подпрограмма TERMO_READ. Посмотрите код, он гораздо читабельней, чем если бы все свалить в одну кучу.
Спойлер
Код:
;Подпрограмма, выполняющая однократный опрос термодатчика и занесение полученных значений температуры
;в память (переменные DS1L:DS1H)
TERMO_READ:
   rcall DS1RESET      ;Сброс термодатчика
   brtc TERMO_R1      ;Если бит T сброшен (нет ошибки датчика), то перейти на TERMO_R1

   rjmp TERMOERR      ;Ошибка термодатчика, индицировать символы ошибки и отключить нагрев

TERMO_R1:   
   ldi BYTEDS,$CC      ;Код команды обращения к датчику без указания его 64-битного адреса
   rcall DS1WRITE      ;Занести команду в термодатчик
   ldi BYTEDS,$BE      ;Код команды чтения 9 байт из памяти датчика
   rcall DS1WRITE      ;Занести команду в термодатчик
   clr R16         ;Обнулить ячейку, хранящую значение CRC
   sts CRC8,R16      ;перед расчетом CRC для принятого пакета байт
   rcall DS1READ      ;Прочитать нулевой байт из памяти термодатчика (Temperature LSB)
   rcall CRC_8      ;Вычислить CRC для нулевого байта
   sts DS1L,BYTEDS      ;Занести прочитанный младший байт температуры в ячейку DS1L
   rcall DS1READ      ;Прочитать первый байт из памяти термодатчика (Temperature MSB)
   rcall CRC_8      ;Вычислить CRC для первого байта
   sts DS1H,BYTEDS      ;Занести прочитанный старший байт температуры в ячейку DS1H
   ldi R16,0x07      ;Организовать цикл для чтения оставшихся семи байт памяти термодатчика
   mov R14,R16      ;
TERMO_R2:   rcall DS1READ      ;Прочитать байт из памяти термодатчика
   rcall CRC_8      ;Вычислить CRC для прочитанного байта
   dec R14         ;Декремент счетчика прочитанных байт
   brne TERMO_R2      ;Если прочитаны не все байты, вернуться на метку TERMO_R2

   mov R16,STAT2      ;Загрузить в рег.R16 значение байта STAT2
   andi R16,~((1<<TIMEDS)|(1<<DSCONV)|(1<<DSREAD))   ;Так как опрос термодатчика выполнен,
            ;сбросить все биты, относящиеся к измерению температуры
   mov STAT2,R16      ;Сохранить в памяти новое значение байта STAT2
   
   lds R16,CRC8      ;Занести в рег.R16 рассчитанную для 9-ти байтного пакета CRC
   tst R16         ;Если пакет принят корректно, то расчет CRC для байта CRC должен дать нуль
   brne TERMOERR      ;Если результат расчета не нуль, то пакет принят с ошибкой, перейти на метку TERMOERR
   rcall TEMPSYMB      ;Иначе пакет принят корректно, вызвать подпрограмму, проверяющую необходимость
            ;включения нагреватели и подготавливающую значения для индикации температуры    
   ret         ;


;Подпрограмма формирования RESET для интерфейса 1-Wire и чтения ответа датчика PRESENCE PULSE
;Если термодатчик не ответил, подпрограмма установит бит T
DS1RESET:   cli         ;Запретить прерывания для неразрывности формирования RESET
   sbi DSDDR,DS1      ;Перевод вывода на передачу
   cbi DSPORT,DS1      ;Сброс выхода в ноль, формирование Trstl
   rcall DEL05MS      ;Задержка 500 мкс
   cbi DSDDR,DS1      ;Перевод вывода на прием
   sbi DSPORT,DS1      ;и ожидание ответа датчика "Presence pulse"
   rcall DEL10MK      ;Задержка 10 мк
   rcall DEL10MK      ;Задержка 10 мк

   ldi R24,$A0      ;Цикл для непрерывного чтения данных в течение 100 мкс
            ;если ответа нет, то ошибка
DS1RES_L:   dec R24         ;
   breq DS1RES_ERR      ;Если цикл непрерывного чтения завершен, то ошибка
   sbic DSPIN,DS1      ;Проверка состояния на шине данных от термодатчика
   rjmp DS1RES_L      ;если 1, то ответа датчика пока нет, возврат на ожидание
   clt         ;Иначе на линии 0, ответ датчика получен, сбросить бит Т
   rcall DEL05MS      ;Задержка 500 мкс
   bld STATUS,DSFAIL_ST   ;Сбросить бит DSFAIL_STв байте STATUS, т.к. термодатчик исправен
DS1RES_1:   sei         ;Неразрывный процесс окончен, разрешить прерывания
   ret         ;
DS1RES_ERR:
   set         ;Термодатчик не ответил, установить бит Т
   bld STATUS,DSFAIL_ST   ;Установить бит DSFAIL_STв байте STATUS, т.к. термодатчик неисправен
   rjmp DS1RES_1      ;Переход для разрешения прерываний и завершения подпрограммы


;Подпрограмма чтения одного байта данных для интерфейса 1-Wire, результат возвращается в регистре BYTEDS
DS1READ:   cli         ;Запретить прерывания для неразрывности цикла чтения байта
   ldi R24,8         ;В рег.R24 счетчик принятых бит
DS1READ2:   cbi DSPORT,DS1      ;Сброс выхода в 0, формирование Trdv
   sbi DSDDR,DS1      ;Переключение вывода на передачу
   rcall DEL2MK7      ;Задержка 2,7мкс
   cbi DSDDR,DS1      ;Переключение вывода на приём
   sbi DSPORT,DS1      ;Резистор подтяжки линии к питанию включен
   rcall DEL10MK      ;Задержка 10мкс
   clc         ;Сбросить бит С перед проверкой состояния линии
   sbic DSPIN,DS1      ;Если на линии лог.0, то пропустить следующую команду
DS1BIN:   sec         ;Иначе на линии лог.1, установить бит С
   ror BYTEDS      ;Сдвинуть бит С в регистр результата
DS1DELAY:   rcall DEL60MK      ;Задержка 60мкс
   dec R24         ;Декремент счетчика принятых бит
   brne DS1READ2      ;Если счетчик принятых бит не равен 0, то возврат для приёма следующего бита
   rjmp DS1RES_1      ;Иначе байт принят, переход для разрешения прерываний и завершения подпрограммы


;Подпрограмма записи одного байта данных для интерфейса 1-Wire, байт для отправки должен находится в BYTEDS
DS1WRITE:   cli         ;Запретить прерывания для неразрывности цикла записи байта
   ldi R24,8         ;В рег.R24 счетчик отправленных бит
DS1COMP:   cbi DSPORT,DS1      ;Сброс выхода в ноль, формирование Tlow1
   sbi DSDDR,DS1      ;Переключение выхода на передачу
   rcall DEL2MK7      ;Задержка 2,7мкс
   ror BYTEDS      ;Отправка байта происходит младшим битом вперед
   brcc DS1WR0      ;Проверка бита С на 0. Если бит С равен нулю, отправляемый бит - нуль,
            ;переход на DS1WR0
   sbi DSPORT,DS1      ;Иначе отправляемый бит - единица
DS1WR0:   rcall DEL60MK      ;Задержка 60мкс
   sbi DSPORT,DS1      ;Установка строгой "1" на 2 мкс
   rcall DEL2MK7      ;Задержка 2,7мкс
   dec R24         ;Декремент счетчика отправленных бит
   brne DS1COMP      ;Если отправлены не все биты, вернуться на DS1COMP
   cbi DSDDR,DS1      ;Иначе все биты переданы,линию данных - в состояние входа, резистор подтяжки
            ;обеспечит лог.1 на линии данных
   rjmp DS1RES_1      ;Переход для разрешения прерываний и завершения подпрограммы

Главное достоинство такого подхода в том, что если в дальнейшем мне понадобиться в другом проекте работать с таким же датчиком, я скопирую эти, уже отлаженные мной подпрограммы в новый проект и там мне не понадобиться тратить время на отладку этой части программы. А можно вообще *.inc файл создать и как библиотеку подключать в других проектах.

Re: Вопрос по SPI на asm

Чт сен 08, 2016 00:22:17

Всё что Вы тут написали, именно так я и делаю. И так делают все.)) У меня куча подпрограмм под разные аппаратные/программные интерфейсы.. индикаторы.. датчики... фильтры... контрольные суммы CRC-8/16/32... и т.д. и т.п... Я так же как и все копирую отлаженные мной подпрограммы в новый проект. В основной программе вызываю нужную мне подпрограмму... можно по таймеру (в обработчике прерывания таймера что-то делаю)... можно по событию (ввод/вывод МК)... и т.д. и т.п. У меня всё как у всех))

)) Вообщето изначально был вопрос про SPI интерфейс. Человек не может разобраться как работает SPI интерфейс...
vit007 писал(а):Значит аппаратный SPI работает параллельно программе?

vit007 писал(а):это правда, что предмет плохо знаю...

А Вы, вместо того чтобы "на пальцах" объснить человеку как работает SPI интерфейс, начали рассказывать про оптимизацию алгоритма)) vit007 надо было просто почитать даташит и в протеусе поиграться с настройками и просто разобраться с SPI интерфейсом))
vit007 писал(а):Всем спасибо, за участие... много интересного узнал... следующий этап - реализация в железе, но это другая история...
Пожалуйста)) Вообщем с SPI интерфейсом разобрались... переходим на следующий этап))

Re: Вопрос по SPI на asm

Ср окт 24, 2018 19:58:46

Эмулирую работу SPI в Proteus.
SPI-debugger работает в режиме монитора и корректно отслеживает передаваемые по линии SPI данные.
Но не пойму, что за знаки вопросов я вижу в окне дебаггера? (обведены зелёным).
Изображение Изображение

Чё за импульзы я вижу на осциллограмме на линии MOSI перед передачей данных? (обведены зелёным)
Изображение

Передаю вот таким стандартным кодом на ассемблере для AVR.
Код:
;загоняем биты в 74hc595
   out SPDR, ShiftRegister4   ; передаём байт для 4-го 74hc595
   Wait_SPI_Tranfer4:   ;ожидание передачи байта
      in temp, SPSR
      sbrs temp, SPIF ;если флаг завершения передачи установлен,
   rjmp Wait_SPI_Tranfer4 ;то пропускаем эту команду
      
   out SPDR, ShiftRegister3   ; передаём байт для 3-го 74hc595
   Wait_SPI_Tranfer3:   ;ожидание передачи байта
      in temp, SPSR
      sbrs temp, SPIF ;если флаг завершения передачи установлен,
   rjmp Wait_SPI_Tranfer3 ;то пропускаем эту команду
      
   out SPDR, ShiftRegister2   ; передаём байт для 2-го 74hc595
   Wait_SPI_Tranfer2:   ;ожидание передачи байта
      in temp, SPSR
      sbrs temp, SPIF ;если флаг завершения передачи установлен,
   rjmp Wait_SPI_Tranfer2 ;то пропускаем эту команду
      
   out SPDR, ShiftRegister1   ; передаём байт для 1-го 74hc595
   Wait_SPI_Tranfer1:   ;ожидание передачи байта
      in temp, SPSR
      sbrs temp, SPIF ;если флаг завершения передачи установлен,
   rjmp Wait_SPI_Tranfer1 ;то пропускаем эту команду

Re: Вопрос по SPI на asm

Пн ноя 20, 2023 15:17:39

Сдрасти уважаемые :)
У кого нибудь удалось завести этот дисплей на аппаратном SPI? Я давно завёл его с помощью ногодрыга по 10 бит а вот аппаратный SPI пока не хочет, передаю ему по 16 бит где требуется 10. Кстати да, дисплей не требует таких диких задержек как HD4478.
Ответить