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

Обсуждаем контроллеры компании Atmel.
Ответить
Друг Кота
Аватара пользователя
Сообщения: 15778
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

ммм....
о "длинных переходах"...
при общем объёме программной памяти для большинсьва "ходовых" МК в 4килобайта слов в большинстве случаев достаточно RJMPа чтоб перекрыть практически весь эффективный диапазон доступа в+/-2килобайта... Возможно посему и не приходилось пока с двухсловными переходами по условию сталкиваться. :dont_know:
ARV
с вопросом о "чудотворцах" вполне согласен - чем проще алгоритм - тем надежнее.
сам испытал ( http://radiokot.ru/forum/viewtopic.php? ... 0%BE%D0%B4 )
8)
Реклама
Друг Кота
Аватара пользователя
Сообщения: 6347
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Сообщение Jack_A »

ARV писал(а): может быть, все чудеса заключены в чудотворцах, а не в ядрах МК?
Скорее всего. Потому что "не бывает в электронике чудес". Возможно, та моя проблемная команда меняла не все флаги, и потому анализ всего флагового вектора мог зависить от контекста, от предыдущих команд. Времени детально анализировать не было, нужно было сдавать работу. Нашел обходной вариант - и ладно. Давно это было, еще в прошлом тысячелетии :( .
Реклама
Открыл глаза
Сообщения: 53
Зарегистрирован: Пн ноя 09, 2009 20:14:52

Сообщение SatinS »

Доброго времени суток. Есть массив в eeprom из 70 символов, я хочу перенести их в озу но не через стэк. Подскажите - как переделать код, что бы данные из eeprom загружались в ОЗУ "с начала" а не с конца. Вариант вручную прописать ВСЕ адреса для каждой ячейки не подходит :) а сам придумать не могу :|

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

ldi Temp,RamEnd
out SPL,temp
CLI
ldi temp,0
EERead:	
SBIC 	EECR,EEPE
RJMP	EERead
OUT 	EEARL, temp
SBI 	EECR,EERE 
IN 	temp1, EEDR
push temp1
inc temp
cpi temp, 70
brne EERead
SEI
Друг Кота
Аватара пользователя
Сообщения: 20117
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

Сообщение Gudd-Head »

Ну так считать не от 0 до 70, а наоборот (кстати, помимо прочего для этого не нужна команда cpi = экономия). И из регистра сохранять не в стек, а в ОЗУ c помощью команд ST/STD через указатели адреса ОЗУ X/Y/Z.
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Реклама
Эиком - электронные компоненты и радиодетали
akl
Друг Кота
Сообщения: 4470
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Сообщение akl »

Можно так
Спойлер

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

	.ESEG
	.ORG	$50
;***************************************************************************
COEFF:
;данные
	.DB	$00,$01,$02,$FA	
	.DB	$04,$92,$45,$E8
;.............
;.............
;.............
;.............
E_END:
;************************************************
;*************************************************	
CLR ZH
CLR YH
	LDI	ZL,LOW(COEFF)
	LDI	YL,LOW(COEFF+$40)
_E:
	RCALL	EEREAD
	ST	Y+,R0
	INC	ZL
	CPI	ZL,LOW(E_END)
	BRNE	_E
;*************************************************	
Реклама
Друг Кота
Аватара пользователя
Сообщения: 20117
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

Сообщение Gudd-Head »

Почему
.ORG $50
LDI YL,LOW(COEFF+$40)
?
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Реклама
Открыл глаза
Сообщения: 53
Зарегистрирован: Пн ноя 09, 2009 20:14:52

Сообщение SatinS »

Gudd-Head так я так и хочу, но не понимаю как)
при таком раскладе запись идёт в один и тот же регистр
ну да, если cpi уберу сэкономлю такты))
Спойлер

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

ldi Temp,RamEnd
out SPL,temp
CLI				     
ldi temp,0
EERead:	
SBIC 	EECR,EEPE	
RJMP	EERead	
OUT 	EEARL, temp
SBI 	EECR,EERE 
IN 	temp1, EEDR 		
LDI	ZL,low(CalibrM)
LDI ZH,High(CalibrM)
ST Z+, R18
inc temp
cpi temp, 70
brne EERead
SEI
или адресс не будет прибавляться сам? как его прибавить?

akl, либо я что то не так делаю, либо что то я делаю не так, но не работает
Спойлер

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

