Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: 1-wire Интерфейс
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему
3state-systems
Здравствуйте,
Изучаю микроконтроллеры для себя, решил изучить интерфейс 1-wire
наткнулся на странную ситуацию: вроде и все давно ясно и куча библиотек готовых есть под разные микроконтроллеры на С разных мастей и под Assembler.
И в форумах не одна тема создана, а полной картины по 1-wire[AVR Assembler] как небыло так и нет.

Предлагаю поделится опытом, советом, готовым примером, покритиковать, поддержать и просто высказать свое мнение
Цель: Создание простых, универсальных и ясных подпрограмм для работы с 1-wire
Резюмируя эту тему можна создать неплохую статью для начинающих в рамках проекта AVR для начинающих Electronix.ru

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

Ну так начнем!
Возьмем в качестве отправной точки (Я начинающий!)
Код
AVR318: Ведущий однопроводной интерфейс 1-Wire компании Dallas (21 страница, пересмотр А, обновление от 09/04)
В рекомендациях показывается, как реализовать 1-проводной ведущий интерфейс с помощью микроконтроллера AVR. Рассмотрено два подхода: полностью программный и с помощью встроенного модуля У(С)АПП

Нас интересует только полностью программный подход
Из него следует:
Что для программной реализации протокола удобно разделить все команды на четыре уровня
УРОВНИ (и команды)
1)Передача и прием отдельных битов
a)Сброс всех устройств на шине [Restart]
B)Запись бита "1" в устройство [WriteBit1]
с)Запись бита "0" в устройство [WriteBit0]
d)Чтение бита из устройства [ReadBit]

2)Передача и прием отдельных байтов
a)Послать байт в устройство [SentByte]
B)Принять байт из устройства [ReseiveByte]

3)Сетевой уровень
a)Чтение ПЗУ [ReadROM]
B)Совпадение ПЗУ [MatchROM]
c)Пропуск ПЗУ [SkipROM]
d)Поиск ПЗУ [SearchRom]

4)Команды для работы с конкретными устройствами например датчик температуры ds1820 series
м некоторые прикладные подпрограммки
a)Вычисление CRC8 (табличная реализация и прямое вычисление)
B)Диагностика ошибок
с)Чтение режима питания микросхем паразитное или отдельное





Так как стандарт основывается на точном соблюдении всех задержек, всего 2 группы
6-64мкс и 470-1000мкс.
Вопрос как универсально сформировать задержки для различных частот задающих кварцов?

Так по теме словесное описанное описание команд первого уровня
Код
Restart:
;Сброс всех устройств
;Подсаживаем линию, задержка на 700мкс
;Задержка в 65мкс, проверка сигнала
;ок =уровень сигнала равен 0 передача управления дальше на3
;error уровень Равен 1 =обрыв линии
;3 формируем задержку в 500мкс проверяем уровень сигнала
;ок =уровень сигнала равен 1
;error уровень равен 0 =линия закорочена
;в переменную помешаем код ошибки и выходи 0=ок
    reti
    Readbit:
;Чтение чтение одного бита из устройства
;Формируем синхроимпульс, подсаживаем линию =задержка 1мкс отпускаем линию снова                               задержка 13мкс
;считываем уровень сигнала помешаем кудато
;заполняем слот задержкой в 60-120мкс (60мкс)
     reti
    writebit0:
;Запись в слот нулевого значения
;подсадить линию    
;задержка в 80мкс
;отпустиь линию
;
    reti
    writebit1:
;Запись в слот единичного значения
;подсадить линию    
;задержка в 4,5мкс
;отпустиь линию
;задержка в 75мкс
    reti
Kuzmi4
2 3state-systems - с 1-Wire интерфейсом не сталкивался , однако на счёт "...как универсально сформировать задержки для различных частот задающих кварцов?..." - в принципе есть идея, точнее размышлизмы - я обычно затачиваю вся под 1 кварц, но если потом кварц может меняться , то использую ф-цию делэй предварительно определив Ф_ЦПУ - там идея довольно простая -
Для мкс -
_delay_us(double __us)
{
uint8_t __ticks;
!!!!double __tmp = ((F_CPU) / 3e6) * __us;!!!
if (__tmp < 1.0)
__ticks = 1;
else if (__tmp > 255)
__ticks = 0; /* i.e. 256 */
else
__ticks = (uint8_t)__tmp;
_delay_loop_1(__ticks);
}
Можно конечно на этой основе наварганить чтото своё, но я использую встроенные делэи - проблем и вопросов не возникало..
Сергей Борщ
Цитата(3state-systems @ Apr 11 2007, 18:48) *
Предлагаю поделится опытом, советом, готовым примером, покритиковать, поддержать и просто высказать свое мнение
Хм. "петь я не умею, но люблю". Т.е. на ассемблере пишу очень редко, но покритиковать - всегда пожалуйста. Цель благородная, поэтому постараюсь внести свою лепту, но примеры буду кидать на С, если хотите - переводите их на ассемблер.
Цитата(3state-systems @ Apr 11 2007, 18:48) *
1)Передача и прием отдельных битов
a )Сброс всех устройств на шине [Restart]
B )Запись бита "1" в устройство [WriteBit1]
с )Запись бита "0" в устройство [WriteBit0]
d )Чтение бита из устройства [ReadBit]
с А согласен. Что касается b-d, то если мы внимательно посмотрим на диаграмму работы шины, то заметим что при передаче единицы и при приеме мастер шевелит ногой совершенно одинаково. Поэтому все три пункта объединяются в одну функцию (подпрограмму) "обмен битом", которая в качестве входного параметра принимает передаваемый бит а возвращает принятый бит. Если надо передать бит, мы не используем возвращаемый результат, если надо принять - вызываем ее с параметорм "1". Таким образом мы существенно упрощаем и сокращаем программу.
Цитата(3state-systems @ Apr 11 2007, 18:48) *
2)Передача и прием отдельных байтов
a )Послать байт в устройство [SentByte]
B )Принять байт из устройства [ReseiveByte]
Аналогично предыдущему - обе функции сливаются в одну "обмен байтом". Передача = "обмен" с игнорированием ответа, прием = "обмен" с передачей 0xFF.
Цитата(3state-systems @ Apr 11 2007, 18:48) *
3)Сетевой уровень
a )Чтение ПЗУ [ReadROM]
B )Совпадение ПЗУ [MatchROM]
c )Пропуск ПЗУ [SkipROM]
d )Поиск ПЗУ [SearchRom]
Ненаказуемо wink.gif
Цитата(3state-systems @ Apr 11 2007, 18:48) *
Так как стандарт основывается на точном соблюдении всех задержек, всего 2 группы 6-64мкс и 470-1000мкс.
Вопрос как универсально сформировать задержки для различных частот задающих кварцов?
Поскольку допуски довольно большие, вполне можно формировать задержки пустым циклом, т.е. функцией __delay_cycles() в IAR C или макросом вроде (я же предупреждал - пишу редко)
Код
Delay   MACRO  cycles
    local Loop
    LDI  R16, cycles
