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

Обсуждаем контроллеры компании Atmel.
Ответить
Опытный кот
Сообщения: 772
Зарегистрирован: Вс апр 10, 2011 02:24:06
Откуда: г.Северодонецк

Сообщение eufs »

eufs писал(а):Если непонятно - пиши, поясню на примере. Все получается не очень компактно(из-за таблицы), но очень быстро и просто и без условных переходв.
Тогда таблицу придётся делать для всех возможных комбинаций, т.е. 2^4 = 16 байт для хранения, по сути, всего двух бит (0 или ±1). Как-то нерационально, а бешеная скорость мне не нужна: по даташиту максимальная скорость вращения энкодера 100 об/мин.
Да. 16 байт. Но не только для хранения 2 бит. Таблица дает возможность исключить всевозможные проверки и условные переходы, а это тоже место. А 16 байт - это 8 команд(всего лишь). Попробуй, напиши с таблицей и без, тогда поговорим о длине кода и затем о рациональности.
C0FFEE=‭12648430‬
Реклама
Друг Кота
Аватара пользователя
Сообщения: 20092
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

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

eufs писал(а):Да. 16 байт. Но не только для хранения 2 бит. Таблица дает возможность исключить всевозможные проверки и условные переходы, а это тоже место. А 16 байт - это 8 команд(всего лишь). Попробуй, напиши с таблицей и без, тогда поговорим о длине кода и затем о рациональности.
Ну, я не говорил, что совсем отказываюсь от таблицы :) К тому же, у меня есть подозрение что с таблицей будет проще организовать обработку двух энкодеров.
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Реклама
Друг Кота
Аватара пользователя
Сообщения: 4468
Зарегистрирован: Вс янв 24, 2010 19:19:52
Откуда: Главный Улей России (Moscow)

Сообщение DX168B »

Вот и я суда с вопросом.
Подскажите, как можно разделить 8-битное число на 2? Сдвигом вправо?
I am DX168B and this is my favourite forum on internet!
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 20092
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

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

DX168B писал(а):Подскажите, как можно разделить 8-битное число на 2? Сдвигом вправо?
ДА :) По кр. мере, положительное.
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Реклама
Эиком - электронные компоненты и радиодетали
Друг Кота
Аватара пользователя
Сообщения: 4468
Зарегистрирован: Вс янв 24, 2010 19:19:52
Откуда: Главный Улей России (Moscow)

Сообщение DX168B »

Знаковое или нет, там не играет роли.
Мне нужно было поделить число пополам, отвечающее за частоту ШИМ,
чтобы его вставить в регистр сравнения.
TINY26L, TIMER1
OCR1C - число n+1 (частота ШИМ)
OCR1A - число n\2 (длинна периода)
Разрабатываю кодер\декодер сигнатур для радиосвязи. :)
Спасибо :) :beer:
I am DX168B and this is my favourite forum on internet!
Контактная информация:
Реклама
Опытный кот
Аватара пользователя
Сообщения: 838
Зарегистрирован: Вт апр 12, 2011 18:38:19
Откуда: с Земли

Сообщение coredumped »

Gudd-Head писал(а):Как с помощью МК определить направление вращения энкодера, покрасивее и покомпактнее?
Энкодер двухбитный в коде Грея, т.е. последовательность 00-10-11-01 в одну сторону и 00-01-11-10 в другую.
Пока в голову не приходит ничего лучше, чем сравнивать прошлые 2 бита и новые 2 бита с константами (CPI с последующим BREQ на каждую константу) "0010", "1011", "1101" и "0100" в случае инкремента (условно); "0001", "0111", "1110" и "1000" в случае декремента.
Можно с помощью аппаратного прерывания по положительному фронту. Подаете первую ногу энкодера, например, на INT0. В обработчике считываете вторую ногу. Если 0 - то одно направление, если 1 - другое. Можно замутить внешний детектор на одном D-триггере. Полет фантазии безграничен :)
Все будет только лучше, в крайнем случае - хуже.
Реклама
Друг Кота
Аватара пользователя
Сообщения: 20092
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

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

coredumped писал(а):Можно с помощью аппаратного прерывания по положительному фронту. Подаете первую ногу энкодера, например, на INT0. В обработчике считываете вторую ногу. Если 0 - то одно направление, если 1 - другое. Можно замутить внешний детектор на одном D-триггере. Полет фантазии безграничен :)
Во-первых, не хочется делать это в прерывании. Во-вторых, такой алгоритм даст всего одно прерывание на 4 изменения положения энкодера. Ну и в-третьих, только внешнего D-триггера мне и не хватало, когда есть МК.
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Опытный кот
Аватара пользователя
Сообщения: 838
Зарегистрирован: Вт апр 12, 2011 18:38:19
Откуда: с Земли

