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

Обсуждаем контроллеры компании Atmel.
vit007
Встал на лапы
Сообщения: 124
Зарегистрирован: Пн мар 22, 2010 18:07:52

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

Сообщение vit007 »

Всем спасибо, за участие... много интересного узнал... следующий этап - реализация в железе, но это другая история...
Реклама
Alkul
Держит паяльник хвостом
Сообщения: 933
Зарегистрирован: Ср апр 13, 2011 11:09:20
Откуда: Екатеринбург

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

Сообщение Alkul »

roman.com писал(а): -измерил датчик 1
-обработал данные
-закинул в SPI... SPI автоматом передает. А я измеряю следующие датчики...
...
-измерил датчик N
-обработал данные
-закинул в SPI... SPI автоматом передает. А я измеряю следующие датчики...
То есть, если у Вас 10 одинаковых датчиков, Вы линейно 10 раз повторите код опроса датчика, код обработки данных и код передачи по SPI?
Вопросов больше не имею...
Реклама
roman.com
Друг Кота
Сообщения: 9175
Зарегистрирован: Вт мар 13, 2012 12:16:13
Откуда: .ru

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

Сообщение roman.com »

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

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

Хотя... кому как больше нравится))
Alkul
Держит паяльник хвостом
Сообщения: 933
Зарегистрирован: Ср апр 13, 2011 11:09:20
Откуда: Екатеринбург

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

Сообщение Alkul »

Alkul писал(а):То есть, если у Вас 10 одинаковых датчиков, Вы линейно 10 раз повторите код
roman.com писал(а):Нет, в цикле.
Тогда у Вас проблемы с терминологией.
Вы сами написали:
roman.com писал(а):Ну и нафига эта мне головная боль с подпрограммами при линейном алгоритме?
По определению, линейный алгоритм - это алгоритм, не содержащий циклов и ветвлений.
Реклама
Эиком - электронные компоненты и радиодетали
roman.com
Друг Кота
Сообщения: 9175
Зарегистрирован: Вт мар 13, 2012 12:16:13
Откуда: .ru

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

Сообщение roman.com »

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

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

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

А Вы, как я понял, для того что бы измерить 10 датчиков и отправить 10 байт на индикатор, предлагаете использовать подпрограмму ?))
Реклама
Alkul
Держит паяльник хвостом
Сообщения: 933
Зарегистрирован: Ср апр 13, 2011 11:09:20
Откуда: Екатеринбург

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

Сообщение Alkul »

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 файл создать и как библиотеку подключать в других проектах.
Реклама
roman.com
Друг Кота
Сообщения: 9175
Зарегистрирован: Вт мар 13, 2012 12:16:13
Откуда: .ru

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

Сообщение roman.com »

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

)) Вообщето изначально был вопрос про SPI интерфейс. Человек не может разобраться как работает SPI интерфейс...
vit007 писал(а):Значит аппаратный SPI работает параллельно программе?
vit007 писал(а):это правда, что предмет плохо знаю...
А Вы, вместо того чтобы "на пальцах" объснить человеку как работает SPI интерфейс, начали рассказывать про оптимизацию алгоритма)) vit007 надо было просто почитать даташит и в протеусе поиграться с настройками и просто разобраться с SPI интерфейсом))
vit007 писал(а):Всем спасибо, за участие... много интересного узнал... следующий этап - реализация в железе, но это другая история...
Пожалуйста)) Вообщем с SPI интерфейсом разобрались... переходим на следующий этап))
Аватара пользователя
BlYur
Открыл глаза
Сообщения: 52
Зарегистрирован: Пн май 27, 2013 17:02:32

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

Сообщение BlYur »

Эмулирую работу 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 ;то пропускаем эту команду
Аватара пользователя
alex_
Опытный кот
Сообщения: 781
Зарегистрирован: Сб июн 01, 2013 22:24:21
Откуда: ПФО

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

Сообщение alex_ »

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

Вернуться в «AVR»