Loop:
    DEC R16
    BNE  Loop
    ENDM
Один такой цикл (если не изменяет память) исполняется 3 такта, т.е. надо предусмотреть вариант когда требуется бОльшая задержка:
Код
Delay   MACRO  cycles
    local Loop
#if cycles < 256 * 3
    LDI  R16, cycles / 3
Loop:
    DEC R16
    BNE  Loop
#else
    // предполагаю, что цикл займет 7 тактов, если ошибся - изменить константу
    LDI  R16, LOW(cycles / 7)
    LDI  R16, HI(cycles / 7)
Loop:
    // дописать код для двухбайтного счетчика

#endif
    ENDM

Далее, следуя принципу IBM "машина должна работать, а человек - думать" пишем простой макрос, переводящий время задержки в количество тактов:
Код
#define  OSC 7372800UL //Core frequency, Hz, unsigned long (32 bits)
#define MS *OSC/1000
#define MKS *OSC/1000/1000
Меняется кварц - меняем строчку #define OSC. Теперь задержка делается просто:
Код
на С:
__delay_cycles(15 MKS);
__delay_cycles(60 MS);
На асм:
    Delay  15 MKS
    Delay  60 MS
Ваш ход.
3state-systems
Так сейчас закодил первый уровень
вот что получилось
Код
Restart:                     ;Сброс всех устройств
sbi DDRD,DataPin1;Настроить линию на выход
cbi PORTD,DataPin1;подсадить линию    
rcall delay480            ;задержка в 480мкс
sbi PORTD,DataPin1;отпустиь линию
rcall delay70             ;задержка в 70мкс
cbi DDRD,DataPin1;Настроить линию на вход
clt                            ;Очистить флаг Т регистра Sreg 0 = Все нормально
sbic PIND,DataPin1    ;Пропустить следущию команду если бит равен "0"
set                        ;Записать "1" в регитр Sreg флаг Т 1 = Ошибка в линии Microlan
rcall delay410        ;задержка в 410мкс
reti

ReadBit:                     ;чтение одного бита из устройства в Регистр Sreg флаг Т
sbi DDRD,DataPin1;Настроить линию на выход
cbi PORTD,DataPin1;подсадить линию    
rcall delay6            ;задержка в 6мкс
sbi PORTD,DataPin1;отпустиь линию
rcall delay9            ;задержка в 9мкс
cbi DDRD,DataPin1;Настроить линию на вход
clt                            ;Очистить флаг Т регистра Sreg
sbic PIND,DataPin1    ;Пропустить следущию команду если бит равен "0"
set                        ;Записать "1" в регитр Sreg флаг Т
rcall delay55        ;задержка в 55мкс
reti

Writebit0:;                 ;Запись бита "0" в устройство
sbi DDRD,DataPin1;Настроить линию на выход
cbi PORTD,DataPin1;подсадить линию    
rcall delay60             ;задержка в 80мкс
sbi PORTD,DataPin1;отпустиь линию
rcall delay10        ;задержка в 10мкс
reti

Writebit1:                ;Запись бита "1" в устройство
sbi DDRD,DataPin1;Настроить линию на выход
cbi PORTD,DataPin1;подсадить линию    
rcall delay6            ;задержка в 6мкс
sbi PORTD,DataPin1;отпустиь линию
rcall delay64        ;задержка в 64мкс
reti


Но впереди конечно
.equ DataPin1 =5 ;portd5 = DataPin 1-wire bus
Эту куда подключена наша шина долго думал как сделать универсально
получилось что можно свободно менять пин подключения в пределах одного порта D
изменить только циферку
Так и непонял что как организовать задержки ну лана будем мутить nop с циклами