Сообщение coredumped »

moza-mult писал(а): Период импульса Т 1100 машинных циклов (305 мкс*)
Длительность импульса t 340 машинных циклов (94 мкс*)
Источники прерывания
Запрос на прерывание от внешнего источника INT0
Запрос на прерывание от внутреннего источника INT1
исходник добавил... но не могу понять как он работает... и работает ли... проверить на анализаторе его временно не могу... поэтому если есть возможность ответьте плиз :)
Не хочу читать нотаций, просто в паузах, пока компилится проект на ARM (минут 10) скучно... А тут какраз плата с 16й мегой валялась :)))

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

#include <avr/io.h> 
#include <stdio.h>
#include <stdlib.h>
#include <avr/interrupt.h>

volatile unsigned char INT0_count = 0;
volatile unsigned char INT1_count = 0;
volatile unsigned char phase = 0;

ISR(INT0_vect) 
{
	TCCR1B = 0; //Stop timer 1

	INT0_count++;
	if(INT0_count == 6) GICR &= ~(1<<INT0); //disable INT0 

	TCCR1B = 1; //Start timer 1, prescaler=1
}

ISR(INT1_vect)
{
	TCCR1B = 0; //Stop timer 1

	INT1_count++;
	if(INT1_count == 6) GICR &= ~(1<<INT1); //disable INT1 

	TCCR1B = 1; //Start timer 1, prescaler=1
}

ISR(TIMER1_OVF_vect)
{
	if(phase == 0)
	{
		TCNT1 += 0xffff - 340; //One phase
		PORTA = 1; // set PA=1;
		phase = 1;
	}
	else
	{
		TCNT1 += 0xffff - (1100 - 340); // Zero phase
		PORTA = 0; // set PA=0;
		phase = 0;
	}
}



int main( void )
{

	DDRA = 0x01; //PA1 - output
	PORTA = 0;
		
	TIMSK |= (1<<TOIE1); //timer1 overflow interrupt enable 
	TCNT1 = 0xffff - (1100 - 340); // Zero phase

	TCCR1B = 1; //Start timer 1, prescaler=1

    MCUCR = (1<<ISC00) | (1<<ISC01) | (1<ISC10) | (1<ISC11); //interrupts INT0,INT1 on rising edge
	GICR |= (1<<INT0) | (1<<INT1);  //enable INT0 and INT1
	sei(); //global interrupts enable 
	for(;;); //main loop
	
	return 0;
} 

Импульсы наблюдаются на PA0. Кварц под рукой был тока на 4МГц, поэтому время слегка отличается
tek00001.png
(5.47 КБ) 399 скачиваний
Все будет только лучше, в крайнем случае - хуже.
Опытный кот
Сообщения: 772
Зарегистрирован: Вс апр 10, 2011 02:24:06
Откуда: г.Северодонецк

Сообщение eufs »

coredumped писал(а):
Gudd-Head писал(а):Как с помощью МК определить направление вращения энкодера, покрасивее и покомпактнее?
Энкодер двухбитный в коде Грея, т.е. последовательность 00-10-11-01 в одну сторону и 00-01-11-10 в другую.
Пока в голову не приходит ничего лучше, чем сравнивать прошлые 2 бита и новые 2 бита с константами (CPI с последующим BREQ на каждую константу) "0010", "1011", "1101" и "0100" в случае инкремента (условно); "0001", "0111", "1110" и "1000" в случае декремента.
Можно с помощью аппаратного прерывания по положительному фронту. Подаете первую ногу энкодера, например, на INT0. В обработчике считываете вторую ногу. Если 0 - то одно направление, если 1 - другое. Можно замутить внешний детектор на одном D-триггере. Полет фантазии безграничен :)
Чуть изношеный энкодер дает дребезг по фронтам, поэтому так делать нельзя. С аппаратным триггером на входе-это получится, но нужен еще один корпус. Так что для полетов не так и много места.
C0FFEE=‭12648430‬
Родился
Сообщения: 5
Зарегистрирован: Вс фев 20, 2011 23:48:02

Сообщение Karusel »

