Имеем Atmega8535 с кварцем 11.0592 Мгц.
Задача обработка сигнала с оптического энкодера (2048 имп/об, Fmax- 160кГц Канал А заведен на INT0, который настроен на прерывание по спаду) с выдачей результата на ком порт (возможно в будущем потребуется Modbus RTU).
Так вот, справится ли AVR с такой задачей? Или лучше сразу медленно ползти в сторону ARM?
Программно организованный стек справится с выдачей в порт, чтение по прерыванию (и анализ тоже), еще будет свободное пространство кода основной программы (в промежутках вывода в порт, можно анализ прерываний сделать). Если частоты не будет хватать (в чем я сильно сомневаюсь), можно MEGA8-PU-16 (16MHz). Еще многое зависист от того как программу построите,старайтесь применять оптимизацию на скорость, поменьше работать с ОЗУ, побольше с регистрами и применять операторы, которые 1 такт занимают, тогда 160КГц проанализировать и вывести в порт-легко.
Человек умный - объяснит
Глупый - будет разбрасываться умными словами.
А каким методом хотите определять направление вращения ?
Делал что-то подобное очень давно на таком же кварце и контроллере и тоже с оптическим датчиком уперся в скорость ~25кГц .
OBIVAN писал(а):А каким методом хотите определять направление вращения ?
Делал что-то подобное очень давно на таком же кварце и контроллере и тоже с оптическим датчиком уперся в скорость ~25кГц .
Ну что то вроде этого:
interrupt [EXT_INT1] void ext_int1_isr(void) // Прерывание по спаду фронта
{
if (!PIND.6&!PIND.3) //если PD.3 и PD.6 = 0
{
count_enc++; //прибавим 1 к счетчику импульсов
#asm("reti")
};
if (!PIND.3|PIND.6) //если !PD.3 или PD.6 =1
{
count_enc--; //вычтем 1 из счетчика импульсов
};
#asm("reti") //выход из прерывания
Даже работает Еще нужно добавить обработку индексной метки.
Еще такой вопрос - какую длину буфера TXD сделать? На выходе float .2f.
По-моему, занимать такой задачей ARM - это из пушки по воробьям. Но скорости атмеги для этой задачи, в такой формулировке, действительно, может не хватать. Может изменить условия? Скажем, направление вращения распознавать мелкой логикой снаружи м/к, а импульсы подсчитывать счетчиком (по одному входу - наращивать, по другому - уменьшать), и раз в nn миллисекунд слать накопленное их количество наружу. Поскольку счет импульсов будет реализован аппаратно, с такой задачей атмега справится.
Lonleystranger писал(а):поменьше работать с ОЗУ, побольше с регистрами
А типа регистры не в этой же памяти находятся? или доступ к ним быстрее чем к другим ячейкам ОЗУ?
С регистрами можно работать напрямую, а для обработки значений в ОЗУ их сначло нужно оттуда скопировать(перед этим адрес ячейки ОЗУ нужно положить в регистровую пару) в те же самые регистры, поработать с ними и обратно положить.
There is only 10 kind of people: those who understands binary code and those who dont!!!
Yellow Tiger писал(а): Скажем, направление вращения распознавать мелкой логикой снаружи м/к, а импульсы подсчитывать счетчиком (по одному входу - наращивать, по другому - уменьшать), и раз в nn миллисекунд слать накопленное их количество наружу.
Есть микросхема, содержащая квадратурный декодер и 24 разрядный счётчик с 8 разрядной шиной для чтения. Тип точно не помню, надо порыться (был у меня даташит). В своё время, мне было лениво искать эту микросхему и я сделал на ПЛИС.
Но вообще, можно ограничиться одним квадратурным декодером на двух корпусах логики. Два сигнала на выходе: "счёт" и "направление".
(точность будет 2048 Х 4 = 8192 отсчётов на оборот )
Вот, кажется она. Только она 16 битная (это я на ПЛИСе 24 битную делал), хотя, если порыться , то может есть и другие аналогичные микрухи с большей разрядностью.
При заданных условиях, между каждым импульсом от энкодера успеет пройти примерно 70 тактов, при этом мин. 8-10 тактов уйдет на обработку прерывания, т.е. остается около 60 тактов, или 60 однотактных команд, для вывода в USART больше чем достаточно
Я думаю внешний декодер стоит делать если только нужен режим х4. А если не нужен этот режим то и так довольно просто декодируется:
interrupt [EXT_INT1] void ext_int1_isr(void) // INT1 Mode: Falling Edge
{
if (!PIND.3&!PINA.0)
{
count--;
}
else
count++;
}
count = signed long int.
Если заводить сигналы на счетчик, учитывая то что он 16 битный а число на выходе нужно скажем от -20000 до +20000 то код получится куда больше
__Alexander писал(а):А типа регистры не в этой же памяти находятся? или доступ к ним быстрее чем к другим ячейкам ОЗУ?
Сами посчитайте- загрузить в 16 разрядный регистр (Х,У,или Z) адрес ОЗУ (LDI,2 такта), Прочитать данные из ОЗУ в регистры 2 такта(LD)и провести операцию (n-количество тактов), и записать назад, еще 4 такта, а так на каждой операции вычисления экономите по 8 тактов процессора. Только надо четко разграничить регистры, я так всегда делал, если программа не очень сложная, экономится до 20% времни проца
Человек умный - объяснит
Глупый - будет разбрасываться умными словами.
Я делал на обычной логике, направление определялось на ней, выходы были подключены на два внешних прерывания ,писал на asm , была передача на ком. порт со скоростью 115 кб + динамическая индикация 11 знаков ,индикация находилась в основной цикле задержкой между зажиганием сегментов была передача на ком. ~25кГц как я писал выше все было прекрасно больше и появлялись пропуски .
Yellow Tiger писал(а):VIRGO, спасибо за информацию, но цена у этого агилента какая-то неадекватная (ок. 800 рэ!), уж лучше на малой интеграции делать...
Не удивляюсь, с ценами порой происходит какая-то фантастика.
Ещё вариант: в некоторых PIC контроллерах старшего семейства есть встроенный аппаратный квадратурный декодер.