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

Обсуждаем контроллеры компании Atmel.
Ответить
Друг Кота
Аватара пользователя
Сообщения: 20117
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

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

Можно во флэше хранить четверть периода, а перед началом выполнения программы сгенерить полный период в ОЗУ и оттуда херачить. Быстродействие + экономия памяти.
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Реклама
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Сообщение COKPOWEHEU »

Выигрыш в быстродействии ровно на 1 такт. ld занимает 2 такта, lpm - 3.
Реклама
Друг Кота
Аватара пользователя
Сообщения: 20117
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

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

Выигрыш во флэше.
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Сообщение COKPOWEHEU »

Зато потеря в оперативке, которой обычно меньше.
Для какого-то круга задач лучше этот метод, для какого-то - хранение всей таблицы во флеше, а для какого-то даже вычисление на лету. Спорить на тему, какой из них самы-самый лучший во всех ситуациях мне неохота.
Реклама
Эиком - электронные компоненты и радиодетали
Держит паяльник хвостом
Аватара пользователя
Сообщения: 965
Зарегистрирован: Сб апр 12, 2014 23:46:03
Откуда: Киев

Сообщение Flash.#13 »

Здравствуйте! Косяк вылез при работе с АЦП на Атмега8. Задача состоит в том чтобы произвести последовательно два замера, первый с одной ножки, и через некоторое время второй, с другой ножки АЦП. И так по циклу, типа меряем два напряжения. По одному оно меряется, а два вместе ну ни в какую! Начинает мерить какое то левое скачущее напряжение, вроде помех каких то.

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

;включаем модуль АЦП и разрешаем прерывания по замеру
ldi R16, 0b01000000	;AD_Converter ADMUX byte, включаем опорное напряжение +5в, АЦП выв.0
out ADMUX, R16
ldi R16, 0b10001011	;AD_Converter ADCSRA byte, делитель 125kHz, и прерывание ЦП по замеру
out ADCSRA, R16			
sei 			;вкл. прерывания в ЦП
...
;делаем замер включая бит замера АЦП
sbi ADCSRA,6		;старт замера АЦП
...
ldi R16, 0b01000001             ;меняем ножку АЦП на "1"
out ADMUX, R16		;ставим на вход ножку АЦП "1"
sbi ADCSRA,6		;старт 2-го замера АЦП
И после 2-го замера получаю цикличный мусор на обеих входах. Ребята чего делаю не так?
Немного файлов по зажиганию: ФУОЗ 2.2 + программа правки таблиц 0.987, монтажка
Реклама
Друг Кота
Аватара пользователя
Сообщения: 20117
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

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

Задержку хорошо бы между переключением каналов поставить чтобы напряжение успело устаканиться.
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Реклама
Держит паяльник хвостом
Аватара пользователя
Сообщения: 965
Зарегистрирован: Сб апр 12, 2014 23:46:03
Откуда: Киев

Сообщение Flash.#13 »

Ввел временную задержку и ...немножко подафигел. При малых временных задержках происходит неверный замер. Опытным путем, получил минимальную задержку, на переключение входа АЦП около 1.8сек... :shock: Мне становится жутко, а какое время переключения между входами по мануалу? Может чего либо не допаял на входах АЦП?
Немного файлов по зажиганию: ФУОЗ 2.2 + программа правки таблиц 0.987, монтажка
Держит паяльник хвостом
Аватара пользователя
Сообщения: 965
Зарегистрирован: Сб апр 12, 2014 23:46:03
Откуда: Киев

Сообщение Flash.#13 »

От части решилась проблема, как всегда гугл и программатор в помощь... :cry: На одном с сайтов написанно:
...При переключении на дифференциальный канал первое преобразование будет характеризоваться плохой точностью из-за переходного процесса в схеме автоматической регулировки смещения. Следовательно, первый результат такого преобразования рекомендуется игнорировать.
От себя добавлю, что нужно добавить еще и временную задержку, после первого "неточного" замера, и задержка эта, не менее 20 циклов генератора-делителя АЦП... Жуть...

Получилось где-то вот так:

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

