Страница 29 из 400
Добавлено: Пт янв 22, 2010 15:47:58
GP1
Для "плавающей" установки разряда в 1 нужно использовать or с 1 в нужном разряде, а для сброса в 0, аналогично используется команда and
Добавлено: Пт янв 22, 2010 19:18:47
Pooher
Ну, не дописал две буквы

Добавлено: Пт янв 22, 2010 19:36:09
SII
Savelek писал(а):Извините пожалуйста за возможно глупый вопрос, но что случится, если сделать логическую операцию между двумя регистрами (т.е. двумя байтами)? Ну например логическое ИЛИ. Будут поочередно сравниваться одинаковые п осчету биты двух регистров? А результат? Результат сравнения запишется в первый из сравниваемых регистров?
И еще вопрос - у Вас в коде команда "or tmp,tmp1", а в комментариях указано что это логическое И. Но ведь or это или... Да и для установки бита, наверное, нужно использовать лог. ИЛИ. Или я не прав?
Правы во всём

Для установки разрядов используется ИЛИ (or), для сброса -- И (and), для инверсии -- ИСКЛЮЧАЮЩЕЕ ИЛИ (eor). Для того, чтобы установить или сбросить разряд по его номеру, нужно сначала сформировать правильную маску. Например, если в R16 у нас номер бита (0 -- младший, 7 -- старший), то маску в R17 для установки этого бита можно сформировать так:
Код: Выделить всё
ldi R17, 1
looplab:
dec R16
brmi loopend
lsl R17
rjmp looplab
loopend:
Добавлено: Пт янв 22, 2010 20:50:00
Savelek
Логические операции действительно очень помогут в решении этой задачи, зря я про них забыл. Пойду пробовать.
Спасибо!

Инверсия
Добавлено: Вс янв 24, 2010 16:48:06
lag1
Здравствуйте!
Подскажите, пожалуйста, как можно инвертировать два (младших) разряда в регистре ввода-вывода? Если можно, на примере.
Спасибо!
Re: Инверсия
Добавлено: Вс янв 24, 2010 17:03:41
ARV
lag1 писал(а):Здравствуйте!
Подскажите, пожалуйста, как можно инвертировать два (младших) разряда в регистре ввода-вывода? Если можно, на примере.
Спасибо!
например, так:
Код: Выделить всё
in r0, PORTB ; берем содержимое PORTB
ldi r16, 3 ; берем 2 младших бита - число 3
eor r0, r16 ; инвертируем биты
out PORTB, r0 ; выводим обратно в PORTB
Инверсия
Добавлено: Вс янв 24, 2010 18:00:05
lag1
С примером стало понятно. Все работает.
Еще раз спасибо!
Добавлено: Вс янв 24, 2010 20:00:25
avreal
Ну и дополнение - для многих кристаллов можно инвертировать выход
PORT записью 1-ки в соответствующий бит
PIN
Код: Выделить всё
ldi r16, 3
out PINB, r16 ; инвертируем два младших бита в PORTB
Например, для at90s2313 и atmega8 так нельзя, для attiny2313 и atmega48/88/168 - можно.
Смотреть описание на конкретный кристалл - раздел
I/O-Ports
Искать там подраздел
Toggling the Pin
Если он вообще есть, то возможно его можно не читать

- функция доступна. Там должно быть написано такое
Writing a logic one to PINxn toggles the value of PORTxn, independent on the value of DDRxn.
Note that the SBI instruction can be used to toggle one single bit in a port.
Добавлено: Ср янв 27, 2010 21:57:45
IfoR
У меня тоже вопрос по чтению из памяти. Контроллер ATmega16
Суть: есть запись в FLASH. Нужно её считать и запихнуть в регистр.
Делаю так:
Код: Выделить всё
.CSEG
.org 0x0000 ;Reset вектор
rjmp Reset
.org 0x002A
BVB: .DW 0x2255 ;Данные
Reset:
LDI R30,LOW(BVB) ;Пишем адрес в Z регистр
LDI R31,HIGH(BVB);Всё нормально. Пишется 0x002A
LD R16,Z+ ;Читаем слово из flash
LD R17,Z
Вот тут и проблема. В R16 пишется 0x00, а R17 - 0x20 при чём независимо от значения BVB.
Что я делаю не так?

