Ассемблер (ASM) для AVR в вопросах и ответах

Обсуждаем контроллеры компании Atmel.
Аватара пользователя
GP1
Поставщик валерьянки для Кота
Сообщения: 2401
Зарегистрирован: Пт май 23, 2008 19:32:22
Откуда: Россия, Волгоград
Контактная информация:

Сообщение GP1 »

Для "плавающей" установки разряда в 1 нужно использовать or с 1 в нужном разряде, а для сброса в 0, аналогично используется команда and
Чем дальше, тем больше становлюсь занудой...
Изображение
Аватара пользователя
Pooher
Мучитель микросхем
Сообщения: 491
Зарегистрирован: Вс янв 07, 2007 01:45:48
Откуда: Российская Федерация, будь она неладна...

Сообщение Pooher »

Ну, не дописал две буквы :)
Научить нельзя, можно научиться. Пифагор.
Вставь недостающие буквы в слово *у*ня. Если у тебя получилось слово кухня, значит ты интеллигентный человек.
SII
Вымогатель припоя
Сообщения: 635
Зарегистрирован: Пт янв 30, 2009 14:50:35
Откуда: Солнечногорск

Сообщение 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:
Аватара пользователя
Savelek
Прорезались зубы
Сообщения: 221
Зарегистрирован: Сб апр 25, 2009 14:29:05

Сообщение Savelek »

Логические операции действительно очень помогут в решении этой задачи, зря я про них забыл. Пойду пробовать.
Спасибо! :beer:
lag1
Первый раз сказал Мяу!
Сообщения: 26
Зарегистрирован: Пн июн 09, 2008 23:40:31

Инверсия

Сообщение lag1 »

Здравствуйте!
Подскажите, пожалуйста, как можно инвертировать два (младших) разряда в регистре ввода-вывода? Если можно, на примере.
Спасибо!
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Инверсия

Сообщение ARV »

lag1 писал(а):Здравствуйте!
Подскажите, пожалуйста, как можно инвертировать два (младших) разряда в регистре ввода-вывода? Если можно, на примере.
Спасибо!
например, так:

Код: Выделить всё

   in  r0, PORTB ; берем содержимое PORTB
   ldi r16, 3 ; берем 2 младших бита - число 3
   eor r0, r16 ; инвертируем биты
   out PORTB, r0 ; выводим обратно в PORTB
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
lag1
Первый раз сказал Мяу!
Сообщения: 26
Зарегистрирован: Пн июн 09, 2008 23:40:31

Инверсия

Сообщение lag1 »

С примером стало понятно. Все работает.
Еще раз спасибо!
Аватара пользователя
avreal
Опытный кот
Сообщения: 842
Зарегистрирован: Чт дек 31, 2009 19:27:45
Откуда: Бровари, Україна
Контактная информация:

Сообщение 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.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Аватара пользователя
IfoR
Поставщик валерьянки для Кота
Сообщения: 2029
Зарегистрирован: Сб ноя 15, 2008 10:09:56
Откуда: г. Тула
Контактная информация:

Сообщение 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.

Что я делаю не так? :)
Изображение
/dev/urandom - гигабайты информации.

OS: openSUSE 13.2 (x86_64)
Аватара пользователя
GP1
Поставщик валерьянки для Кота
Сообщения: 2401
Зарегистрирован: Пт май 23, 2008 19:32:22
Откуда: Россия, Волгоград
Контактная информация:

Сообщение 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 (значения по умолчанию при включении)
Чем дальше, тем больше становлюсь занудой...
Изображение
Аватара пользователя
IfoR
Поставщик валерьянки для Кота
Сообщения: 2029
Зарегистрирован: Сб ноя 15, 2008 10:09:56
Откуда: г. Тула
Контактная информация:

Сообщение IfoR »

Ах вот как обращаться с ней надо. Ясно. Спасибо.
Но, что интересно, теперь оно всегда возвращает 0x00. :roll:
Изображение
/dev/urandom - гигабайты информации.

OS: openSUSE 13.2 (x86_64)
SII
Вымогатель припоя
Сообщения: 635
Зарегистрирован: Пт янв 30, 2009 14:50:35
Откуда: Солнечногорск

Сообщение 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).
Аватара пользователя
GP1
Поставщик валерьянки для Кота
Сообщения: 2401
Зарегистрирован: Пт май 23, 2008 19:32:22
Откуда: Россия, Волгоград
Контактная информация:

Сообщение GP1 »

Спасибо SII, у мняу всегда были проблемы с ясностью словесного выражения мыслительной деятельности, о как завернул, сделать/понять могу, выразить словами - трабла :)))
Чем дальше, тем больше становлюсь занудой...
Изображение
Аватара пользователя
IfoR
Поставщик валерьянки для Кота
Сообщения: 2029
Зарегистрирован: Сб ноя 15, 2008 10:09:56
Откуда: г. Тула
Контактная информация:

Сообщение IfoR »

Не ну это-то я понял (кодер кодеру рознь :) ), только я не могу понять, почему оно теперь возвращает 0x00? :roll:
Изображение
/dev/urandom - гигабайты информации.

OS: openSUSE 13.2 (x86_64)
SII
Вымогатель припоя
Сообщения: 635
Зарегистрирован: Пт янв 30, 2009 14:50:35
Откуда: Солнечногорск

Сообщение SII »

Раз возвращает 0, значит, там 0 :) А вот почему -- это уже другой вопрос, над которым надо думать (глядя заодно в текст программы).
Аватара пользователя
IfoR
Поставщик валерьянки для Кота
Сообщения: 2029
Зарегистрирован: Сб ноя 15, 2008 10:09:56
Откуда: г. Тула
Контактная информация:

Сообщение 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.
Изображение
/dev/urandom - гигабайты информации.

OS: openSUSE 13.2 (x86_64)
Аватара пользователя
GP1
Поставщик валерьянки для Кота
Сообщения: 2401
Зарегистрирован: Пт май 23, 2008 19:32:22
Откуда: Россия, Волгоград
Контактная информация:

Сообщение GP1 »

ну блин ты даешь!
русским же языком написано LD - для чтения данных из ОЗУ, а для чтения из памяти программ используется команда LPM
Чем дальше, тем больше становлюсь занудой...
Изображение
Аватара пользователя
IfoR
Поставщик валерьянки для Кота
Сообщения: 2029
Зарегистрирован: Сб ноя 15, 2008 10:09:56
Откуда: г. Тула
Контактная информация:

Сообщение IfoR »

Опа-а... Всё, теперь понятно. Спасибо.
В программ мануале эта команда в таблице спрятана в низу, не в месте со всеми там LD, вот и пропустил...
Изображение
/dev/urandom - гигабайты информации.

OS: openSUSE 13.2 (x86_64)
Аватара пользователя
MTF
Нашел транзистор. Понюхал.
Сообщения: 179
Зарегистрирован: Чт янв 07, 2010 11:25:12
Откуда: Москва

Сообщение 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

натолкните на мысль как это можно реализовать ??? :?
Аватара пользователя
GP1
Поставщик валерьянки для Кота
Сообщения: 2401
Зарегистрирован: Пт май 23, 2008 19:32:22
Откуда: Россия, Волгоград
Контактная информация:

Сообщение GP1 »

Из выше сказаного не понял ни хр..на, но, ОДИН ТАЙМЕР в одно и тоже время может работать только на одной частоте.
Чем дальше, тем больше становлюсь занудой...
Изображение
Ответить

Вернуться в «AVR»