...
ldi R16, 0b01000000	;AD_Converter ADMUX byte, АЦП ножка 0
out ADMUX, R16
sbi ADCSRA,6		;старт "ложного" замера АЦП
rcall delay40mks                  ;задержка, уже была раньше для ЖК, ну и юзаю ту же самую подпрограмму
rcall delay40mks
rcall delay40mks
rcall delay40mks                  ; всего задержек на 20 циклов генератора АЦП
sbi ADCSRA,6		;старт "нормального" замера АЦП
...
ldi R16, 0b01000001	;AD_Converter ADMUX byte,  АЦП ножка 1
out ADMUX, R16
sbi ADCSRA,6		;старт "ложного" замера АЦП
rcall delay40mks
rcall delay40mks
rcall delay40mks
rcall delay40mks
sbi ADCSRA,6		;старт "нормального" замера АЦП
...
У меня АЦП работает на 125кГц, получается 8мкс, и пока не пройдет примерно 20 тактов генератора, около 160мкс, корректные данные не замерятся. Может что то допаять на входе АЦП(ATMega8), и будет лучше?
Немного файлов по зажиганию: ФУОЗ 2.2 + программа правки таблиц 0.987, монтажка
Первый раз сказал Мяу!
Аватара пользователя
Сообщения: 39
Зарегистрирован: Пн дек 31, 2012 13:16:59

Сообщение *скрыто* »

Так ты же не используешь дифференциальный вход по этому должен быть пофигу этот переходной процесс, которого нет.
У меня все работает без задержек, так же переключаю 2 входа и забираю результат после сброса флага ADIF
может у тебя другая подпрограмма в прерывании портит регистры, в которые забираешь результат ?
Держит паяльник хвостом
Аватара пользователя
Сообщения: 965
Зарегистрирован: Сб апр 12, 2014 23:46:03
Откуда: Киев

Сообщение Flash.#13 »

Может и не использую, но он не пофигу... Процесс идет вот так:
Старт:

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

.org 0				;начало кода
rjmp start
.org 9 				;вектор прер. timer0
rjmp timer			;подпрограмма таймера 4Гц
.org 14				;вектор прер. АЦП
rjmp adc_complete	;подпрограмма АЦП (срабатывает редко)
затем инициализация АЦП:

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

ldi R16, 0b01000000	;AD_Converter ADMUX byte
out ADMUX, R16
ldi R16, 0b10001011	;AD_Converter ADCSRA byte, 125kHz
out ADCSRA, R16			
sei 				;вкл. прерывания в ЦП
Срабатывает условие старта замера в главной программе

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

sbi ADCSRA,6		;старт замера АЦП
При этом прога идет по прерыванию АЦП adc_complete

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

;====АЦП замер сделан====
adc_complete:
in R9, ADCL	
in R8, ADCH
reti
Если не переключаю порт АЦП при замерах, то мерить можно без задержек. Четко и гладко. Но если идет переключение входа АЦП в коде, то первый замер будет со сбоем даже через 1.5 секунды :shock: Единственное чего нашел, это сделать пустой первый замер, и задержку в 20 тактов генератора АЦП. Тогда все нормально. Может у меня контроллер паленый или паяльником его перегрел, но с задержкой все нормально. Правда еще не проверяд переключение на 3-4 ножки))
*скрыто* писал(а):...забираю результат после сброса флага ADIF...
Не опрашиваю флаги, использую вектор прерывания, АЦП сам вызывает подпрограмму и возвращается в точку кода.
Немного файлов по зажиганию: ФУОЗ 2.2 + программа правки таблиц 0.987, монтажка
Первый раз сказал Мяу!
Аватара пользователя
Сообщения: 39
Зарегистрирован: Пн дек 31, 2012 13:16:59

Сообщение *скрыто* »

Судя по даташиту, внутрений мультиплексор переключается не после обновления admux, а спустя 1 такт после установки бита ADSC . По этому нет никаких причин делать задержки.
Опытный кот
Аватара пользователя
Сообщения: 721
Зарегистрирован: Ср июн 11, 2014 09:43:13
Откуда: США

Сообщение Pink-Pank »

Да, в даташите описано, что смена канала происходит непосредственно при старте преобразования. Это сделано для того, чтобы можно было менять каналы не дожидаясь конца преобразования. Единственный случай, когда требуется задержка - включение запитка Ацп от внутреннего ИОН. И то, только перед первым запуском и если данный ИОН не был включен ранее другой периферией (схемой BOD, например).
А так смотрите, может где-то у Вас большая емкость по входу повисла, либо подаете измеряемый сигнал через большое сопротивление.
Fucking static initialization order fiasco
Контактная информация:
Встал на лапы
Аватара пользователя
Сообщения: 115
Зарегистрирован: Ср окт 22, 2014 07:39:26
Откуда: Омск