Прошу всех обратить внимание как вначале организовать порт с подтягивающими встроенными резисторами ну чтобы 0 это было 0 а не 1
и еще один вопрос можно ли для обмена байтами в следующем уровне использовать стек (PUSH POP)
Сергей Борщ
Цитата(3state-systems @ Apr 12 2007, 19:57) *
Но впереди конечно
.equ DataPin1 =5 ;portd5 = DataPin 1-wire bus
Почему впереди? Надо сразу писать правильно и красиво.
Код
#define DataPort   PIND
#define DataPin 5
Указываем именно PINx, чтобы можно было получить адреса остальных регистров прибавляя 1, 2, 3. Кстати, я ориентируюсь на ассемблер IAR, а вы, судя по .equ имеете ввиду avrasm2?
Цитата(3state-systems @ Apr 12 2007, 19:57) *
вот что получилось
Код
Restart:                ;Сброс всех устройств
sbi DDRD,DataPin1;Настроить линию на выход
cbi PORTD,DataPin1;подсадить линию    
rcall delay480    ;задержка в 480мкс
sbi PORTD,DataPin1;отпустиь линию
rcall delay70        ;задержка в 70мкс
cbi DDRD,DataPin1;Настроить линию на вход
Сразу большая ошибка: точно также как и в I2C, в 1-wire нельзя выдавать единицу на вывод. Потому что в это время другое устройство может притягивать линию к нулю и мы получим конфликт уровней. Возможно, сгорит не сразу, но делать так нельзя wink.gif При инициализации надо записать в PORTx ноль, и дальше работать только изменением направления: настроили на вывод - снаружи линия притянулась к нулю. Настроили на ввод - внешний резистор потянул линию к единице. И заканчиваются подпрограммы командой ret. reti завершает прерывания. Поэтому ваш код должен выглядеть примерно так:
Код
.equ   DataPort   PIND
.equ   DataPin     5

Restart:                ;Сброс всех устройств
cbi DataPort + 2, DataPin; PORTx = 0, подготовить к работе
sbi DataPort + 1, DataPin; DDRx = 1, Настроить линию на выход - посадить линию в 0
rcall delay480            ;задержка в 480мкс
cbi DataPort + 1, DataPin;Настроить линию на вход = отпустить линию
rcall delay70            ;задержка в 70мкс
clt                    ;Очистить флаг Т регистра Sreg 0 = Все нормально
; обычно используют флаг Z, так удобнее - он выставляется командой TST.
sbic DataPort, DataPin    ; Пропустить следущию команду если бит равен "0"
set                    ; Записать "1" в регитр Sreg флаг Т 1 = нет устройств на шине
rcall delay410        ; задержка в 410мкс
ret                    ; хотя RCALL и следом за ним RET можно заменить на один RJMP delay410

Чтение/запись бита:
Код
WriteBit0:
   clt
   rjmp  ExchangeBit
WriteBit1:
ReadBit:
   set
ExchangeBit:        ;Передаваемый бит в T
   sbi DataPort + 1, DataPin; DDRx = 1, Настроить линию на выход - посадить линию в 0
   rcall delay6        ; задержка в 6мкс
   BRTC    Write_0             ; Если передается ноль - оставить ногу посаженной в 0
   cbi DataPort + 1, DataPin; Настроить линию на вход = отпустить линию
Write_0:
   rcall delay9        ; задержка до точки чтения
   clt            ; Очистить флаг Т
   sbic DataPort, DataPin    ; Пропустить следущию команду если линия притянута к 0
   set
   rcall delay45        ; задержка в 45мкс
   cbi DataPort + 1, DataPin; Настроить линию на вход = отпустить линию
   rjmp delay2        ; задержка >1мкс - пауза между битами и возвратиз подпрограммы. В флаге T - считанный бит

Цитата(3state-systems @ Apr 12 2007, 19:57) *
Так и непонял что как организовать задержки ну лана будем мутить nop с циклами
Напишите две задержки разной длительности. Посмотрите, насколько похож код. Почитайте в описании ассемблера про макросы.
Цитата(3state-systems @ Apr 12 2007, 19:57) *
Прошу всех обратить внимание как вначале организовать порт с подтягивающими встроенными резисторами ну чтобы 0 это было 0 а не 1
Даже и не думать в эту сторону - внутренних подтяжек совершенно недостаочно для 1-wire Поэтому обязательно ставить внешнюю и про внутреннюю забыть!
Цитата(3state-systems @ Apr 12 2007, 19:57) *
и еще один вопрос можно ли для обмена байтами в следующем уровне использовать стек (PUSH POP)
Можно, почему бы нет?
3state-systems
Цитата
Кстати, я ориентируюсь на ассемблер IAR, а вы, судя по .equ имеете ввиду avrasm2?

Да конечно на него, мы же пишем для начинающих smile.gif
Цитата
И заканчиваются подпрограммы командой ret. reti завершает прерывания.

Сорри попутал чуток blush.gif
Цитата
При инициализации надо записать в PORTx ноль, и дальше работать только изменением направления: настроили на вывод - снаружи линия притянулась к нулю. Настроили на ввод - внешний резистор потянул линию к единице.

Вроде с виду все правильно, может так оно и есть, просто я смотрел исходники для MCS-51 там вроде делается записью единицы.

Цитата
Даже и не думать в эту сторону - внутренних подтяжек совершенно недостаочно для 1-wire Поэтому обязательно ставить внешнюю и про внутреннюю забыть!

