Страница 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
Логические операции действительно очень помогут в решении этой задачи, зря я про них забыл. Пойду пробовать.
Спасибо! :beer:

Инверсия

Добавлено: Вс янв 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. :roll:

Добавлено: Чт янв 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? :roll:

Добавлено: Чт янв 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
Из выше сказаного не понял ни хр..на, но, ОДИН ТАЙМЕР в одно и тоже время может работать только на одной частоте.