Добрый день ребята :tea: ! Я к вам за помощью и советами-вот с утра вожусь со SPI интерфейсом на MEGA16 :sleep: ,никак не хочет нормально работать зараза. Собственно идея в том,чтобы передать сигналы 'A' и 'B' с одного МК на другой и переключать соответствующие светодиоды на ведомом МК-зеленый и желтый,т.е. нажимаешь одну кнопку-горит соответствующий светодиод,а другой светодиод выключается,нажимаещь другую-наоборот. :dont_know: где я ошибаюсь-не понимаю. Прикрепляю исходные коды и схему в ПРОТЕУСЕ. Заранее благодарю!
Вложения
SPI.zip
(45.71 КБ) 161 скачивание
Друг Кота
Аватара пользователя
Сообщения: 3872
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Сообщение Engineer_Keen »

Во-первых у вас портD подтянут к +

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

ldi temp,0xFF
out PORTD,temp
И как тогда контроллер сообразит что кнопка нажата, если кнопки подключены тоже к +? Так что кнопки сажаем на землю и меняем sbic на sbis.
Ну и еще про антидребезг не забываем...
Родился
Сообщения: 5
Зарегистрирован: Вс фев 20, 2011 23:48:02

Сообщение Karusel »

Engineer_Keen писал(а):Во-первых у вас портD подтянут к +

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

ldi temp,0xFF
out PORTD,temp
И как тогда контроллер сообразит что кнопка нажата, если кнопки подключены тоже к +? Так что кнопки сажаем на землю и меняем sbic на sbis.
Ну и еще про антидребезг не забываем...
Спасибо большое,щас исправим! :kill:
Открыл глаза
Аватара пользователя
Сообщения: 61
Зарегистрирован: Пт янв 01, 2010 20:43:32
Откуда: cccp

Сообщение teist »

подскажите пожалуйста насчет антидребезга, я так понял что бороться с ним
надо задержкой. а какую лучше выбрать. Например 0,1с подойдет?
Опытный кот
Аватара пользователя
Сообщения: 838
Зарегистрирован: Вт апр 12, 2011 18:38:19
Откуда: с Земли

Сообщение coredumped »

teist писал(а):подскажите пожалуйста насчет антидребезга, я так понял что бороться с ним
надо задержкой. а какую лучше выбрать. Например 0,1с подойдет?
методов много, я использую следующий - читаем порт с задержкой 3 раза, если все 3 раза прочиталось одно и тоже, значит считаем, что событие произошло (нажатие кнопки или чего-то там еще дребезжащего). Задержку нужно выбирать в зависимости от кнопки. Обычно достаточно 10-50мкс. А Вы хотите в 10000 раз больше - это слишком "эстонское" устройство может получиться :) Поставьте 10 мкс, если будут ложные срабатывания, увеличьте.
Все будет только лучше, в крайнем случае - хуже.
Опытный кот
Аватара пользователя
Сообщения: 703
Зарегистрирован: Вс янв 18, 2009 21:12:49

Сообщение asteroid7 »

teist писал(а):... а какую лучше выбрать. Например 0,1с подойдет?
100 мс многовато.
12...14 мс - один опрос (удобно также для динамической индикации). 3 раза = истина.
Опытный кот
Сообщения: 772
Зарегистрирован: Вс апр 10, 2011 02:24:06
Откуда: г.Северодонецк

Сообщение eufs »

Время подавления дребезга контактов умные дядьки рекомендуют делать некратным длительности периода сети и не менее 100мс. То есть ближайшее значение 110мс, затем 130, 150,170. А вот более 200 мс рекомендуют делать для узлов управления с повышенными внешними помехами. Например в автомобилях.
Я, как правило, делаю 150 мс. Если в течении этого времени активный уровень от контакта стабильный - контакт замкнутый.
C0FFEE=‭12648430‬
Встал на лапы
Аватара пользователя
Сообщения: 86
Зарегистрирован: Вс фев 27, 2011 01:01:11
Откуда: Республика Крым

Сообщение VirZh »