Полностью согласен, по даташиту - резистор, правда номинал у всех довольно сильно варьируется в топиках. но это потом у\еще уточним.
Приду домой внимательно посмотрю ваш код smile.gif
Сергей Борщ
Цитата(3state-systems @ Apr 13 2007, 08:47) *
Да конечно на него, мы же пишем для начинающих smile.gif
Три раз перечитал, так и не понял - "Да" - это IAR или avrasm2? smile.gif
Цитата(3state-systems @ Apr 13 2007, 08:47) *
Вроде с виду все правильно, может так оно и есть, просто я смотрел исходники для MCS-51 там вроде делается записью единицы.
А! Тогда понятно. У 51 нет верхнего транзистора, для него что вывод 1, что ввод - одинаково. Он в этом смысле очень похож на вывод 1-wire. Вы обратили внимание, что у 51 нет регистра направления порта? Именно поэтому. На "честных" портах подход должен быть другим - как я описал.
3state-systems
Цитата
(3state-systems @ Apr 13 2007, 08:47) *
Да конечно на него, мы же пишем для начинающих smile.gif
Три раз перечитал, так и не понял - "Да" - это IAR или avrasm2? smile.gif

AvrAsm2 smile.gif

Цитата
Указываем именно PINx, чтобы можно было получить адреса остальных регистров прибавляя 1, 2, 3.

Сначала хотел возмутится в даташите на мегу в Register Summary все в обратном порядке потом глянул
на адреса blush.gif Гениально придумано! Вот тока зачем добавлять 3? wink.gif
Код
0x1B (0x3B) PORTA
0x1A (0x3A) DDRA
0x19 (0x39) PINA


Код
.equ DataPort =PIND;Порту к которому подключена шина
.equ DataPin   =5     ;Пин к которому подключена шина 1-wire bus
;DataPort=PIN(x);
;DataPort+1=DDR(x)
;DataPort+2=PORT(x)
Сергей Борщ
Цитата(3state-systems @ Apr 13 2007, 14:26) *
Вот тока зачем добавлять 3? wink.gif
Ну обшибся tongue.gif Регистров три? Вот и написал раз-два-три. А ведь и правда - надо было ноль-раз-два.
3state-systems
Часа два разбирался с вашей универсальной подпрограммой обмена битами, вроде разобрался но для новичка конечно это жесть smile.gif
Так значит имеем 100пудовые подпрограммы для первого уровня

Код
.equ DataPort =PIND;Порту к которому подключена шина
.equ DataPin  =5      ;Пин к которому подключена шина 1-wire bus
;DataPort=PIN(x);
;DataPort+1=DDR(x)
;DataPort+2=PORT(x)



    Restart:                       ;Сброс всех устройств
     cbi DataPort+2,DataPin;PORTx = 0, подготовить к работе
     sbi DataPort+1,DataPin;DDRx = 1, Настроить линию на выход - посадить линию в 0
     rcall delay480              ;задержка в 480мкс
     cbi DataPort+1,DataPin;Настроить линию на вход = отпустить линию
     rcall delay70                ;задержка в 70мкс
     clt                               ;Очистить флаг Т регистра Sreg 0 = Все нормально
     sbic DataPort, DataPin      ;Пропустить следущию команду если бит равен "0"
     set                                  ;Записать "1" в регитр Sreg флаг Т=1 - нет устройств на шине
     rcall delay410                  ;задержка в 410мкс
    ret                                   ;[хотя RCALL и следом за ним RET можно заменить на один RJMP delay410]

    WriteBit0:                           ;Запись Бита "0"
     clt
     rjmp ExchangeBit
    WriteBit1:                           ;Запись Бита "1"
    ReadBit:                     ;Чтение Бита
     set
         ExchangeBit:                 ;Передаваемый бит в T
          sbi DataPort+1,DataPin  ;DDRx = 1, Настроить линию на выход - посадить линию в 0
         rcall delay6                   ;задержка в 6мкс
         BRTC    Write_0            ;Если передается ноль - оставить ногу посаженной в 0
         cbi DataPort + 1, DataPin;Настроить линию на вход = отпустить линию
         Write_0:
          rcall delay9                   ;задержка до точки чтения
          clt                                ;Очистить флаг Т
          sbic DataPort,DataPin    ;Пропустить следущию команду если линия притянута к 0
          set
          rcall delay45                  ;задержка в 45мкс
          cbi DataPort+1,DataPin ;Настроить линию на вход = отпустить линию
          rcall delay10                 ;задержка 10мкс - пауза между битами и возвратиз подпрограммы. В флаге T - считанный бит
    ret


Restart -Сброс всех устройств
WriteBit0 - Запись Бита "0"
WriteBit1 - Запись Бита "1"
ReadBit - Чтение Бита
3state-systems
Так добрались до байт
черновой вариант такой
.def Temp =R16 ;Temp он и в африке Temp
.def ByteBus =R20 ;Байт для передачи\приема 1-wire bus

Код
WriteByte:                    ;Запись байта в ведомое устройство
    
     lsr Bytebus          ;Сдвинуть байт вправо ->С (Флаг переноса регистра Sreg)
     brcs Writebit1         ;Перейти если флаг переноса установлен(текущий бит равен 1)
     rcall Wriebit0          ;Перейти если флаг переноса сброшен (текущий бит равен 0)
                       ;Нужен цикл повторить 8 раз
    ret

Чтот у мня цикл взбунтовался не работает smile3046.gif

Чтение байта чтото подобное
3state-systems
bb-offtopic.gif
а где сдесь модераторы?, можно эту тему перенести обратно в ветку AVR, то в этой чета хоть и начинающим, но както широкого плана вопросы, например передача энергии без проводов и влияние чернобыля на курапаток smile.gif
там в ветке AVR спецов валом blush.gif