E_END:

CLR ZH
CLR YH
   LDI   ZL,LOW(CalibrE)
   LDI   YL,LOW(CalibrE+$40)
_E:
   RCALL   EEREAD
   ST   Y+,temp1
   INC   ZL
   CPI   ZL,LOW(E_END)
   BRNE   _E

EERead:	
SBIC 	EECR,EEPE	
RJMP	EERead
OUT 	EEARL, temp
SBI 	EECR,EERE
IN 	temp1, EEDR
ret

.ESEG 
CalibrE: 
.DB 0b00000011, 0b01100100
.DB 0b00000011, 0b01111100
akl
Друг Кота
Сообщения: 4470
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Сообщение akl »

А так
Спойлер

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

.ESEG
CalibrE:
.DB 0b00000011, 0b01100100
.DB 0b00000011, 0b01111100
E_END:

.DSEG
CLR ZH
CLR YH
   LDI   ZL,LOW(CalibrE)
   LDI   YL,LOW(CalibrE+$40)
OUT   EECR,ZH
_E:
   RCALL   EEREAD
   ST   Y+,temp1
   INC   ZL
   CPI   ZL,LOW(E_END)
   BRNE   _E

RJMP  PC+0

EERead:   
;SBIC    EECR,EEPE   
;RJMP   EERead
OUT    EEARL, temp
SBI    EECR,EERE
IN    temp1, EEDR
ret

;.ESEG
;CalibrE:
;.DB 0b00000011, 0b01100100
;.DB 0b00000011, 0b01111100
Открыл глаза
Сообщения: 53
Зарегистрирован: Пн ноя 09, 2009 20:14:52

Сообщение SatinS »

А так пишет "error: Code in DSEG", а если поставить после него .cseg не пашет :?
akl
Друг Кота
Сообщения: 4470
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Сообщение akl »

Ну да, конечно .CSEG

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

CLR ZH
CLR YH
   LDI   ZL,LOW(CalibrE)
   LDI   YL,LOW(CalibrE+$60)   ; нужно установить адрес в области RAM
OUT   EECR,ZH
_E:
   RCALL   EEREAD
   ST   Y+,r18
   INC   ZL
   CPI   ZL,LOW(E_END)
   BRNE   _E

RJMP  PC+0

EERead:   
;SBIC    EECR,EEPE   
;RJMP   EERead
OUT    EEARL, ZL   ; откуда здесь temp Нужно поставить адрес ячейки.
SBI    EECR,EERE
IN    R18, EEDR
ret

Открыл глаза
Сообщения: 53
Зарегистрирован: Пн ноя 09, 2009 20:14:52

Сообщение SatinS »

akl работает! :shock: спасибо!
Друг Кота
Аватара пользователя
Сообщения: 15778
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

счетчик байт массива
буфер обмена
начальный адрес источника (регистр адреса еепром)
начальный адрес массива (указатель z/x/y -на выбор)
--------
читаем еепромку в буфер
пишем в озу из буфера
адрес источника = адрес источника +1 (или -1)
адрес массива = адрес массива +1 (или -1)
счетчик = счетчик-1
ежли счетчик не равен 0 продолжим сызнова
---------
ну иль чего из вариаций... :dont_know:

указатели весьма в дефиците - использовать два сразу для простого примитива - как-то ЖАБО ЗЭЛЭНЭ
8)
akl
Друг Кота
Сообщения: 4470
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Сообщение akl »

Удалил.
Последний раз редактировалось akl Чт ноя 13, 2014 09:11:45, всего редактировалось 1 раз.
Друг Кота
Аватара пользователя
Сообщения: 15778
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

это с какого бодуна "потеряли"? :))
сколько байт в массиве - столько и в счетчике,
у данного примера предобработка массива с последующим декрементом счетчика событий 8)
другое дело, если была бы постобработка (вначале счетчик событий - затем массив)
- тогда один элемент может потеряться.
akl
Друг Кота
Сообщения: 4470
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Сообщение akl »

Виноват. :facepalm: Чёт зашкалило.
Друг Кота
Аватара пользователя
Сообщения: 15778
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