Добавлено: Ср янв 27, 2010 22:30:21
GP1
начнем с того что в меге16, как впрочем и в других АВРках, флеш-память словная, т.е. состоит из 2 байтов, и чтобы получить доступ к ячейке BVB нада писать так:
Код: Выделить всё
LDI R30,LOW(BVB*2) ;Пишем адрес в Z регистр
LDI R31,HIGH(BVB*2);Всё нормально. Пишется 0x002A*2=0х0054
lpm R16,Z+ читаем данные из flash
Lpm R17,Z
а команда LD читает данные из памяти данных, а там по адреск 0х002А находится служебный регист UCSR0B=0х00 а по адресу 0х002В регистр UCSR0A=0x20 (значения по умолчанию при включении)
Добавлено: Ср янв 27, 2010 23:15:34
IfoR
Ах вот как обращаться с ней надо. Ясно. Спасибо.
Но, что интересно, теперь оно всегда возвращает 0x00.

Добавлено: Чт янв 28, 2010 04:03:15
SII
GP1 писал(а):начнем с того что в меге16, как впрочем и в других АВРках, флеш-память словная, т.е. состоит из 2 байтов, и чтобы получить доступ к ячейке BVB нада писать так:
Код: Выделить всё
LDI R30,LOW(BVB*2) ;Пишем адрес в Z регистр
LDI R31,HIGH(BVB*2);Всё нормально. Пишется 0x002A*2=0х0054
lpm R16,Z+ читаем данные из flash
Lpm R17,Z
а команда LD читает данные из памяти данных, а там по адреск 0х002А находится служебный регист UCSR0B=0х00 а по адресу 0х002В регистр UCSR0A=0x20 (значения по умолчанию при включении)
Чуток добавлю: с точки зрения выборки команд флэш-память организована по словам, т.е. адрес команды -- это адрес слова (двух байтов). Однако при доступе к ней за данными (с помощью команды LPM) она адресуется уже побайтно. Именно поэтому в этом примере адрес, с которого начинается считывание данных, умножен на два -- чтобы адрес слова (его использует транслятор ассемблера) превратить в адрес байта (нужный команде LPM).
Добавлено: Чт янв 28, 2010 08:39:59
GP1
Спасибо
SII, у мняу всегда были проблемы с ясностью словесного выражения мыслительной деятельности, о как завернул, сделать/понять могу, выразить словами - трабла

Добавлено: Чт янв 28, 2010 13:38:04
IfoR
Не ну это-то я понял (кодер кодеру рознь

), только я не могу понять, почему оно теперь возвращает 0x00?

Добавлено: Чт янв 28, 2010 15:25:30
SII
Раз возвращает 0, значит, там 0

А вот почему -- это уже другой вопрос, над которым надо думать (глядя заодно в текст программы).
Добавлено: Чт янв 28, 2010 15:39:52
IfoR
сообсно весь код:
Код: Выделить всё
.DEVICE ATmega16
.INCLUDE "m16def.inc"
.CSEG
.org 0x0000 ;Reset вектор
rjmp Reset
.org 0x002A
BVB: .DW 0x1545 ;Данные
CVB: .DW 0x1234
Reset: ;outi SPL,low(RAMEND)
;outi SPH,high(RAMEND)
LDI R30,LOW(BVB*2)
LDI R31,HIGH(BVB*2)
LD R16,Z+
LD R17,Z
Main:
WDR
rjmp Reset
И из BVB, и из CVB возвращает стабильно 0.
Добавлено: Чт янв 28, 2010 16:21:47
GP1
ну блин ты даешь!
русским же языком написано LD - для чтения данных из ОЗУ, а для чтения из памяти программ используется команда LPM
Добавлено: Чт янв 28, 2010 20:10:05
IfoR
Опа-а... Всё, теперь понятно. Спасибо.
В программ мануале эта команда в таблице спрятана в низу, не в месте со всеми там LD, вот и пропустил...
Добавлено: Пт янв 29, 2010 17:33:49
MTF
Уважаемые коты помогите решить проблему с таймером !!!!
Попытаюсь обьяснить суть проблемы ,допустим в таймере T0 есть счетчик
Код: Выделить всё
inc timer1 ;64us
inc inttemp
brne TIM0_OVF_exit
inc timer2
TIM0_OVF_exit:
работает CK/0 без деления т.к надо отсчитать
0,000064 cек и 0,016384 сек
сейчас таймер работает CK/256 и менять его частоту не могу ,так как там тоже есть счетчик но для счета более 1 сек
как можно использовать один таймер как CK/0 и CK/256 одновременно ???
допустим T0 без деления CK/0 , а все остальное что у меня работало в таймере с делением СK/256 , срабатывало через время как при СK/256
натолкните на мысль как это можно реализовать ???

Добавлено: Пт янв 29, 2010 18:23:27
GP1
Из выше сказаного не понял ни хр..на, но, ОДИН ТАЙМЕР в одно и тоже время может работать только на одной частоте.