Где Вы откопалиглавный колбасист писал(а):...ldi r30,0xdf
ld r20,r30
ld r20,r30
???
Вторым регистром в команде LD может быть указан X, Y или Z
или как слэнг первый регистр регистровой пары - в данном случае R31 (но уж никак не R30)
Где Вы откопалиглавный колбасист писал(а):...ldi r30,0xdf
ld r20,r30
Код: Выделить всё
ld r16,z Код: Выделить всё
#define pointer_2 z
#define tmp0 r16Код: Выделить всё
ld tmp0,pointer_2Код: Выделить всё
; ***** CPU REGISTER DEFINITIONS *****************************************
.def XH = r27
.def XL = r26
.def YH = r29
.def YL = r28
.def ZH = r31
.def ZL = r30Код: Выделить всё
#define ptrd_h XH
#define ptrd_l XLТак получается. ошибок нет.ld r20,Z
Это я сама придумала. что с меня возьмешь.Где Вы откопали
ld r20,r30
???
Конечно я не так все делаю. Я вообще не понимаю что я тут делаю.(в этой реальности)Ничего не понял. Вы что-то не так делаете.
Код: Выделить всё
1. Настройка i2c
2. i = 0
3. IIC_START i2c
4. IIC_SEND (3231_ADDR+i)
5. if (i = 0)
then begin
6. IIC_SEND 0x00 ;адрес, с которого мы будем читать данные из 3231
7. goto 16
end
else begin
8. j = 7 ; число байт, которые надо прочитать
9. Z = (адрес области памяти для чтения из 3231)
10. j = j - 1
11. if (j > 0) then IIC_READ_ASK
else IIC_READ_NASK
12. save DATA -> Z
13. Z = Z + 1
14. if (j > 0) then goto 10
15. end ; конец блока else для if (i=0)
16. i = i + 1
17. if ( i < 2 ) then goto 3
18. IIC_STOP Код: Выделить всё
;--------------------------------------------------------
; I2C Code
;--------------------------------------------------------
; по мотивам DiHalt'a
;--------------------------------------------------------
; Работа с IIC передатчиком. Предупреждаю -- это быдлокод!
; Несмотря на то, что так делают почти все :)
; Но это медленно и тормозно, особенно в свете использования
; RTOS. Почему? Да потому что использует глухое
; ожидание флага готовности IIC. Вместо того, чтобы отдать
; управление диспетчеру задач. Также нет обработоки ошибок
; и какой либо оценки прошла команда или нет. Просто пример!
;---------------------------------------------------------
; IIS_START — устраивает на шине Start состояние
; IIC_SEND — посылает байт, просто байт. Не важно что это — адрес, данные…
; IIC_READ_ASK — команда противополжная предыдущей — принимает байт в конце дает ACK
; IIC_READ_NASK — тоже принимает байт, но в конце дает NACK, используется для приема последнего байта,
; чтобы дать понять Slave устройству что мы в его услугах больше не нуждаемся.
; IIS_STOP — устраивает на шине Stop состояниеи освобождает линию
;---------------------------------------------------------
; Последовательность инициализации TWI (i2c)-интерфейса
; Рассматривается только Master-режим
; В регистр TWBR, а так же в биты 0,1 (TWPS0:1) регистра TWSR записываются константы для определения скорости шины.
; (констатны можно рассчитать на AVRCalc)
;---------------------------------------------------------
; Последовательность чтения для IIC, на примере обычной EEPROM типа АТ24Схх обычно такая:
; Старт
; Адрес дейвайса[write]
; Адрес ячейки откуда будем читать
; Повторный Старт,
; Адрес девайса [read],
; Байт из адресованой ячейки,
; Байт из адресованой ячейки+1,
; Байт из адресованой ячейки+2
; ….
; Cтоп
;
; Последовательность записи для IIC обычно такая:
; Старт
; Адрес девайса [write]
; Адрес ячейки куда будем писать
; Данные раз
; Данные два
; Данные три
; …..
; Стоп
; [write] & [read] - младший бит адреса. =0 - запись, =1 - чтение
;
;---------------------------------------------------------
; примеры для работы с часами - см. http://easyelectronics.ru/chasy-realnogo-vremeni-pcf8583.html
;---------------------;
; Даем старт на линию I2C
; Портит R16,SREG
IIC_START:
LDI R16,1<<TWINT|1<<TWSTA|1<<TWEN|0<<TWIE
OUT TWCR,R16
IIC_S:
IN R16,TWCR
ANDI R16,1<<TWINT
BREQ IIC_S ; Ждем пока передатчик IIC выполнит старт
RET
;-----------------------------------------------------------------------------
;Посылаем байт (R16) по IIC
; Портит R16,SREG
IIC_SEND:
OUT TWDR,R16
LDI R16,1<<TWINT|1<<TWEN|0<<TWIE
OUT TWCR,R16
IIC_B:
IN R16,TWCR
ANDI R16,1<<TWINT ; Ждем пока передатчик пошлет байт
BREQ IIC_B
RET
;-----------------------------------------------------------------------------
; Принять байт.
; Принятый байт в R16
; Портит SREG
IIC_READ_ASK:
LDI R16,1<<TWINT|1<<TWEN|1<<TWEA|0<<TWIE
OUT TWCR,R16
IIC_R:
IN R16,TWCR
ANDI R16,1<<TWINT
BREQ IIC_R ; Ждем пока байт будет принят
IN R16,TWDR
RET
;-----------------------------------------------------------------------------
; Принять последний байт. Помните я писал о разнице между просто байтом и последним
; байтом? В последнем байте не генерируется ACK!!!
; Принятый байт в R16
; Портит SREG
IIC_RREAD_NACK:
LDI R16,1<<TWINT|1<<TWEN|0<<TWEA|0<<TWIE
OUT TWCR,R16
IIC_R2:
IN R16,TWCR
ANDI R16,1<<TWINT ; Ждем пока байт будет принят
BREQ IIC_R2
IN R16,TWDR
RET
;-----------------------------------------------------------------------------
; Сгенерировать STOP
; Портит R16,SREG
IIC_STOP:
LDI R16,1<<TWINT|1<<TWSTO|1<<TWEN|0<<TWIE
OUT TWCR,R16
IIC_ST:
IN R16,TWCR
ANDI R16,1<<TWSTO
BREQ IIC_ST ; Ждем пока не будет готов стоп.
RET
Я не спорю, метод простой, рабочий и широко распространённый. Но я занимаюсь программированием не для комерции, а ради высокого искусства. Вот захотелось сделать на прерываниях, а оно для I2C одно. Вот и сгородил такой лабиринт.Работа с IIC передатчиком. Предупреждаю -- это быдлокод!
Несмотря на то, что так делают почти все![]()
Но это медленно и тормозно, особенно в свете использования
RTOS. Почему? Да потому что использует глухое
ожидание флага готовности IIC.
абсолютно верно! ни коллизий, ни потерь битов в правильно сконструированном девайсе на шине I2C быть не может! и нужды в анализе этих битов нет никакой. от слова совсем.GoldenAndy писал(а):Обычно i2c-устройства - это не plug'n'play, а запаянные на плату конкретные устройства. И при исправности всех устройств обмен по шине не должен выдавать ошибки.
как я неоднократно утверждал в разных других темах, реальная необходимость действительно параллельно что-то делать в любительских проектах возникает крайне-крайне-крайне редко. более того, после реализации этой "истинной" параллельности обычно оказывается, что никакого выигрыша нет вообще, только напрасно потраченное время. но это моё мнение, оно может не совпадать с мнением редакцииGoldenAndy писал(а):Если уже параллельно процессу обмена нужно что то выполнять
и тут согласен на все 100%.GoldenAndy писал(а):проще всего эти задержки делать на тупых циклах
Ну, тут нужно заложить какой то гипотетический случай на выход из строя i2c-ведомого устройства.... Но с этим прекрасно справится таймаут ожидания - делается на одном регистре и трех ассемблерных командах (пишу по памяти, но могу и криво написать, на асме очень давно не писал, в основном голый Си)ARV писал(а):ни коллизий, ни потерь битов в правильно сконструированном девайсе на шине I2C быть не может!
У меня такое было всего один раз. Когда приходилось читать по i2c из INA219 1000 раз в сек попеременно значения тока и напряжения, класть их в буфер и обрабатывать. И это была основная задача - там действительно пришлось использовать прерывание и конечный автомат. Таймер дергал старт обмена, а конечник в прерывании i2c обрабатывал всю лог.цепочку. При этом в прерывании таймера обрабатывались значения тока и напряжения из предыдущего цикла. И это была основная задача МК. А оставшееся от всей этой кухни время - это формирование изображения для дисплея, вывод его по SPI через DMA. По второму i2c был обмен с EEPROMкой внешней, но он редкий, там настройки живут и калибровочные константы. Тут уже былл обмен на ожиданиях, ибо основная задача работает реалтаймово на прерываниях.ARV писал(а):реальная необходимость действительно параллельно что-то делать в любительских проектах возникает крайне-крайне-крайне редко