Ээххх... :roll:
Ежли б народ чууток больше внимания общим алгоритмам уделял, без привязки к конкретному ядру и системе команд - такой алгоритм можно было б под любое семейство МК прикошачить! 8)
А уж далее - "полировка" под конкретную систему команд и ресурсы конкретного МК. :write:
xkp
Опытный кот
Аватара пользователя
Сообщения: 781
Зарегистрирован: Ср ноя 18, 2009 12:50:31
Откуда: ковров

Сообщение xkp »

Дорогие котобратья и котосестры, подскажите пожалуйста как лучше выполнить поставленную задачу?
Микроконтроллер Atmega8, в устройсте есть графический LCD индикатор 128*64 и шина i2c, все висит на вышеупомянутом МК, так же есть несколько цифровых входов. Есть еще другой сигнал, точнее импульсы, которые нужно измерить с минимальной потерей времени. Измерить нужно время между импульсами, но не в коем случае не количество импульсов в секунду(например), так как этот способ вызовет задержку в эту самую секунду, для устройства это критично. В программе для этого инициализировано прерывание INT0 по нарастанию сигнала. Частота импульсов может варироваться от 1 до 350 Гц. Думаю создать какой-нито счетчик, а в прерывании INT0 смотреть показания счетчика и обнулять его.
Вопросы:
Как организовать счетчик для такой задачи что бы точность измерений составляла 1 Гц (особенно важно на бОльших частотах)? И вообще возможно ли это? Если да то как и сколько байт памяти будет занимать максимально возможный результат? Думаю 3 байта...
Не скажется ли это на работе всего устройства? В частности не будет ли сбиваться LCD индикатор и шина i2c?
Может есть другие пути решения такого рода проблем?
R5VCH
Хотелки:
СпойлерАналоговый осциллограф С1-112, С1-118, другие
не/рабочие модули от комплекса ОДА-102
всё что касается AVR, arduino, raspberry
всё что касается КВ-УКВ-радиосвязи, mashtastic
Контактная информация:
Друг Кота
Сообщения: 4550
Зарегистрирован: Чт май 05, 2011 21:26:34
Откуда: Украина, Славутич

Сообщение Alexeyslav »

нижний предел в 1Гц - от задержки измерения в 1 сек в худшем случае НИКУДА не уйти.
Подключай свой сигнал на вывод INT0 или INT1 настраивай прерывание на работу по фронту.
Первый фронт - запускаешь таймер, на второй - считываешь значение. Если во время между прерываниями ловишь переполнение таймера - частота ниже нижнего предела измерения, надо сбросить режим измерения на начало и ждать следующего прерывания чтобы стартовать таймер. Таймер делителями настроить так чтобы переполнялся больше чем за 1 сек - иначе на предел в 1гц не обеспечить. И по всей видимости это должен быть 16-битный таймер.
Потом тебе надо будет реализовать функцию 1/X и т.д. использовать немного арифметики чтобы согласовать скорость счета таймера с милисекундами и после деления получить герцы.
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 25862
Зарегистрирован: Чт янв 10, 2008 22:01:02
Откуда: Московская область, Фрязино

Сообщение КРАМ »

xkp писал(а):Измерить нужно время между импульсами, но не в коем случае не количество импульсов в секунду(например), так как этот способ вызовет задержку в эту самую секунду, для устройства это критично. В программе для этого инициализировано прерывание INT0 по нарастанию сигнала. Частота импульсов может варироваться от 1 до 350 Гц. Думаю создать какой-нито счетчик, а в прерывании INT0 смотреть показания счетчика и обнулять его.
Для этой цели есть модуль Capture в МК.
Этот модуль по входному событию на пине (входе модуля) производит АППАРАТНУЮ запись (захват) значения некоего таймера, который работает с этим модулем.
Одновременно происходит прерывание от этого модуля, где и считывается из буфера Capture то значение счетчика которое было захвачено.
Делается так же буфер на два значения измерений, где из текущего захвата вычитается предыдущее значение.
Для обеспечения заданной точности по любому потребуется усреднять (фильтровать) измерения, поэтому нужен так же кольцевой буфер на несколько измерений, которые каждый цикл захвата усредняются.
Задержка НЕИЗБЕЖНА. Это ФИЗИКА и МАТЕМАТИКА. Это ПРИРОДА...
:)
Друг Кота
Аватара пользователя
Сообщения: 15778
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

Прицепи внешний МК для предварительной обработки данных. Дальнейший обмен с базовым по варианту аппаратного или программного I2C/SPI.
Ответить

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