Сергей Борщ Большой респект за помошь 1111493779.gif
Сергей Борщ
Для начала отступление: я вас обманул. Вот тут:
Цитата(Сергей Борщ @ Apr 12 2007, 21:45) *
точно также как и в I2C, в 1-wire нельзя выдавать единицу на вывод.
То есть про I2C - чистая правда, там нельзя. А в 1-wire почти правда. Нельзя выдавать единицу во время обмена. А между битами можно и в случае устройств типа термометров с паразитным питанием даже нужно. Поэтому возвращаемся к "100пудовым подпрограммам" и правим:
Код
   Restart:            ;Сброс всех устройств
;     линия уже была настроена на вывод между обращениями
     cbi DataPort+2,DataPin;PORTx = 0, посадить линию в 0
     rcall delay480;задержка в 480мкс
     cbi DataPort+1,DataPin;Настроить линию на вход = отпустить линию
     rcall delay70        ;задержка в 70мкс
     clt                    ;Очистить флаг Т регистра Sreg 0 = Все нормально
     sbic DataPort, DataPin;Пропустить следущию команду если бит равен "0"
     set                    ;Записать "1" в регитр Sreg флаг Т=1 - нет устройств на шине
     rcall delay410    ;задержка в 410мкс
     sbi DataPort+2,DataPin;PORTx = 1, подготовить к паразитному питанию
     sbi DataPort+1,DataPin;DDRx = 1, Настроить линию на выход - подать паразитное питание
    ret

ExchangeBit:;Передаваемый бит в T
                            ; линия настроена на вывод между обменами
     cbi DataPort+2,DataPin;PORTx = 0, посадить линию в 0
;     sbi DataPort+1,DataPin;DDRx = 1, Настроить линию на выход - посадить линию в 0

     ...........

      rcall delay45    ;задержка в 45мкс
;          cbi DataPort+1,DataPin;Настроить линию на вход = отпустить линию
     sbi DataPort+2,DataPin;PORTx = 1, подготовить к паразитному питанию
     sbi DataPort+1,DataPin;DDRx = 1, Настроить линию на выход - подать паразитное питание
     rcall delay10;задержка 10мкс - пауза между битами
     ret; возврат из подпрограммы. В флаге T - считанный бит
Цитата(3state-systems @ Apr 13 2007, 16:18) *
Часа два разбирался с вашей универсальной подпрограммой обмена битами, вроде разобрался но для новичка конечно это жесть smile.gif
Зато посмотрите насколько она короче. Когда вы будете писать для I2C или SPI вы сможете использовать эту же идею и снова получить компактную и при этом быструю подпрограмму. Если в 1-wire скорость большой роли не играет (все равно в задержках сидим), то I2C и SPI уже достаточно шустрые интерфейсы. Да и вообще, мало ли где такой прием пригодится.
Цитата(3state-systems @ Apr 13 2007, 19:35) *
Чтот у мня цикл взбунтовался не работает smile3046.gif
Ну цикла я тут не увидел, но обратите внимание, что по brcs Writebit1 вы уходите в подпрограмму, а дойдя до ее ret вы вернетесть не туда, откуда вызвали Writebit1, а туда, откуда вызвали WriteByte, ведь вы использовали не RCALL для вызова Writebit1.

А я вам подкину еще одну мысль: В теперешнем варианте вы берете бит
Цитата
Код
lsr Bytebus;Сдвинуть байт вправо ->С (Флаг переноса регистра Sreg)
и выясняете через какую ветвь зайти в ExchangeBit чтобы загрузить правильное значение в флаге T. Так почему бы не переписать ExchangeBit чтобы он ожидал и возвращал бит сразу в флаге С? Тогда цикл ExchangeByte будет выглядеть совсем просто:
Код
.def Counter=R16;Счетчик бит
.def ByteBus =R20;Байт для передачи\приема 1-wire bus
ExchangeByte:
     ldi Counter, 8
Loop:
     rol    ByteBus; очередной передаваемый бит выдвинуть в C, принятый из С в ByteBus
     RCALL ExchangeBit
     dec   Counter
     BNE  Loop
     rol    ByteBus;задвинуть последний принятый бит
     ret
Цитата(3state-systems @ Apr 13 2007, 19:35) *
Чтение байта чтото подобное
Еще проще.Перед ExchangeByte дописать:
Код
ReadByte:
     LDI  ByteBus, 0xFF
WriteByte:
ExchangeByte:
      .............
"По-моему так!" (с)Винни-Пух.
Кто-нибудь покритикует?Кстати, нашел как сэкономить одну команду в ExchangeBit:
Код
вместо
    clt                               ;Очистить флаг Т
    sbic DataPort,DataPin   ;Пропустить следущию команду если линия притянута к 0
    set
сделать
    sbis DataPort,DataPin;Пропустить следущию команду если линия притянута к 1
    clt                        ;Очистить флаг Т
Можете объяснить почему? wink.gif
zltigo
Цитата(3state-systems @ Apr 13 2007, 21:19) *
там в ветке AVR спецов валом

Полагаете им будет интересно в 1002... раз на этом форуме обсуждать 1-wire (какое отношение он вообще а AVR имеет?) в перемешку с еще более "глобальными" проблемами и начальным введением в программирование?
Те, кто имеет силы и время, поверьте, заходят и в этот раздел.
3state-systems
Цитата
но обратите внимание, что по brcs Writebit1 вы уходите в подпрограмму, а дойдя до ее ret вы вернетесть не туда, откуда вызвали Writebit1, а туда, откуда вызвали WriteByte, ведь вы использовали не RCALL для вызова Writebit1.

Вай, так и есть, подводный камень smile.gif
Я то думал что у мня цикл уходит в бесконечность
ldi temp, 8
loop:
dec temp
nop
brne loop