Сообщение neoneon »

Напишем маленькую подпрограмму для задержки:

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

DELAY:
ldi delay1,0x80      ; записываем нужное число в переменные, младший разряд
ldi delay2,0x1A      ; старший разряд

subi delay1,1         ; создаем цикл уменьшения этого числа на 1
sbci delay2,0         ; вычитаем 1 из старшего разряда, если был перенос
brcc DELAY            ; переход, если не было переноса
ret
То есть записываем число в два регистра, оно в течении цикла инкрементируется. Это понятно. Но как так получается, что эту подпрограмму можно вызывать много раз и она будет работать? То есть команда subi записывает результат обратно в регистр, после первого вызова переменные delay1 и delay2 будут обнулены, верно?
Полный чайник.
akl
Друг Кота
Сообщения: 4473
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Сообщение akl »

neoneon писал(а):Напишем маленькую подпрограмму для задержки:
То есть записываем число в два регистра, оно в течении цикла инкрементируется. Это понятно. Но как так получается, что эту подпрограмму можно вызывать много раз и она будет работать? То есть команда subi записывает результат обратно в регистр, после первого вызова переменные delay1 и delay2 будут обнулены, верно?
Не думаю, что программа будет корректно работать. Обычно делают так

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

DELAY:
ldi delay1,0x80      ; записываем нужное число в переменные, младший разряд
ldi delay2,0x1A      ; старший разряд
LOOP:
subi delay1,1         ; создаем цикл уменьшения этого числа на 1
sbci delay2,0         ; вычитаем 1 из старшего разряда, если был перенос
brcc LOOP            ; переход, если не было переноса
;brcc DELAY            ; переход, если не было переноса
ret
Встал на лапы
Аватара пользователя
Сообщения: 115
Зарегистрирован: Ср окт 22, 2014 07:39:26
Откуда: Омск

Сообщение neoneon »

Хорошее замечание :) Но суть не меняется - вызываем Loop, а после первого вызова переменные delay уже обнулены :?
Полный чайник.
akl
Друг Кота
Сообщения: 4473
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Сообщение akl »

Да обнулены. В этом и суть программной задержки. При следующем входе в пп DELAY эти переменные сначала будут установлены, а затем LOOP опять обнулены. Можно ведь делать переменную задержку. Установить сначала переменные, а затем войти в пп LOOP.
Например

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

   LDI XH,HIGH(5555)
   LDI XL,LOW(5555)
   RCALL LOOP
.
.
.
LOOP:
   SBIW XH:XL,1
   BRNE LOOP
   RET
Последний раз редактировалось akl Вс янв 04, 2015 18:39:00, всего редактировалось 1 раз.
Опытный кот
Аватара пользователя
Сообщения: 721
Зарегистрирован: Ср июн 11, 2014 09:43:13
Откуда: США

Сообщение Pink-Pank »

Обнулены они были бы в том случае, если бы условие проверки было brne, а у Вас получится, что разряды будут равны 0xFF
Fucking static initialization order fiasco
Контактная информация:
akl
Друг Кота
Сообщения: 4473
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Сообщение akl »

Да, верно. Условие brcc будет выполняться до 0xFFFF.
Встал на лапы
Аватара пользователя
Сообщения: 115
Зарегистрирован: Ср окт 22, 2014 07:39:26
Откуда: Омск

Сообщение neoneon »

Спасибо, разобрался :) Только не понял про brcc и 0xFF. Если поставить brсс, то когда subi сделает операцию (0-1), получит -1 (то есть FF), команда sbci выполнит операцию (0-1), тоже получит -1 (FF), установится флаг переноса С=1, то программа не перейдет по метке и выйдет из цикла. Если поставить brne, то когда в delay2 установится 00, т.е. сбросится полностью (а в delay1 еще будет FF), установится флаг нулевого результата Z=1, программа выйдет из цикла. Так? :?
Полный чайник.
Опытный кот
Аватара пользователя
Сообщения: 721
Зарегистрирован: Ср июн 11, 2014 09:43:13
Откуда: США

Сообщение Pink-Pank »

Совершенно верно. При использовании brne будет необходимо проверять отдельно старшую часть и потом отдельно младшую. Иначе программа будет меньше циклов выполняться, чем надо. Обычно делают вложенным циклом проверки младшей части в цикл проверки старшей части.
Fucking static initialization order fiasco
Контактная информация:
Ответить

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