eufs писал(а):Время подавления дребезга контактов умные дядьки рекомендуют делать некратным длительности периода сети и не менее 100мс. То есть ближайшее значение 110мс, затем 130, 150,170. А вот более 200 мс рекомендуют делать для узлов управления с повышенными внешними помехами. Например в автомобилях.
Я, как правило, делаю 150 мс. Если в течении этого времени активный уровень от контакта стабильный - контакт замкнутый.
дребезг контактов - это время, за которое при нажатии на кнопку установится стабильное соединение (разъединение) контактов. Все зависит от самой кнопки, Например, подпружиненные срабатывают немного быстрее обычных. Как правило 20 мс хватает для всех случаев. 100-150 мс, как на мой взгляд, долговато. Здесь уже можно успеть нажать и отпустить кнопку, успешно приняв сигнал за дребезг... :) Борьба с помехами-это несколько другая ситуация, и тут надо смотреть в каждом случае отдельно...
Опыт и мудрость приходят с годами... К некоторым годы приходят одни...
Опытный кот
Аватара пользователя
Сообщения: 838
Зарегистрирован: Вт апр 12, 2011 18:38:19
Откуда: с Земли

Сообщение coredumped »

eufs писал(а):Время подавления дребезга контактов умные дядьки рекомендуют делать некратным длительности периода сети и не менее 100мс. То есть ближайшее значение 110мс, затем 130, 150,170. А вот более 200 мс рекомендуют делать для узлов
Это кто рекомендует? Умные дядьки что курят? Че за бред? За секунду кнопку 10 раз нажать можно, ну ладно, любой и каждый 5 раз нажмет, а это 5 нажатий и 5 отпусканий. С таким подходом Ваш контроллер посчитает это дребезгом. Или Вы спутали милисекунды и микросекунды? Включите здравый смысл :)
Все будет только лучше, в крайнем случае - хуже.
Опытный кот
Сообщения: 772
Зарегистрирован: Вс апр 10, 2011 02:24:06
Откуда: г.Северодонецк

Сообщение eufs »

VirZh писал(а): дребезг контактов - это время, за которое при нажатии на кнопку установится стабильное соединение (разъединение) контактов. Все зависит от самой кнопки, Например, подпружиненные срабатывают немного быстрее обычных. Как правило 20 мс хватает для всех случаев. 100-150 мс, как на мой взгляд, долговато. Здесь уже можно успеть нажать и отпустить кнопку, успешно приняв сигнал за дребезг... :) Борьба с помехами-это несколько другая ситуация, и тут надо смотреть в каждом случае отдельно...
20 мс, это очень мало. Да и не к чему. 50 раз в секунду никто кнопки нажимать не будет, а помехоустойчивость выше. Это я в руководстве по программированию МК лет 10 назад еще читал (еще для 51,но суть дела не меняет). Там очень тесно связывалась моторика и физиология человека с подобными вещами. Приводились выкладки зачем и почему выбираются те или иные интервалы.

Для Вас специально привожу пример, который запомнился оттуда же. Подготовленная реакция человека на событие (зажигается например светодиод и этого человек пристально ждет) лежит в диапазоне 100-150мс, а неподготовленная, то есть та, которая происходит внезапно - 300-500мс, а если пьяный, то до 2 сек доходит. Можете проверить это каким либо образом на себе. я убежден, что цифры правильные.
А теперь скажите, зачем делать подавление дребезга 20мс, если все равно никаких действий, чаще чем 10 раз в секунду (100мс) Вы все равно пальцами сделать не сможете, а даже если у вас это получится - все равно отреагировать на каждое нажатие неполучится. Проще и грамотнее делать автоповтор нажатия на кнопку.
По поводу нажал-отпустил за 100мс - аргумент еще проще - нафига было нажимать. Мы же заботимся об эргономике и помехоподавлении, а не об играх с кнопками.

http://www.navoprosotveta.net/03/03_2882.htm
http://2po.eu/blog/vremya-reakcii-i-kibersport/
C0FFEE=‭12648430‬
Опытный кот
Сообщения: 772
Зарегистрирован: Вс апр 10, 2011 02:24:06
Откуда: г.Северодонецк

Сообщение eufs »

coredumped писал(а):
eufs писал(а):Время подавления дребезга контактов умные дядьки рекомендуют делать некратным длительности периода сети и не менее 100мс. То есть ближайшее значение 110мс, затем 130, 150,170. А вот более 200 мс рекомендуют делать для узлов
Это кто рекомендует? Умные дядьки что курят? Че за бред? За секунду кнопку 10 раз нажать можно, ну ладно, любой и каждый 5 раз нажмет, а это 5 нажатий и 5 отпусканий. С таким подходом Ваш контроллер посчитает это дребезгом. Или Вы спутали милисекунды и микросекунды? Включите здравый смысл :)
С таким подходом к школьному курсу физики Ваш контроллер вообще ничего не посчитает...Сколько в секунде миллисекунд?
C0FFEE=‭12648430‬
Ответить

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