Разбираюсь дальше.....
3state-systems
Так вот вторая версия ОБМЕН БАЙТОМ
Код
ReadByte:            ;Чтение байта  
LDI ByteBus,0xFF  ;Запись всех еденичек, потому что при чтении и при записи 1, одинаковые слоты
WriteByte:            ;Запись байта     
ldi Counter,8      
Loop:
ror ByteBus        ;Очередной передаваемый бит выдвинуть в C, сдвиг регистра вправо
RCALL ExchangeBit;Принятый из С в ByteBus
dec Counter;Уменьшаем счетчик цикла
ror ByteBus        ;Задвинуть последний принятый бит
brne Loop             ;Цикл пока счетчик не стал равен 0
ret

Надо использовать не rol - сдвиг регистра влево, а ROR -сдвиг регистра вправо
помоему обмен битами на шине идет от младшего к старшему"

теперь надо переделать обмен битами на флаг С
А я не понял получается надо всегда подавать единичку на выход иначе например у термометра с паразитным питанием, кончится заряд и он отключится, чет я совсем запутался может ну его нафиг паразитное питание?
Сергей Борщ
Цитата(3state-systems @ Apr 15 2007, 10:09) *
Надо использовать не rol - сдвиг регистра влево, а ROR -сдвиг регистра вправо помоему обмен битами на шине идет от младшего к старшему"
Да, тут я ошибся. А последнюю команду сдвига вы напрасно перенесли в цикл: у меня сдвиг происходил 8 раз внутри цикла и один раз после цикла (потому что во время первого сдвига еще не был принят бит), а у вас получился сдвиг 16 раз
Цитата(3state-systems @ Apr 15 2007, 10:09) *
А я не понял получается надо всегда подавать единичку на выход иначе например у термометра с паразитным питанием, кончится заряд и он отключится, чет я совсем запутался может ну его нафиг паразитное питание?
Да, питание надо постоянно подавать между битами. А в чем сложности? Я же это реализовал в предыдущем сообщении.
3state-systems
Цитата(Сергей Борщ @ Apr 15 2007, 11:45) *
Да, тут я ошибся.Да, питание надо постоянно подавать между битами. А в чем сложности? Я же это реализовал в предыдущем сообщении.

А ну я только сейчас буду разбираться в коде, у мня на вскидку не получается пока понять сразу как работает blush.gif

Цитата
А последнюю команду сдвига вы напрасно перенесли в цикл: у меня сдвиг происходил 8 раз внутри цикла и один раз после цикла (потому что во время первого сдвига еще не был принят бит), а у вас получился сдвиг 16 раз

ой, напортачил smile.gif

Код
Restart:                       ;Сброс всех устройств
sbi DataPort+1,DataPin;DDRx = 1, Настроить линию на выход
cbi DataPort+2,DataPin;PORTx = 0, посадить линию в 0

я добвил команду вначале на настройку порта на вывод, у вас написано было что уже настроена на выход, так этож первая команда перед началом обмена, линия еще не настроена.

А еще вопрос
Код
sbi DataPort+2,DataPin;PORTx = 1, подготовить к паразитному питанию
sbi DataPort+1,DataPin;DDRx = 1, Настроить линию на выход - подать паразитное питание

такой порядок следования, может наоборот? сначала настроить на выход а потом подавать единичку.
или без разницы
3state-systems
Код
ExchangeBit:                    ;Обмен битом передаваемый\принимаемый бит в C
                                      ;Линия настроена на вывод между обменами
cbi DataPort+2,DataPin   ;PORTx = 0, посадить линию в 0
rcall delay6                    ;Задержка в 6мкс
brcc Write_0                   ;Если передается ноль - оставить ногу посаженной в 0
cbi DataPort+1,DataPin   ;Настроить линию на вход = отпустить линию
  Write_0:
  rcall delay9                   ;задержка до точки чтения
  clc                               ;Очистить флаг C
  sbic DataPort,DataPin    ;Пропустить следущию команду если линия притянута к 0
  sec                   ;Установить флаг C
  rcall delay45                ;Задержка в 45мкс
  sbi DataPort+1,DataPin ;DDRx = 1, Настроить линию на выход - подготовить к паразитному питанию
  sbi DataPort+2,DataPin ;PORTx = 1,подать паразитное питание
  rcall delay10                ;Задержка 10мкс - пауза между битами
ret

Вот вроде так должно быть, как все упростилось
только вот brcc Write_0 почемуто в симуляторе AVRStudio все время прыгает на метку при любом флаге С(SREG)

Цитата
Conditional relative branch. Tests the Carry flag © and branches relatively to PC if C is cleared. This instruction branches relatively to PC in either direction (PC - 63 ≤ destination ≤ PC + 64). The parameter k is the offset from PC and is represented in two's complement form. (Equivalent to instruction BRBC 0,k).

