Пт янв 07, 2022 14:42:42
Пт янв 07, 2022 15:04:05
я очень дико извиняюсь - о каких ожиданиях вы тут говорите? если я правильно помню, то в и2ц после того, как сделал нужный фронт SCL, можно сразу читать SDA - задержки там будут настолько малые, что ожидания не потребуется. возможно, один NOP... и то не уверен, что на самом деле необходимо. (давно с и2ц работал, пишу по воспоминаниям)GoldenAndy писал(а):Ведомый отозвался - ура, работаем на ожиданиях.
Пт янв 07, 2022 15:23:07
Пт янв 07, 2022 15:28:53
;
; "av_i2c.txt" файл обработчика шины I2C
; лаподрыг под AVR при системной частоте 1МГц
; (0,000001S/одноцикловая команда)
;
;----------
; заготовка программного модуля
; для обработки кристаллов с интерфейсом I2C
; асинхронный режим обмена,
; вплоть до полного останова в процессе работы.
; линии данных и строба настроены на вход с Z
; при внешнем подтягивающем резисторе
; (статус МК по умолчанию после сброса при подаче питания)
;
; ---------- константы/флаги ----------
;
.equ i2c_sda = 7 ; позиционный номер линии SDA
.equ i2c_scl = 6 ; позиционный номер линии SCL
.equ i2c_sqw = 2 ; позиционный номер линии SQVOUT
.equ f_Ai2c = 0 ; интерпритатор статуса сигнала ACK
.equ f_Ei2c = 1 ; флаг ошибки обмена
.equ i2c_t4 = 8 ; интервал задержки
; 1/4 длительности строб-импульса приема/передачи
.equ i2c_dcte = 5 ;0x5F ; константа для счетчика интервала ошибок
;
;----------
;
;таблица обьявленных имен - переназначение регистров РОН
#ifndef disposit
;
; принята базовая модель:
; область ограниченного функционала
; .def mfr0 = r0 ;(математика и обмен с ПЗУ/самопрограммирование)
; .def mfr1 = r1 ;(математика и обмен с ПЗУ/самопрограммирование)
; .def s_sreg = r2 ; зеркало SREG(ограниченный функционал)
; .def sys_flag = r3 ; системные флаги(ограниченный функционал)
; .def = r4 ;(ограниченный функционал)
; .def = r5 ;(ограниченный функционал)
; .def = r6 ;(ограниченный функционал)
; .def = r7 ;(ограниченный функционал)
;
; .def = r8 ;(ограниченный функционал)
; .def = r9 ;(ограниченный функционал)
; .def = r10 ;(ограниченный функционал)
; .def = r11 ;(ограниченный функционал)
; .def = r12 ;(ограниченный функционал)
; .def = r13 ;(ограниченный функционал)
; .def = r14 ;(ограниченный функционал)
; .def = r15 ;(ограниченный функционал)
;
; область полного функционала
.def tmp0 = r16 ; рабочий регистр(полный функционал)
.def tmp1 = r17 ; рабочий регистр(полный функционал)
.def tmp2 = r18 ; рабочий регистр(полный функционал)
.def tmp3 = r19 ; рабочий регистр(полный функционал)
.def tmp4 = r20 ; рабочий регистр(полный функционал)
.def tmp5 = r21 ; рабочий регистр(полный функционал)
.def tmp6 = r22 ; рабочий регистр(полный функционал)
.def tmp7 = r23 ; рабочий регистр полный функционал)
;
.def Bl = r24 ; "указатель базы"(полный функционал)
.def Bh = r25 ; "указатель базы"(полный функционал)
; Xl = r26 ; адрес сегмента Х (полный функционал)
; Xh = r27 ; адрес сегмента Х (полный функционал)
; Yl = r28 ; адрес сегмента Y (полный функционал)
; Yh = r29 ; адрес сегмента Y (полный функционал)
; Zl = r30 ; адрес сегмента Z (полный функционал ПЗУ/самопрограммирование)
; Zh = r31 ; адрес сегмента Z (полный функционал ПЗУ/самопрограммирование)
; регистры Xh:Xl, Yh:Yl, Zh:Zl определены в дефайне изготовителя и в системе команд
; изменение их имени хотя и возможно, но нежелательно -
; возникает путаница с интегрированной абревиатурой системы команд
; в случае с "малой моделью" допускающей/достаточной для размещения ВСЕХ
; используемых ВСЕМИ подпрограммами регистров в области СОЗУ регистрового
; файла одновременно (без "подкачки" наборов параметров через ОЗУ)
; рекомендовано переназначение индивидуальных имен регистров
; согласно текущей задачи
;
#endif
;
;----------
; секция переназначения регистров или портов РСФ
;
;----------
; !!! порты требуется указать в соответствии с конкретной схемой !!!
;
#define i2c_ddr DDRB ; переприсвоение регистра режима порта DDRх
#define i2c_port PORTB ; переприсвоение регистра порта PORTх
#define i2c_pin PINB ; переприсвоение регистра выводов порта PINх
;----------
#define i2c_dat tmp0 ; буфер ввода/вывода данных
#define i2c_cntb tmp1 ; счетчик бит ввода/вывода
#define i2c_tm tmp2 ; счетчик задержки 1/4 стробимпульса
#define i2c_cnte tmp3 ; счетчик ошибок обмена/ожидания ответа
#define i2c_flag tmp4 ; флаги протокола обмена
; #define i2c_adrl tmp5 ; буфер младшей части начального/целевого адреса
;
;----------
;
; ----- собственно утилиты -----
;
.CSEG
;----------
; отработка интервала 1/4 длительности
; строб-импульса приема/передачи
;
tm4i:
ldi i2c_tm,i2c_t4 ;
l_tm4i:
dec i2c_tm ;
brne l_tm4i
ret
;
;----------
; stop2 - п/п генерации стоп-условия для шины и2с
; эта же программа при необходимости выполняет функционал
; "горячей переинициализации" (reinit)
;
;вызов acall stop2 , используемый регистр tm2i, передаваемых
;параметров нет, при входе:
; i2c_sda=?
; i2c_scl=0
; по выходу i2c_sda=i2c_scl=Z&1
;
stop2:
sbi i2c_ddr,i2c_sda ; line i2c_sda=0 страховка
rcall tm4i ;
cbi i2c_ddr,i2c_scl ; line i2c_scl=Z&1
rcall tm4i ;
rcall tm4i ;
cbi i2c_ddr,i2c_sda ; line i2c_sda=Z&1
rcall tm4i ;
ret
;
;----------
; restar - "повторный старт" (Sr-условие) протокола I2C
;
;(желательно разместить в блоке п/п работы
; с I2C, чтобы избежать "длинные"
; вызовы для субблоков strob)
;
restar:
cbi i2c_ddr,i2c_sda ;line i2c_sda=Z&1 ; страховка
rcall tm4i ;
lwait:
sbis i2c_pin,i2c_sda ; ждем подтверждение ведомого
rjmp lwait ; line i2c_sda=1
rcall tm4i ;
cbi i2c_ddr,i2c_scl ; line i2c_scl=Z&1
rcall tm4i ;
;----------
; start2 - п/п генерации старт-условия для шины и2с
; является завершающей частью подпрограммы restar
;вызов rcall start2 , используемый регистр i2c_tm, передаваемых
;параметров нет, по умолчанию исходно:
; i2c_ddr.i2c_sda = 0
; i2c_port.i2c_sda = 0
; line i2c_sda = Z&1
; i2c_ddr.i2c_scl = 0
; i2c_port.i2c_scl = 0
; line i2c_scl = Z&1
; по выходу line i2c_sda = line i2c_scl = 0
;
start2:
rcall tm4i ;
sbi i2c_ddr,i2c_sda ;line i2c_sda=0
rcall tm4i ;
rcall tm4i ;
sbi i2c_ddr,i2c_scl ;line i2c_scl=0
rcall tm4i ;
ret
;
;----------
; ---- strob SCL ----
;
strob2i:
rcall tm4i ;acall tm4i
cbi i2c_ddr,i2c_scl ; line i2c_scl=Z&1
rcall tm4i ;acall tm4i
rcall tm4i ;acall tm4i
sbi i2c_ddr,i2c_scl ; line i2c_scl=0
rcall tm4i ;acall tm4i
ret
;
;----------
; rxb2 - программа для приема байта по протоколу и2с
;
; вызов = rcall rxb2
; статус ACK=0 генерируется в случае,
; если перед вызовом rxb2 был установлен
; f_Ai2c=1 (последний в текущем пакете rxb2
; устанавливает статус ACK=1(NO_ACK) при f_Ai2c=0 )
; по выходу
; i2c_dat = принятый байт
; i2c_sda=Z&1(1), i2c_scl=0
;
rxb2:
ldi i2c_cntb,8 ; загрузить счетчик бит приемника
cbi i2c_ddr,i2c_sda ; ориентировать line i2c_sda(как вход)=Z&1
nop ;
nop ;
loopr2:
rcall tm4i ;acall tm4i ; задержка в 1/4 строб-импульса
cbi i2c_ddr,i2c_scl ; line i2c_scl=Z&1 начало строб-импульса
rcall tm4i ; задержка в 1/4 строб-импульса
sbis i2c_pin,i2c_sda ; читать текущий статус line i2c_sda
clc
sbic i2c_pin,i2c_sda
sec
rol i2c_dat ; продвижка i2c_dat влево
rcall tm4i ; задержка в 1/4 строб-импульса
sbi i2c_ddr,i2c_scl ; конец строб-импульса line i2c_sda остается=Z&1
rcall tm4i ; задержка в 1/4 строб-импульса
dec i2c_cntb ; счетчик бит ввода/вывода -1
brne loopr2 ; повторять до исчерпания i2c_cntb
sbrc i2c_flag,f_Ai2c ; если i2c_flag.f_Ai2c=0 продолжить от noack
rjmp off0 ; если i2c_flag.f_Ai2c=1 то переход на off0
noack:
rcall tm4i ; задержка в 1/4 строб-импульса
rcall strob2i ; выполнить строб на line i2c_scl
rcall tm4i ; задержка в 1/4 строб-импульса
ret
off0:
cbr i2c_flag,1<<f_Ai2c ; сбросить f_Ai2c
sbi i2c_ddr,i2c_sda ; установить line i2c_sda=0
rcall tm4i ; задержка в 1/4 строб-импульса
rcall strob2i ; выполнить строб на line i2c_scl
rcall tm4i ; задержка в 1/4 строб-импульса
rcall tm4i ; задержка в 1/4 строб-импульса
cbi i2c_ddr,i2c_sda ; установить line i2c_sda=Z&1
nop ;
nop ;
ret
;
;----------
; txb2 - программа для передачи байта по протоколу и2с
;
; вызов = rcall txb2
; перед вызовом txb2 разместить
; в i2c_dat пересылаемый байт
; фрагмент "контроль 1" по завершению ACK слэйва не
; проводится в случае, если была передана команда
; чтения данных - перед вызовом rcall txb2 был установлен
; флаг i2c_flag.f_Ai2c=1
; по выходу
; i2c_dat=0
; i2c_sda=Z&1(1), i2c_scl=0
; i2c_flag.f_Ai2c=0, i2c_flag.f_Ei2c=??
; (i2c_flag.f_Ei2c=1 в случае ошибки обмена
; типа "ведомый не отвечает")
;
txb2:
cbr i2c_flag,1<<f_Ei2c ; очистка f_Ei2c =0
ldi i2c_cnte,i2c_dcte ; загрузка счетчика интервала ошибок
ldi i2c_cntb,8 ; загрузить счетчик бит передатчика
nop ;
nop ;
loopt2:
sbi i2c_ddr,i2c_sda ; установить line i2c_sda=0 (0)
lsl i2c_dat ; текущий бит данных в СY
brcc loopt21 ; если СY=0 оставить line i2c_sda=0
cbi i2c_ddr,i2c_sda ; иначе установить line i2c_sda=Z&1 (1)
loopt21:
rcall strob2i ; тело строба передачи
dec i2c_cntb ; счетчик бит ввода/вывода -1
brne loopt2 ; повторять до исчерпания i2c_cntb
askont:
cbi i2c_ddr,i2c_sda ; установить line i2c_sda=Z&1(как вход)
lpask1:
rcall tm4i ; задержка в 1/4 строб-импульса
sbis i2c_pin,i2c_sda ; проверка на ответ ведомого (SDA=0)
rjmp eask ;jnc eask ; продолжать при line i2c_sda=0 от eask
dec i2c_cnte ; счетчик интервала ошибок -1
brne lpask1 ; продолжать от lpask1 до исчерпания с-ка повторов
extbof:
sbr i2c_flag,1<<f_Ei2c ; установить флаг ошибки обмена f_Ei2c=1
txbof:
cbr i2c_flag,1<<f_Ai2c ; контрольный сброс f_Ai2c=0
rcall tm4i ; задержка в 1/4 строб-импульса
ret ; по выходу i2c_sda=1, i2c_scl=0
eask:
ldi i2c_cnte,i2c_dcte ; перезагрузить счетчик ошибок
rcall strob2i ; тело 9-го строба передачи (поддержки сигнала AСK)
sbrc i2c_flag,f_Ai2c ; при f_Ai2c=1 проверка на ответ ведомого (SDA=1)
; НЕ ПРОВОДИТСЯ!
rjmp txbof ; переход мимо анализа ответной 1
lpask2:
rcall tm4i ; задержка в 1/4 строб-импульса
sbic i2c_pin,i2c_sda ; проверка на ответ ведомого(SDA=1)
rjmp txbof ; при нормальном завершении продолжить от TXBOFF
dec i2c_cnte ; счетчик интервала ошибок -1
brne lpask2 ; продолжать от lpask2 до исчерпания с-ка повторов
rjmp extbof ; при ошибке ответа ведомого продолжить от ETXBOF
;
;----------
Пт янв 07, 2022 15:29:50
Пт янв 07, 2022 15:32:06
Пт янв 07, 2022 16:46:38
вот сроду TWI не применял, даже не пробовал, всегда хватало программного дрыгоногаGoldenAndy писал(а):А вот чтение/запись данных - тут надо ждать, ибо формирование SCL, чтение/запись SDA делает блок TWI самостоятельно.
Пт янв 07, 2022 21:16:13
Сб янв 08, 2022 11:08:14
Пн янв 10, 2022 18:07:31
что касается последних сообщений, касающихся LD, то меня просто возмущает отсутствие желания у вопрошающего прочитать о системе команд AVR.
Пн янв 10, 2022 19:44:56
Пн янв 10, 2022 20:30:57
Пн янв 10, 2022 21:30:46
Пн янв 10, 2022 22:57:58
Вт янв 11, 2022 10:33:41
Чт янв 13, 2022 14:07:30
Чт янв 13, 2022 14:24:54
Вс янв 16, 2022 21:59:56
Вс янв 16, 2022 23:14:18
Пн янв 17, 2022 06:49:55