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

 
 
3 страниц V   1 2 3 >  
Reply to this topicStart new topic
> 1-wire Интерфейс, Assembler'ные подпрограмы для начинаюших
3state-systems
сообщение Apr 11 2007, 19:48
Сообщение #1


Участник
*

Группа: Новичок
Сообщений: 18
Регистрация: 11-04-07
Из: Россия, Бурятия, Улан-Удэ
Пользователь №: 26 954



Здравствуйте,
Изучаю микроконтроллеры для себя, решил изучить интерфейс 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


Сообщение отредактировал 3state-systems - Apr 11 2007, 19:48
Go to the top of the page
 
+Quote Post
Kuzmi4
сообщение Apr 12 2007, 10:24
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 3 304
Регистрация: 13-02-07
Из: 55°55′5″ 37°52′16″
Пользователь №: 25 329



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);
}
Можно конечно на этой основе наварганить чтото своё, но я использую встроенные делэи - проблем и вопросов не возникало..
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Apr 12 2007, 12:46
Сообщение #3


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(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
Ваш ход.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
3state-systems
сообщение Apr 12 2007, 20:57
Сообщение #4


Участник
*

Группа: Новичок
Сообщений: 18
Регистрация: 11-04-07
Из: Россия, Бурятия, Улан-Удэ
Пользователь №: 26 954



Так сейчас закодил первый уровень
вот что получилось
Код
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, 21:07
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Apr 12 2007, 22:45
Сообщение #5


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(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)
Можно, почему бы нет?


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
3state-systems
сообщение Apr 13 2007, 09:47
Сообщение #6


Участник
*

Группа: Новичок
Сообщений: 18
Регистрация: 11-04-07
Из: Россия, Бурятия, Улан-Удэ
Пользователь №: 26 954



Цитата
Кстати, я ориентируюсь на ассемблер IAR, а вы, судя по .equ имеете ввиду avrasm2?

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

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

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

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

Полностью согласен, по даташиту - резистор, правда номинал у всех довольно сильно варьируется в топиках. но это потом у\еще уточним.
Приду домой внимательно посмотрю ваш код smile.gif
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Apr 13 2007, 12:36
Сообщение #7


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(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 нет регистра направления порта? Именно поэтому. На "честных" портах подход должен быть другим - как я описал.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
3state-systems
сообщение Apr 13 2007, 15:26
Сообщение #8


Участник
*

Группа: Новичок
Сообщений: 18
Регистрация: 11-04-07
Из: Россия, Бурятия, Улан-Удэ
Пользователь №: 26 954



Цитата
(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)
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Apr 13 2007, 16:50
Сообщение #9


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(3state-systems @ Apr 13 2007, 14:26) *
Вот тока зачем добавлять 3? wink.gif
Ну обшибся tongue.gif Регистров три? Вот и написал раз-два-три. А ведь и правда - надо было ноль-раз-два.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
3state-systems
сообщение Apr 13 2007, 17:18
Сообщение #10


Участник
*

Группа: Новичок
Сообщений: 18
Регистрация: 11-04-07
Из: Россия, Бурятия, Улан-Удэ
Пользователь №: 26 954



Часа два разбирался с вашей универсальной подпрограммой обмена битами, вроде разобрался но для новичка конечно это жесть 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 - Apr 13 2007, 17:20
Go to the top of the page
 
+Quote Post
3state-systems
сообщение Apr 13 2007, 20:35
Сообщение #11


Участник
*

Группа: Новичок
Сообщений: 18
Регистрация: 11-04-07
Из: Россия, Бурятия, Улан-Удэ
Пользователь №: 26 954



Так добрались до байт
черновой вариант такой
.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

Чтение байта чтото подобное
Go to the top of the page
 
+Quote Post
3state-systems
сообщение Apr 13 2007, 22:19
Сообщение #12


Участник
*

Группа: Новичок
Сообщений: 18
Регистрация: 11-04-07
Из: Россия, Бурятия, Улан-Удэ
Пользователь №: 26 954



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


Сергей Борщ Большой респект за помошь 1111493779.gif

Сообщение отредактировал 3state-systems - Apr 13 2007, 22:22
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Apr 14 2007, 10:37
Сообщение #13


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Для начала отступление: я вас обманул. Вот тут:
Цитата(Сергей Борщ @ 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


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
zltigo
сообщение Apr 14 2007, 11:11
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(3state-systems @ Apr 13 2007, 21:19) *
там в ветке AVR спецов валом

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


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
3state-systems
сообщение Apr 14 2007, 11:29
Сообщение #15


Участник
*

Группа: Новичок
Сообщений: 18
Регистрация: 11-04-07
Из: Россия, Бурятия, Улан-Удэ
Пользователь №: 26 954



Цитата
но обратите внимание, что по brcs Writebit1 вы уходите в подпрограмму, а дойдя до ее ret вы вернетесть не туда, откуда вызвали Writebit1, а туда, откуда вызвали WriteByte, ведь вы использовали не RCALL для вызова Writebit1.

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

Разбираюсь дальше.....
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 20th July 2025 - 10:41
Рейтинг@Mail.ru


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