А еще в стандарте написано что длительность слота может быть от 60-120мкс
у нас получается 60мкс потом мы дрыгаем ногой на паразитное питание и доводим слот до 70мкс
может лучше 70мкс
rcall delay10 ;Заполняем слот до 70мкс
sbi DataPort+1,DataPin ;DDRx = 1, Настроить линию на выход - подготовить к паразитному питанию
sbi DataPort+2,DataPin ;PORTx = 1,подать паразитное питание
rcall delay10 ;Задержка 10мкс - пауза между битами
Сергей Борщ
Цитата(3state-systems @ Apr 15 2007, 10:18) *
я добвил команду вначале на настройку порта на вывод, у вас написано было что уже настроена на выход, так этож первая команда перед началом обмена, линия еще не настроена.
Да, наверное так будет правильно.
Цитата(3state-systems @ Apr 15 2007, 10:18) *
такой порядок следования, может наоборот? сначала настроить на выход а потом подавать единичку.или без разницы
Если мы передавали нолик, то разницы никакой. А если единицу, то получится что мы в начале бита притянули линию к нулю (начали обмен), потом перевели порт в третье состояние (на линии единица от подтяжки), теперь если мы сначала настраиваем линию на вывод у нас она снова притянется к нулю, а уже потом мы ее поставим в 1. Получится лишний импульс, который нам совсем не нужен.
Цитата(3state-systems @ Apr 15 2007, 14:25) *
только вот brcc Write_0 почемуто в симуляторе AVRStudio все время прыгает на метку при любом флаге С(SREG)
Нет под рукой AVRStudio, чтобы проверить. В понедельник. А delay9 случайно флаг С не портит?
Цитата(3state-systems @ Apr 15 2007, 14:25) *
А еще в стандарте написано что длительность слота может быть от 60-120мкс
у нас получается 60мкс потом мы дрыгаем ногой на паразитное питание и доводим слот до 70мкс
может лучше 70мкс
Можно и так, для надежности.
3state-systems
Цитата(Сергей Борщ @ Apr 15 2007, 15:55) *
А delay9 случайно флаг С не портит?Можно и так, для надежности.

Задержки пока еще не реализованные, тоесть сразу ret
Цитата
Получится лишний импульс, который нам совсем не нужен.

Высший пилотаж a14.gif , как все продуманно!

Тоесть у нас почти(исправить бяку с условием) готовые 100пудовые программы для обмена битами и байтами по шине 1-wire!
Следущий уровень сетевой

READ ROM (ЧТЕНИЕ ПЗУ) 33H Идентификация
SKIP ROM (ПРОПУСК ПЗУ) CCH Пропуск адресации
MATCH ROM (СОВПАДЕНИЕ ПЗУ) 55H Адресация подчиненного устройства
SEARCH ROM (ПОИСК ПЗУ) F0H Получение идентификационных данных о всех стройствах на шине
OVERDRIVE SKIP ROM 3CH Ускоренная версия SKIP ROM
OVERDRIVE MATCH ROM 69H Ускоренная версия MATCH ROM

