roboforum.ru

Технический форум по робототехнике.

Как передать по SPI 10 бит данных?

Как передать по SPI 10 бит данных?

Змей-Горыныч » 10 мар 2005, 14:12

Может посоветует кто сталкивался...
Задача такая:
Нужно подключить к AVR микроконтроллеру интегральный резистор с цифровым управлением типа AD8402. Для управления им используется 3-х проводный (SPI-совместимый, как написано в описании http://www.promelec.ru/pdf/ad8400_2_3_c.pdf ) интерфейс. Два старших бита это адрес потенциометра, и 8 бит - код управления. Так вот, разве можно из порта SPI контроллера послать 10 бит? Там же всего 8-разрядный регистр сдвига. Или можно както обмануть его. Я просто до этого не сталкивался с SPI.
Предвижу предложение использовать просто 3 линии одного из портов... может быть так и придётся сделать.

Mike_MA » 10 мар 2005, 15:08

Я порекомендовал не париться.... Как я понимаю, сначала надо послать байт данных, а потом адрес. .... Собственно не вижу проблемы....посылаешь один байт, потом пишешь туда же второй, отсчитываешь два периода и отключаешь передачу. Т.е. заведя сигнал CLK на одну из ног и считай переданные битики...

Змей-Горыныч » 10 мар 2005, 15:35

Не понял.
Суть не в посилке двух байт, это то как раз не проблемма. А суть в том, что надо сразу в одной последовательности послать 10 бит (причем первые два - адрес, последующие 8 - данные). См. рис.
Вложения
byte.JPG
Вот как это должно выглядеть.
byte.JPG (9.41 КиБ) Просмотров: 10124

RoboAlex » 11 мар 2005, 10:30

Проще всего - реализовать програмно. если контроллер под это "не заточен", то заставить его трудно. В частности, каким образом определить, когда переданы только 2 бита ? Прерывания такого нет.

SPI ведь синхронный интерфейс, скорость передачи определяет мастер (вы). Если у вас контроллер не перегружен задачами, лучше самому написать ф-цию посылки

Mike_MA » 11 мар 2005, 12:29

Змей-Горыныч писал(а): А суть в том, что надо сразу в одной последовательности послать 10 бит (причем первые два - адрес, последующие 8 - данные). См. рис.


А 10 бит в 8-ми разрядный регистр не засунешь. Либо вешаешь сигнал "CLK" на вход внешнего прерывания  и считаешь переданные биты, или управляешь сигналом "CS". Можно использовать и то и то.

Змей-Горыныч » 14 мар 2005, 14:06

RoboAlex писал(а):SPI ведь синхронный интерфейс, скорость передачи определяет мастер (вы). Если у вас контроллер не перегружен задачами, лучше самому написать ф-цию посылки


Спасибо. Я так и предполагал. Вы подтвердили мои догадки. Что ж реализую сам это дело програмно. Уже придумал как передовать биты в соответствии с их порядком в нужном регистре.

Змей-Горыныч » 16 мар 2005, 09:18

Ну, в общем сделал я это дело!  :lol:
Кстати очень понравились цифровые резисторы. Запросто (и главное дёшево!) можно с их помощью АЦП сварганить.
В общем рекомендую. Может кого заинтересует, вот кратко чего они умеют:

AD5204/ AD5206 является 256 позиционным четырех-/ шестиканальным 8 битным цифровым переменным резистором (VR) с цифровым управлением. Эти устройства исполняют ту же самую электронную функцию настройки как потенциометр или регулируемый резистор. Каждый канал AD5204/AD5206 содержит установленный резистор с контактом движка, который устанавливается в точку, определяемую цифровым кодом, загруженным во входной регистр по SPI - совместимому последовательному интерфейсу. Сопротивление между движком и любым выводом цифрового резистора изменяется линейно в соответствии с цифровым кодом, загруженным во входной регистр VR. Регулировочный движок устанавливается в любое положение от одного вывода до другого. Фиксированное сопротивление между выводами А и В имеет значение 10 кОм, 50 кОм, или 100 кОм и имеет номинальный температурный коэффициент сопротивления 700 ррm/ °C.
Каждый VR имеет свой собственный регистр VR, который содержит кодовое значение сопротивления. Эти регистры VR обновляются от внутреннего последовательно- параллельного регистра сдвига, который загружается по стандартному 3 проводному цифровому SPI интерфейсу. Одиннадцать информационных бит составляют информационное слово, загружаемое во входной регистр синхронно. Первые три бита содержат информацию о номере загружаемого регистра VR, последующие восемь бит содержат информацию о положении движка потенциометра, в который он устанавливается при возвращении стробирующего сигнала CS в высокое состояние. Вывод в противоположном конце последовательного регистра (только у AD5204) позволяет просто организовать последовательную цепочку данных для множества VR без применения дополнительной декодирующей логики.

setar » 16 мар 2005, 12:16

:roll: А не затруднит ли в виде обучающей статейки с кодом оформить?

что то вроде "Управление цифровым потенциометром с помощью AVR"

Змей-Горыныч » 29 мар 2005, 06:38

Ну, на статью это пожалуй не потянет, но может кому и облегчит знакомство с этими устройствами.
Итак, вот фрагмент кода для AVR, который позволяет загрузить необходимое значение сопротивления в цифровой резистор AD8404 или любой другой, имеющий 10-битный последовательный синхронный интерфейс (или SPI).
В переменной AdresRezist содержится адрес резистора в микросхеме (2 бита), так как в одном корпусе может быть несколько потенциометров.
В переменной CodRezist соответственно заданое значение сопротивления (8 бит). Для вывода требуются 4 линии порта. А если вы не хотите посылать согнал сброса, то можно и тремя обойтись.


.equ SPI_PORT = PORTA ;Порт для вывода
.equ SDI = 0  ;Данные
.equ CLK = 1  ;Тактовый сигнал (по возр. фронту)
.equ CS = 2  ;Разрешение ("0" - разрешено)
.equ RS = 3  ;Сброс ("0" на 50 нс)

;______________ Переменные ____________________

.def  temp = R16
.def  CodRezist = R17  ;Заданое значение сопротивления
.def  AdresRezist = R18  ;Адрес резистора в микросхеме

 ;Загрузка значения в AD8402
 ;Адрес
sbi SPI_PORT,RS ;Линию сброса в "1"
cbi SPI_PORT,CLK ;В "0" линию тактового сигнала
cbi SPI_PORT,CS ;Разрешение записи в микр.

cbi SPI_PORT,SDI ;Старший бит адреса A1 = 0
sbrc AdresRezist,1 ;Пропустить if бит в Rd очищен
sbi SPI_PORT,SDI ;Старший бит данных A1 = 1
sbi SPI_PORT,CLK ;"1" линию тактового сигнала (захват)

cbi SPI_PORT,SDI ;Младший бит адреса A0 = 0
sbrc AdresRezist,0 ;Пропустить if бит в Rd очищен
sbi SPI_PORT,SDI ;Младший бит данных A0 = 1
cbi SPI_PORT,CLK ;В "0" линию тактового сигнала
sbi SPI_PORT,CLK ;"1" линию тактового сигнала (захват)

;Данные
cbi SPI_PORT,SDI ;Бит данных D7 = 0
sbrc CodRezist,7 ;Пропустить if бит в Rd очищен
sbi SPI_PORT,SDI ;Бит данных D7 = 1
cbi SPI_PORT,CLK ;В "0" линию тактового сигнала
sbi SPI_PORT,CLK ;"1" линию тактового сигнала (захват)

cbi SPI_PORT,SDI ;Бит данных D6 = 0
sbrc CodRezist,6 ;Пропустить if бит в Rd очищен
sbi SPI_PORT,SDI ;Бит данных D6 = 1
cbi SPI_PORT,CLK ;В "0" линию тактового сигнала
sbi SPI_PORT,CLK ;"1" линию тактового сигнала (захват)

cbi SPI_PORT,SDI ;Бит данных D5 = 0
sbrc CodRezist,5 ;Пропустить if бит в Rd очищен
sbi SPI_PORT,SDI ;Бит данных D5 = 1
cbi SPI_PORT,CLK ;В "0" линию тактового сигнала
sbi SPI_PORT,CLK ;"1" линию тактового сигнала (захват)

cbi SPI_PORT,SDI ;Бит данных D4 = 0
sbrc CodRezist,4 ;Пропустить if бит в Rd очищен
sbi SPI_PORT,SDI ;Бит данных D4 = 1
cbi SPI_PORT,CLK ;В "0" линию тактового сигнала
sbi SPI_PORT,CLK ;"1" линию тактового сигнала (захват)

cbi SPI_PORT,SDI ;Бит данных D3 = 0
sbrc CodRezist,3 ;Пропустить if бит в Rd очищен
sbi SPI_PORT,SDI ;Бит данных D3 = 1
cbi SPI_PORT,CLK ;В "0" линию тактового сигнала
sbi SPI_PORT,CLK ;"1" линию тактового сигнала (захват)

cbi SPI_PORT,SDI ;Бит данных D2 = 0
sbrc CodRezist,2 ;Пропустить if бит в Rd очищен
sbi SPI_PORT,SDI ;Бит данных D2 = 1
cbi SPI_PORT,CLK ;В "0" линию тактового сигнала
sbi SPI_PORT,CLK ;"1" линию тактового сигнала (захват)

cbi SPI_PORT,SDI ;Бит данных D1 = 0
sbrc CodRezist,1 ;Пропустить if бит в Rd очищен
sbi SPI_PORT,SDI ;Бит данных D1 = 1
cbi SPI_PORT,CLK ;В "0" линию тактового сигнала
sbi SPI_PORT,CLK ;"1" линию тактового сигнала (захват)

cbi SPI_PORT,SDI ;Бит данных D0 = 0
sbrc CodRezist,0 ;Пропустить if бит в Rd очищен
sbi SPI_PORT,SDI ;Бит данных D0 = 1
cbi SPI_PORT,CLK ;В "0" линию тактового сигнала
sbi SPI_PORT,CLK ;"1" линию тактового сигнала (захват)

sbi SPI_PORT,CS ;Конец записи в микр.
ret

Поскольку интерфейс синхронный, не используются никикие задержки, програмные или по таймеру. Соответственно работать можно с любой тактовой частотой.

P.S. Уверен что кто-нибудь может сделать лучше. Это мой первый опыт. Я собирал регулируемый источник питания, с задаваемым с компа значением напряжения.
Выходное U оцифровывалось AVR контроллером, и в зависимости от его величины регулировалось сопротивление в цепи обратной связи (значение в переменной CodRezist).
Точность Uвых у меня полутилась +/- 0,02 В.

Stepan » 16 апр 2005, 21:18

Змей-Горыныч писал(а):Кстати очень понравились цифровые резисторы. Запросто (и главное дёшево!) можно с их помощью АЦП сварганить.

По-моему ещё проще и дешевле с помощью ШИМа.

Nihilant » 28 авг 2006, 11:57

У меня похожая задача, только передать надо серию байт. Контроллер - Мега8. Там есть SPI. Надо переслать 5 байт в контроллер LCD от кассового аппарата COP472N-3.
Loading Sequence у него такой, что после опускания !CS надо послать 4 байта для цифр и байт служебной информации. И только потом на !CS выставить высокий уровень. Насколько я понял, Мега моя будет после каждого байта !CS дергать. Поэтому планирую такой алгоритм:

установить ногу, на которой !CS в 1

НЦ (бесконечного)

дернуть ногу, на которой !CS в 0
отправить 1-й байт, ждать прерывания SPI
...
отправить 5-й байт,  ждать прерывания SPI
дернуть ногу, на которой !CS в 1

КЦ


причем нога, на которую вешаем !CS,  не совпадает со штатной !CS от Меги

Буду благодарен за любые замечания.

Nihilant » 28 авг 2006, 11:57

У меня похожая задача, только передать надо серию байт. Контроллер - Мега8. Там есть SPI. Надо переслать 5 байт в контроллер LCD от кассового аппарата COP472N-3 с интерфейсом Microwire(tm).
Loading Sequence у него такой, что после опускания !CS надо послать 4 байта для цифр и байт служебной информации. И только потом на !CS выставить высокий уровень. Насколько я понял, Мега моя будет после каждого байта !CS дергать. Поэтому планирую такой алгоритм:

установить ногу, на которой !CS в 1

НЦ (бесконечного)

получить по UART 5 байт

дернуть ногу, на которой !CS в 0
отправить 1-й байт, ждать прерывания SPI
...
отправить 5-й байт,  ждать прерывания SPI
дернуть ногу, на которой !CS в 1

КЦ


причем нога, на которую вешаем !CS,  не совпадает со штатной !CS от Меги

Буду благодарен за любые замечания.

Re: Как передать по SPI 10 бит данных?

J.Joker » 28 мар 2010, 17:34

Добрый день, не могли бы Вы мне помочь с моим проектом. Я программно реализовал SPI, но потенциометр реагирует слабо, то есть изменения буквально в сотых долях (в модели, в реальности напряжение вообще не меняется). Подскажите пожалуйста, где я ошибся.
Вложения
SPI.rar
схема, файлы для Proteus 7.6 и исходники для CV AVR
(125.5 КиБ) Скачиваний: 0

Re: Как передать по SPI 10 бит данных?

tsrodger » 29 мар 2010, 07:57

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


Rambler\'s Top100 Mail.ru counter