Разбираюсь как работают эти команды...
3state-systems
Так вот что получилось
Сетевой уровень бета подпрограмки
Еще надо реализовать проверку флага Т после сброса на наличие ошибки в линии
Код
SkipROM:               [color=#FF0000];Пропуск ПЗУ[/color]
rcall Restart        ;Сброс всех устройств на шине
ldi ByteBus,0xCC  ;Загрузка кода команды
rcall WriteByte;Запись команды на шину
ret
        
ReadROM:                  [color=#FF0000];Чтение ПЗУ [/color]
rcall Restart            ;Сброс всех устройст на шине
ldi ByteBus,0x33    ;Загрузка кода команды
rcall WriteByte      ;Запись команды на шину
LDI R30,low(idROM)  ;Младший байт - В регистровую пару грузим адрес первой ячейки куда            
LDI R31,high(idROM) ;Старший байт
LDI Counter,8         ;Организуем цикл на принятие 64бит Id кода
ReadLoop:          ;Цикл
  rcall ReadByte     ;Читаем один байт
  st Z+,Bytebus             ;Сохраняем в Памяти, указатель увеличиваем на 1
  dec Counter         ;Уменьшаем счетчик цикла
Brne ReadLoop    ;Цикл пока счетчик не стал равен 0
ret
    
MatchROM:                  [color=#CC0000];Совпадение ПЗУ[/color]
rcall Restart          ;Сброс всех устройст на шине
ldi ByteBus,0x55;Загрузка кода команды
rcall WriteByte     ;Запись команды на шину
LDI R30, low(idROM);Младший байт - В регистровую пару грузим адрес первой ячейки
LDI R31, high(idROM);Старший байт
LDI Counter,8        ;Организуем цикл на запись 64бит Id кода в шину
ReadLoop:         ;Цикл
  ld Z+,Bytebus        ;Загружаем в ригистр из Памяти, указатель увеличиваем на 1
  rcall WriteByte     ;Пишем один байт
  dec Counter             ;Уменьшаем счетчик цикла
Brne ReadLoop    ;Цикл пока счетчик не стал равен 0
ret


Ну и осталась самая мудренная из всех команд
SEARCH ROM (ПОИСК ПЗУ) F0H Получение идентификационных данных о всех стройствах на шине
есть пошаговая инструкция на русском и блок схема работы этой команды
очень сложная команда и не понятно где хранить id микросхем неужели в EEPROM?
от этой реализации команды изменится и алгоритм работы MatchROM

Сергей Борщ огромное спасибо за помощь новичкам!
Разбираюсь с задержками... может таймеры?
Сергей Борщ
Цитата(3state-systems @ Apr 17 2007, 16:54) *
Разбираюсь с задержками... может таймеры?
А смысл? Таймер имело бы смысл использовать если процессору есть еще чем заниматься. Тут же тупого цикла вполне достаточно.
3state-systems
Цитата(Сергей Борщ @ Apr 17 2007, 19:44) *
А смысл? Таймер имело бы смысл использовать если процессору есть еще чем заниматься. Тут же тупого цикла вполне достаточно.

Ну занять процессор всегда надется чем biggrin.gif
У нас задержки по 0,5сек уже есть, например на транспортном уровне есть команда начать преобразование температуры в код так там задержка 1секунда
При таком подходе я даже состояние кнопки не смогу прочитать sad.gif
как быть?
Сергей Борщ
Цитата(3state-systems @ Apr 18 2007, 09:40) *
команда начать преобразование температуры в код так там задержка 1секунда
Стоп. О каких задержках речь шла? Я имел ввиду 480, 70, 10, 7 и т.д. мкс.
3state-systems
Цитата(Сергей Борщ @ Apr 18 2007, 18:42) *
Стоп. О каких задержках речь шла? Я имел ввиду 480, 70, 10, 7 и т.д. мкс.


Ой, на работе запарился, почему то подумал что Сброс 480мс twak.gif
Если "мкс" тогда ладно будет лучше простыми Nop в цикле.
xemul
По окончании ResetPulse мастер по-любому не должен выдавать 1 на шину - слэйв ведь должен еще и ответить.
При работе с устройствами с паразитным питанием обмен происходит вполне обычно, и только после выдачи мастером конкретному слэйву команды, требующей усиленного питания (Strong Pull-Up, SPU в даташитах), мастер должен его обеспечить на время, достаточное для выполнения слэйвом этой команды. Ну и для универсальности можно предварительно убедиться, требуется ли слэйву этот самый SPU.
Задержки на 480 мкс пустыми циклами... Счастливые людиsmile.gif.
3state-systems
Цитата(xemul @ Apr 19 2007, 10:51) *
По окончании ResetPulse мастер по-любому не должен выдавать 1 на шину - слэйв ведь должен еще и ответить.
При работе с устройствами с паразитным питанием обмен происходит вполне обычно, и только после выдачи мастером конкретному слэйву команды, требующей усиленного питания (Strong Pull-Up, SPU в даташитах), мастер должен его обеспечить на время, достаточное для выполнения слэйвом этой команды. Ну и для универсальности можно предварительно убедиться, требуется ли слэйву этот самый SPU.
Задержки на 480 мкс пустыми циклами... Счастливые людиsmile.gif.


Согласен, помоему мы так и реализовали нашу подпрограмму.
Импульс сброса подсаживаем линию на 480мкс, отпускаем линию
Каждое slave устройство обнаружив импульс сброса выдерживает паузу 15-60мкс
затем подсаживает линию Длительность присутствия составляет 60-240мкс
Сигналы присутствия от всех устройств сливаются в один общий импульс (Логика монтажная ИЛИ)
Мастер проверят наличие нулевого уровня в середине этого интервала если линия подсажена значит на шине имеется хотябы одно нормально работающие устройство.
А только потом подаем паразитное питание.
xemul
Цитата(3state-systems @ Apr 19 2007, 16:18) *
Согласен, помоему мы так и реализовали нашу подпрограмму.
...
А только потом подаем паразитное питание.

Извините, последовательность правильно, недоглядел.
Ну а необходимо ли выдывать SPU после любой операции, решать Вам.

ЗЫЖ паразитное питание уже присутствует. Вы выдаете усиленный паекsmile.gif
ЗЗЫЖ чуть попозже перепишу ванварь с пиков под аврки для gcc. Под задержки будет использоваться TMR0). Сорцы закину в соответствующую тему.
3state-systems
Цитата(xemul @ Apr 19 2007, 17:45) *
ЗЗЫЖ чуть попозже перепишу ванварь с пиков под аврки для gcc. Под задержки будет использоваться TMR0). Сорцы закину в соответствующую тему.


Так там уже реализована эта библиотека для AVR только под компилятор IAR может проще ее переделать

Автор SasaVitebsk
Цитата
Исследовал работу нескольких DS18B20/DS1820 "сидящих" на одной шине, а также возможность динамического подключения/замены данных датчиков на шине. Не нашёл. Некоторые библиотеки, в том числе выложенные на этом форуме являются нерабочими. Написал библиотеки, проверил и выложил их в виде библиотек в соответствующем разделе форума.

Подключается несколько датчиков DS1820/ds18b20/ds18s20 в любом сочетании. На LCD дисплей выводится их количество и температура каждого. Допустимо подключения датчиков по двух-проводной схеме включения. Используется динамическое выделение памяти под ROM датчиков.

http://electronix.ru/forum/index.php?act=S...10&t=23814#
xemul
Цитата(3state-systems @ Apr 19 2007, 17:40) *
Так там уже реализована эта библиотека для AVR только под компилятор IAR может проще ее переделать

Автор SasaVitebsk

http://electronix.ru/forum/index.php?act=S...10&t=23814#

Я видел эти сорцы. Как уже сказал, завидую людям, которые могут позволить себе завесить контроллер на 480 мкс в пустом цикле. Опять же сказал, что все задержки будут реализованы на прерываниях TMR0.
На пиках с 1 МИПС у меня и мастер, и слэйв ванварные в фоне крутятся, а контроллеры друг с другом в шахматы по переписке играютsmile.gif. Нечто подобное сделаю и под авр, тем более что и заказ с ванварью, похоже будет.
3state-systems
Так вот что у нас получилось
Половина пути уже пройдена smile.gif
Тестируйте, ищите ошибки, высказывайте свои замечания и дополнения blush.gif
Svin62
bb-offtopic.gif
Граждане! А кто-нить пробовал, вместо таблетки, ну которой двери открывают, подключать считыватель proximity-карт?
Чёта у меня это дело не заработало, хотя таблетки читает нормально...
Может там по другому надо читать, хотя они вроде должны эмулировать таблетку. help.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.