Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: ARM. Энкодеры и акселерометры
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
Страницы: 1, 2, 3, 4
Zliva
aaarrr СПАСИБО. ЗАРАБОТАЛО!!!

Цитата(aaarrr @ Aug 25 2009, 22:54) *
Я бы сделал примерно так:
Но еще не грех добавить аппаратный или программный антидребезг. В последнем случае прерывания непосредственно от выводов не нужны, все обрабатывается по таймеру.


Не пойму зачем. Я писал, что энкодер оптический, и имеет логику на выходе(0=0в,1 = +5в). Еще одно. Как сюда добавить переменную, которая несет в себе информацию о количестве штришков на энкодере, и связать ее с переменной ENCODER1_Position, то есть, когда ENCODER1_Position ==1023 (1024 импульса/об), то ENCODER1_Position =0,
Но когда ENCODER1_Position ==-1 - ENCODER1_Position =1023?

аaarrr, еще раз спасибо
aaarrr
Цитата(Zliva @ Aug 26 2009, 00:22) *
Не пойму зачем. Я писал, что энкодер оптический, и имеет логику на выходе(0=0в,1 = +5в).

Я просто всегда держу в голове худший вариант. Если энкодер приличный, то можно и обойтись.

Цитата(Zliva @ Aug 26 2009, 00:22) *
Еще одно. Как сюда добавить переменную, которая несет в себе информацию о количестве штришков на энкодере, и связать ее с переменной ENCODER1_Position, то есть, когда ENCODER1_Position ==1023 (1024 импульса/об), то ENCODER1_Position =0,
Но когда ENCODER1_Position ==-1 - ENCODER1_Position =1023?

wacko.gif Ну а тут то какие могут быть проблемы?
Только не 1023, а 1024 в первом случае.

Код
    ENCODER1_Position += enc_step[(pa << 3) | (pb << 2) | (a << 1) | b];
    if(ENCODER1_Position < 0) ENCODER1_Position = ENCODER1_Resolution - 1;
    else if(ENCODER1_Position == ENCODER1_Resolution) ENCODER1_Position = 0;
Zliva
aaarrr СПАСИБО.

Заменил volatile int ENCODER1_Position = 0; вместо volatile unsigned int ENCODER1_Position = 0;
и вставил код:
Код
if (ENCODER1_Position == ENCODER1_resolution){
        ENCODER1_Position = 0;}
    if (ENCODER1_Position == -1){
        ENCODER1_Position = ENCODER1_resolution-1;}

Думаю вопрос о определении положения можно считать РЕШЕННЫМ.

Давайте обсудим вопрос о определении скорости вала энкодера. Какие будут мысли?
aaarrr
Цитата(Zliva @ Aug 26 2009, 00:50) *
Давайте обсудим вопрос о определении скорости вала энкодера. Какие будут мысли?

Давайте. Только изложите сначала свои, а мы их потом "подумаем", хорошо?
Zliva
Цитата(aaarrr @ Aug 26 2009, 00:07) *
Давайте. Только изложите сначала свои, а мы их потом "подумаем", хорошо?

Хорошо! Излагаю теорию.
Скорость – первая производная по перемещению от времени Omega(t)=d phi/dt (еще говорят скорость изменения положения), или исходя из определения производной, прирост функции к приросту аргумента Omega(t)=delta phi/ delta t.
Для того, что бы определить скорость нужно от Omega(t)= {ENCODER1_Positionn- ENCODER1_Position(n-1)}/{ttimen - ttime(n-1)}, если неверно формулирую – поправьте. Соответственно ускорение - первая производная по скорости от времени или вторая производная по перемещению от времени (еще говорят скорость изменения скорости).
Тут возникает вопрос связан с переменой ttime, то есть, как ее лучше определить? Что бы она генерировалась таймером?
примечание. Изложена теория относиться как и к линейному перемещению (скорости, ускорению) так и к угловому перемещению(скорости, ускорению), но разница между ними большая.
aaarrr
Цитата(Zliva @ Aug 26 2009, 09:52) *
Тут возникает вопрос связан с переменой ttime, то есть, как ее лучше определить? Что бы она генерировалась таймером?

Ее даже не обязательно вводить - можно просто вычислять скорость, оценивая перемещение через равные промежутки времени (по таймеру).
Zliva
Цитата(aaarrr @ Aug 26 2009, 13:55) *
Ее даже не обязательно вводить - можно просто вычислять скорость, оценивая перемещение через равные промежутки времени (по таймеру).

Я на копе хочу выводить зависимость phi(t), Omega(t), но пока не знаю, что выбрать таймер или интервальный таймер (PIT) для генерации временной характеристики ttime. В любом случаи ttime понадобится. Использование таймера мне понадобится для определения ускорения по захвату, так как выходи у акселерометра - сигнал ШИМ. Что насчет этого думаете?
@Ark
Цитата
Ее даже не обязательно вводить - можно просто вычислять скорость, оценивая перемещение через равные промежутки времени (по таймеру).

Дык, автору неоднократно это уже советовали (в предыдущих двух темах). smile.gif Но он, почему-то, упорно идет своим путем, и никак не хочет упростить себе задачу...

to Zliva: Зачем Вам фиксировать и передавать время на каждый "тик" энкодера? Не нужно этого делать!
Все что необходимо в этой задаче - это 1 раз каждую миллисекунду (точно по таймеру) копировать счетчики обоих энкодеров, АЦП-ровать два канала акселерометра, формировать пакет для передачи и передавать его в компьютер. И все!

В компьютере Вы принимаете пакеты последовательно и уже знаете, что время для них отличается на 1мс.
Текущее значение счетчика энкодера - это и есть текущее угловое положение вала, только в отсчетах энкодера.
Домножьте на соответствующий коэффициент - получите радианы или градусы (что Вам нужно?).
Разница между двумя значениями счетчика энкодера из соседних пакетов - это уже и есть угловая скорость, только в размерности [отсчетов энкодера/мс]. Также можете перевести ее в [радиан/сек] или [градус/сек].
Разница между соседними значениями скоростей - это угловое ускорение в [отсчетов энкодера/мс^2]. Переведите
в [радиан/сек^2] или [градус/сек^2]. Дальше можно заниматься аппрокимацией, обработкой и так далее.

Как видите, Ваша задача в основном решается программными методами в ПК. От микроконтроллера требуется только "ведение" счетчиков энкодеров (по прерываниям), периодический съем значений этих счетчиков и двух каналов АЦП (точно 1 раз в 1 мс) и передача пакетов известного формата в компьютер. Напрямую, без всяких запросов со стороны ПК.

Зачем Вы взяли ARM для этой задачи? Это задача для AVR или PIC среднего размера, тем более что c AVR Вы знакомы, как говорили. Зачем связались с USB, если нет опыта работы с ним? Через обычный UART можно спокойно передать всю информацию. Дальше - поставьте готовый мост UART-RS232 или UART-USB, и принимайте данные в ПК через COM-порт...

P.S. Если Ваша цель не только решить задачу, но и попутно освоить ARM, USB-интерфейс и так далее, тогда выбор понятен. Если же Вы решаете конкретную практическую задачу (для заказчика), то, по-моему, Вы только усложняете себе жизнь и выполняете массу бесполезной работы.
Zliva
Спасибо за наставление. Но я как-то другого пути не вижу кроме намеченного. Чтобы корректно аппроксимировать нужны точки для Х и для Y, тому нужно значение фиксировать. Полученое значение [отсчетов энкодера/мс], будут переводится на компе в(градус/сек, радиан/сек и.т.).

Цитата
От микроконтроллера требуется только "ведение" счетчиков энкодеров (по прерываниям), периодический съем значений этих счетчиков и двух каналов АЦП (точно 1 раз в 1 мс) и передача пакетов известного формата в компьютер. Напрямую, без всяких запросив…

Все верно.
Задача не коммерческая. Работаю над дисером. Сам инженер конструктор торгового оборудования(стеллажи, витрины), а освоение ARM, USB-интерфейс дело для меня принципиальное. Хочу и все.
@Ark
Цитата
Но я как-то другого пути не вижу кроме намеченного...

Собственно, возможных путей-то здесь два.

Первый (по которому Вы идете) - фиксировать время по таймеру при каждой смене положения энкодера и передавать все это в компьютер.

Второй (который Вам предлагается) - фиксировать "набежавшее" значение счетчика энкодера в строго определенные моменты времени - через каждые 1мс. И передавать только последовательность значений счетчиков с известным точным временным интервалом между ними (1мс).

Разница в объемах передаваемой информации может быть очень значительной - в первом случае может быть на порядок или два больше. Соотвественно, требования к аппаратуре и каналом информации будут намного выше.
Самое интересное, что в конечной точности Вы почти ничего не выиграете...
Zliva
Цитата(@Ark @ Aug 26 2009, 18:18) *
Собственно, возможных путей-то здесь два.

Первый (по которому Вы идете) - ....


Хорошо. Уболтали. Давайте «не вам и не нам». Сделаю два варианта и посмотрю, что лучше. Я думаю что это реально. Перед запуском системы просто буду выбирать один из двух режимов. Годится?
@Ark
Это Вам решать как делать. Советы Вы все равно не очень слушаете. smile.gif
Если задача не коммерческая, то можете реализовать оба варианта и сравнить. Думаю, будет полезно для понимания некоторых вещей. Вы сейчас, к сожалению, некоторые проблемы просто не воспринимаете, так как не сталкивались с ними на практике...
Желаю удачи.
Zliva
@Ark Спасибо за комментарии!
Согласен. Опыта маловато. Для того это и делается, что бы его получить.
Поскольку Вы первым написали и предложили свой вариант, ему и жизнь. Думаю делать так. Задействую RTT для генерации прерываний. Коэффициент деления поставлю RTPRES=32, то тогда время генерации прерываний будет составлять 32/32768=0,976563мс. Сейчас вбиваю код. Когда сделаю, отчитаюсьsmile.gif
aaarrr
Цитата(Zliva @ Aug 26 2009, 19:58) *
Поскольку Вы первым написали и предложили свой вариант, ему и жизнь. Думаю делать так. Задействую RTT для генерации прерываний. Коэффициент деления поставлю RTPRES=32, то тогда время генерации прерываний будет составлять 32/32768=0,976563мс. Сейчас вбиваю код. Когда сделаю, отчитаюсьsmile.gif

Ох. Забудьте про RTT - это самый бесполезный таймер кристалла. Тактируется он от RC-генератора, поэтому 32768 там весьма условные. Кроме того, есть косяк с генерацией прерываний.

Для генерации равномерных временных меток следует использовать PIT.
Zliva
Цитата(aaarrr @ Aug 26 2009, 19:20) *
Ох. Забудьте про RTT - это самый бесполезный таймер кристалла. Тактируется он от RC-генератора, поэтому 32768 там весьма условные. Кроме того, есть косяк с генерацией прерываний.

Для генерации равномерных временных меток следует использовать PIT.

Понял. Тогда как посчитать PIV для частоты 1кГц, при МСК = 47.923200МГц? Что-то у меня не выходит.
Верно ли я понял 47 923 200/1000=47923,2 Приблизительно 47923

Цитата(Zliva @ Aug 26 2009, 22:35) *
Понял. Тогда как посчитать PIV для частоты 1кГц, при МСК = 47.923200МГц? Что-то у меня не выходит.
Верно ли я понял 47 923 200/1000=47923,2 Приблизительно 47923

Сам себе отвечу. Нужно еще поделить на 16 значение 47923, так как PIT тактируется через делитель МСК/16
aaarrr
Цитата(Zliva @ Aug 26 2009, 23:35) *
Понял. Тогда как посчитать PIV для частоты 1кГц, при МСК = 47.923200МГц? Что-то у меня не выходит.
Верно ли я понял 47 923 200/1000=47923,2 Приблизительно 47923

Нет, неверно. У PIT есть еще прескалер на 16, и считает он до PIV. Т.е. PIV = MCK / 16 / F - 1 = 47923200 / 16 / 1000 - 1 = 2994
Если хочется маниакальной точности, то процессор можно запустить и на 48.0MHz от кварца 18.432MHz (кроме AT91SAM7S512/256/128).
Zliva
Возникла новая проблема. С PIT вроде разобрался. Теперь появилась новая проблема, связанная с расстановкой приоритетов и пропуском значений энкодера. Буду разбираться.
Zliva
Цитата(Zliva @ Aug 26 2009, 23:36) *
Возникла новая проблема. С PIT вроде разобрался. Теперь появилась новая проблема, связанная с расстановкой приоритетов и пропуском значений энкодера. Буду разбираться.

Проблема еще актуальна.

Наконец-то спаял датчик ускорения ADXL-210. Теперь в ступоре. Дело в том, что я планировал подключать его к ТС по захвату, но теперь сомневаюсь. Там на выход датчика ШИМ. Как его лучше привязать к прерываниям по PIOA или по таймеру?
Zliva
Скопировал пример с ИАР и компильнул его под свою задачу. Что-то он не идет. Прерывания не работают. Где может быть косяк?
aaarrr
Цитата(Zliva @ Aug 31 2009, 01:19) *
Скопировал пример с ИАР и компильнул его под свою задачу. Что-то он не идет. Прерывания не работают. Где может быть косяк?


Прерывание не оформлено должным образом.

Код
    AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_TC0, TIMER0_INTERRUPT_LEVEL,AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, timer0_c_irq_handler);

void timer0_c_irq_handler(void)
Zliva
С прерываниями разобрался. Записал инициализацию так:
Код
pAIC->AIC_SMR[AT91C_ID_TC0] = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | TIMER0_INTERRUPT_LEVEL;
pAIC->AIC_SVR[AT91C_ID_TC0] = (unsigned long) timer0_c_irq_handler;
pAIC->AIC_IECR = (1UL << AT91C_ID_TC0);

кажись работает.
Помогите разобраться с ТС в режиме захвата. Вот что нашел в интернете (www.analog.com.ru/Public/AN604R.pdf), но как это все привязать для измерения ширины импульсов от датчика ускорения – не могу понять, то есть понимаю, но теоретически. Из документации следует, что с помощью захвата это легко делается, но у меня не получается. Помогите хотя бы получить интервалы Т1 и Т2 для X и Y.
aaarrr
Цитата(Zliva @ Aug 31 2009, 22:21) *
С прерываниями разобрался. Записал инициализацию так:
кажись работает.

Кажись, или работает? Нужно было или добавить обертку, или дописать __irq к timer0_c_irq_handler.

Цитата(Zliva @ Aug 31 2009, 22:21) *
Помогите разобраться с ТС в режиме захвата. Вот что нашел в интернете (www.analog.com.ru/Public/AN604R.pdf), но как это все привязать для измерения ширины импульсов от датчика ускорения – не могу понять, то есть понимаю, но теоретически. Из документации следует, что с помощью захвата это легко делается, но у меня не получается. Помогите хотя бы получить интервалы Т1 и Т2 для X и Y.

Ну а что мешает перейти к практике?
- сконфигурируйте таймер в режиме capture с внутренним тактированием
- подайте сигнал ШИМ на вход TIOA таймера
- настройте LDRA на захват по переднему фронту TIOA
- настройте LDRB на захват по заднему фронту TIOA
В прерывании LDRA считаете период ШИМ, в LDRB - длительность импульса.
Вот и все.
Zliva
Прерывания работают. Все заделал как Вы писали.
Верно ли я понял, замыкаю два входа TIOA1 и TIOВ1. Конфигурирую так как описано выше и измеряю X, затем также и для TIOA0 и TIOВ0 и измеряю Y.
aaarrr
Цитата(Zliva @ Sep 1 2009, 00:48) *
Верно ли я понял, замыкаю два входа TIOA1 и TIOВ1. Конфигурирую так как описано выше и измеряю X, затем также и для TIOA0 и TIOВ0 и измеряю Y.

Нет. И LDRA и LDRB срабатывают по TIOA, TIOB вообще не нужен в данном случае.
Zliva
Цитата(aaarrr @ Sep 1 2009, 00:03) *
Нет. И LDRA и LDRB срабатывают по TIOA, TIOB вообще не нужен в данном случае.


Настроил захват для измерения ШИМ. Может будут какие-то комментарии. Сейчас на работе, реально залью прошивку дома.
Код
void AT91F_TC_Open ( AT91PS_TC TC_pt, unsigned int Mode, unsigned int TimerId)
{
    unsigned int dummy;
    AT91F_PMC_EnablePeriphClock ( AT91C_BASE_PMC, 1<< TimerId );
    TC_pt->TC_CCR = AT91C_TC_CLKDIS;
    TC_pt->TC_IDR = 0xFFFFFFFF;
            dummy = TC_pt->TC_SR;
            dummy = dummy;
    TC_pt->TC_CMR = Mode;
TC_pt->TC_CMR = ((unsigned int) 0x0 << 15)    
|    AT91C_TC_CLKI
|    AT91C_TC_BURST_NONE    
|     AT91C_TC_LDBSTOP        
|    AT91C_TC_LDBDIS
|    AT91C_TC_ETRGEDG_NONE        
|    AT91C_TC_LDRA_RISING
|    AT91C_TC_LDRB_FALLING;
    
TC_pt->TC_CCR = AT91C_TC_CLKEN;
}

В режиме симулятора timer1 работает. Дергаю PIN15 в симуляторе работает. Но когда дергаю PIN0 (смотрите схему), появляется You have tried to modify a port pin which is configured as output! Что делать? И еще глупые вопросы. Как после прерывания сбросить после считывания в 0? Что означает эта запись «dummy = dummy»?
p.s.
aaarrr – Вам огромное человеческое СПАСИБО. Хоть кто-то поддерживает меня. Не люблю быть должным. Со временем буду это все оформлять в статью. Если Вы не против, могу Вас включить.
aaarrr
Цитата(Zliva @ Sep 1 2009, 14:29) *
В режиме симулятора timer1 работает. Дергаю PIN15 в симуляторе работает. Но когда дергаю PIN0 (смотрите схему), появляется You have tried to modify a port pin which is configured as output! Что делать?

PIN0 - TIOA0, и относится к нулевому таймеру, его сконфигурировать не забыли?

Цитата(Zliva @ Sep 1 2009, 14:29) *
Как после прерывания сбросить после считывания в 0?

Не понял вопрос.

Цитата(Zliva @ Sep 1 2009, 14:29) *
Что означает эта запись «dummy = dummy»?

Это достаточно некрасивый трюк для подавления warning'а компилятора.
Код
    dummy = TC_pt->TC_SR;
    dummy = dummy;

можно заменить на
Код
    TC_pt->TC_SR;


Цитата(Zliva @ Sep 1 2009, 14:29) *
Если Вы не против, могу Вас включить.

Спасибо, конечно, но не стоит smile.gif
Zliva
Цитата(aaarrr @ Sep 2 2009, 15:30) *
PIN0 - TIOA0, и относится к нулевому таймеру, его сконфигурировать не забыли?

Как его настроить?

Цитата
Не понял вопрос.

У меня сначала прога в прерывание заходила один раз и все. Но когда закомментировал AT91C_TC_LDBDIS, все вроде заработало. Верно ли я сконфигурировал TC_CMR?

И еще. Сегодня пробовал тестировать на осциллографе дачик ускорения. Все вроде ок. ШИМ генерируется, аналоговый выход работает, но когда я кручу плату в плоскости X, Y(плоскость перпендикулярна земле) -. Взял контактор на 220В для эксперимента. Прикрепил дачки к якорю. Придерживая контактор отверткой изменяю его амплитуду. Изменений ШИМ и аналога нет. Тряс, крутил, что только не делал(по нем не прыгал) ничего. Можно считать что механика в нутрии датчика умерла? Кто нибудь работал с серией ADXL202/210? Думаю приобрести такой же датчик (просто все под него сделано) и парочку LIS302DL с интерфейсом SPI и на три оси. Что народ скажет?
aaarrr
Цитата(Zliva @ Sep 2 2009, 21:41) *
Как его настроить?

Понятно, это была только часть кода. Что-то не вижу настройки PIO для TIOAx.

Старайтесь не копировать "библиотечные" функции типа AT91F_ - получаете набор маразмов (типа dummy) и
просто ошибок как здесь:
Код
void AT91F_TC_Open ( AT91PS_TC TC_pt, unsigned int Mode, unsigned int TimerId)
{
    ...
    TC_pt->TC_CMR = Mode;

    TC_pt->TC_CMR = ((unsigned int) 0x0 << 15)    /*0 -режим захвата разрешен.*/

Mode пишется в никуда.

Цитата(Zliva @ Sep 2 2009, 21:41) *
У меня сначала прога в прерывание заходила один раз и все. Но когда закомментировал AT91C_TC_LDBDIS, все вроде заработало. Верно ли я сконфигурировал TC_CMR?

А зачем запрещать или останавливать (как это сделано сейчас) таймер по LDRB? Так же все измерения лесом пойдут.
Zliva
Цитата(aaarrr @ Sep 2 2009, 21:23) *
Понятно, это была только часть кода. Что-то не вижу настройки PIO для TIOAx.

Старайтесь не копировать "библиотечные" функции типа AT91F_ - получаете набор маразмов (типа dummy) и
просто ошибок как здесь:
Mode пишется в никуда.

Что именно здесь не так?

Вот так инициализирую. Больше нигде не используется TIOA. Или нужно где-то прописать TIOA еще?

Код
#define TIOA0           (1<<0)
#define TIOA1           (1<<15)
#define TIOA0_MASK      (1<<0)
#define TIOA1_MASK      (1<<15)
#define TIOA_MASK       (TIOA0_MASK|TIOA1_MASK)
…….
int main (void) {
  *AT91C_PMC_PCER =     (1UL << AT91C_ID_PIOA) |
                               (1UL << AT91C_ID_IRQ0) |  
                                (1UL << AT91C_ID_US0)  |  
                (1UL << AT91C_ID_TC1);

  pPIO->PIO_PER  = LED_MASK;
  pPIO->PIO_OER  = LED_MASK;
  pPIO->PIO_SODR = LED_MASK;

  init_timer ();
  pioa_irq_init();
  init_serial();
  timer_init ();

  while (1) {
    pPIO->PIO_CODR = LED1;
    wait(10);
    printf ("E1=%8.2f",accel_X);  
    pPIO->PIO_SODR = LED1;                       
    wait(10);  
}
}

Что скажете насчет работоспособности датчика. Пост выше?
Zliva
Подскажите пожалуйста (код выше). Дело в том что если LDRBS = 1 значение в В заноситься (спадающий фронт), LDRАS = 1 значение в А заноситься (нарастающий фронт). В чем может быть проблема? Что я делаю не так?
aaarrr
Цитата(Zliva @ Sep 2 2009, 23:20) *
Вот так инициализирую. Больше нигде не используется TIOA. Или нужно где-то прописать TIOA еще?

Тут только дефайны, где инициализация? Нужно перевести TIOAx в режим Peripheral.

Цитата(Zliva @ Sep 3 2009, 12:37) *
Подскажите пожалуйста (код выше). Дело в том что если LDRBS = 1 значение в В заноситься (спадающий фронт), LDRАS = 1 значение в А заноситься (нарастающий фронт). В чем может быть проблема? Что я делаю не так?

Постарайтесь описать проблему так, чтобы можно было понять.
Zliva
Цитата(aaarrr @ Sep 3 2009, 13:37) *
Тут только дефайны, где инициализация? Нужно перевести TIOAx в режим Peripheral.

Как это можно сделать? Что-то не встречал примеров, или просто не туда смотрю.
Цитата
Постарайтесь описать проблему так, чтобы можно было понять.

Имелось ввиду, что когда возникает прерывание по фронтам, нужно его разрешить
Код
AT91C_BASE_TC1->TC_IER  = AT91C_TC_LDRAS|AT91C_TC_LDRBS;

Правильно ли я понял?
aaarrr
Цитата(Zliva @ Sep 3 2009, 19:02) *
Как это можно сделать? Что-то не встречал примеров, или просто не туда смотрю.

Смотреть надо документацию:
10.4 PIO Controller A Multiplexing
27. Parallel Input/Output Controller (PIO)
На все случаи примеров не найдете.

Код
*AT91C_PIOA_BSR = TIOA_MASK;
*AT91C_PIOA_PDR = TIOA_MASK;


Цитата(Zliva @ Sep 3 2009, 19:02) *
Имелось ввиду, что когда возникает прерывание по фронтам, нужно его разрешить
Код
AT91C_BASE_TC1->TC_IER  = AT91C_TC_LDRAS|AT91C_TC_LDRBS;

Правильно ли я понял?

Все равно ничего не понял. Прерывание возникает, когда оно уже разрешено.
Zliva
Цитата(aaarrr @ Sep 3 2009, 18:12) *
Смотреть надо документацию:
10.4 PIO Controller A Multiplexing
27. Parallel Input/Output Controller (PIO)
На все случаи примеров не найдете.

Посмотрите пожалуйста полностью все исподники. Может будут какие-то комментарии.
Не могу с *AT91C_PIOA_BSR = TIOA_MASK и с *AT91C_PIOA_PDR = TIOA_MASK разобраться.
Цитата
Все равно ничего не понял. Прерывание возникает, когда оно уже разрешено.

Вот что имелось в виду (см. картинку). В момент появления нарастающего фронта Та возникает прерывание по нарастающему фронту (LDRАS = 1), значение заносится в RА и сохраняем его в Var_Та. Когда возникает прерывание (LDRВS = 1) по спадающему фронту в момент Тb значение заносится в RВ и сохраняется Var_Тb. При появление нарастающего фронта Те возникает прерывание по нарастающему фронту снова, и мы сохраняем его в Var_Те. Вот (я так думаю) нужна эта запись AT91C_BASE_TC1->TC_IER = AT91C_TC_LDRAS|AT91C_TC_LDRBS. Но я могу ошибаться. Я вот еще что думаю. Возможнее все-таки переполнение счетчика. Как здесь быть?
aaarrr
Цитата(Zliva @ Sep 3 2009, 19:51) *
Посмотрите пожалуйста полностью все исподники. Может будут какие-то комментарии.
Не могу с *AT91C_PIOA_BSR = TIOA_MASK и с *AT91C_PIOA_PDR = TIOA_MASK разобраться.

Я тоже не могу все досконально проверить и еще пересказать документацию. Просто изучите даташит, ничего сложного в этом не вижу.

Цитата(Zliva @ Sep 3 2009, 19:51) *
Вот что имелось в виду (см. картинку). В момент появления нарастающего фронта Та возникает прерывание по нарастающему фронту (LDRАS = 1), значение заносится в RА и сохраняем его в Var_Та. Когда возникает прерывание (LDRВS = 1) по спадающему фронту в момент Тb значение заносится в RВ и сохраняется Var_Тb. При появление нарастающего фронта Те возникает прерывание по нарастающему фронту снова, и мы сохраняем его в Var_Те. Вот (я так думаю) нужна эта запись AT91C_BASE_TC1->TC_IER = AT91C_TC_LDRAS|AT91C_TC_LDRBS. Но я могу ошибаться. Я вот еще что думаю. Возможнее все-таки переполнение счетчика. Как здесь быть?

Ну да, чтобы получать прерывания по факту загрузки RA и RB их нужно предварительно разрешить. В этом и состоял вопрос?

С логикой все немного не так: по каждой загрузке RA смотрим разницу с предыдущим значением и получаем таким образом период ШИМ, по загрузке RB - смотрим разницу RB-RA и получаем длительность импульса. На основании этих двух чисел получаем результат. И переполнение таймера не страшно, если, конечно, его период не выбран меньше периода ШИМ-сигнала.
Zliva
Вот так инициализирую

Код
#define LED1            (1<<17)
#define LED2            (1<<18)
#define NB_LED         2
#define LED_MASK    (LED1|LED2)

#define SW1_MASK   (1<<20)
#define SW2_MASK   (1<<19)
#define SW_MASK     (SW1_MASK|SW2_MASK)      
#define SW1             (1<<20)
#define SW2             (1<<19)
  
#define TIOA0           (1<<0)
#define TIOA1           (1<<15)
#define TIOA0_MASK (1<<0)
#define TIOA1_MASK (1<<15)
#define TIOA_MASK   (TIOA0_MASK|TIOA1_MASK)    

#define ENCODER1_A_MASK        (1<<26)
#define ENCODER1_B_MASK        (1<<28)
#define ENCODER2_A_MASK        (1<<29)
#define ENCODER2_B_MASK        (1<<30)
#define ENCODER_A_MASK         (ENCODER1_A_MASK|ENCODER1_B_MASK|ENCODER2_A_MASK|ENCODER2_B_MASK)

#define ENCODER1_A             (1<<26)
#define ENCODER1_B             (1<<28)
#define ENCODER2_A             (1<<29)
#define ENCODER2_B             (1<<30)
….
/*OUTPUT*/             
    pPIO->PIO_PER   = LED_MASK;
    pPIO->PIO_OER   = LED_MASK;
    pPIO->PIO_SODR = LED_MASK;
/*INPUT*/
    pPIO->PIO_ODR  = SW_MASK;
    pPIO->PIO_PER  = SW_MASK;
    pPIO->PIO_IER  = ENCODER_A_MASK;
/*INPUT peripheral*/
    pPIO->PIO_BSR = TIOA_MASK;
    pPIO->PIO_PDR = TIOA_MASK;

Вся периферия работает. Но вот эта ошибка достала. Что делать?
---------------------------
PIOA Error
---------------------------
You have tried to modify a port pin which is configured as output!
aaarrr
Цитата(Zliva @ Sep 3 2009, 23:18) *
Что делать?

Плюнуть на сообщения симулятора.
Zliva
Цитата(aaarrr @ Sep 3 2009, 22:25) *
Плюнуть на сообщения симулятора.

Спасибо, так и заделаю. Буду дальше ШИМ душить
aaarrr
Цитата(Zliva @ Sep 3 2009, 23:33) *
Спасибо, так и заделаю. Буду дальше ШИМ душить

Правильно: вообще не стоит полагаться на симуляцию периферии. Если таймеры настроены идентично, а ругается он только на один, то это явный косяк.
Zliva
Цитата(aaarrr @ Sep 3 2009, 22:52) *
Правильно: вообще не стоит полагаться на симуляцию периферии. Если таймеры настроены идентично, а ругается он только на один, то это явный косяк.

Что вы имеете ввиду?
И еще, когда пины 27, 28, 29, 30 энкодера настраиваю на вход, в симуляции пин 27 выдает коварное сообщение (которое выше), которое я игнорирую, но когда пины 26, 28, 29, 30 энкодера настраиваю на вход, в симуляции пин 26 работает нормально.
aaarrr
Цитата(Zliva @ Sep 4 2009, 00:06) *
Что вы имеете ввиду?

Выше упоминалась такая ситуация с TIOAx.

Цитата(Zliva @ Sep 4 2009, 00:06) *
И еще, когда пины 27, 28, 29, 30 энкодера настраиваю на вход, в симуляции пин 27 выдает коварное сообщение (которое выше), которое я игнорирую, но когда пины 26, 28, 29, 30 энкодера настраиваю на вход, в симуляции пин 26 работает нормально.

Угу. Просто надо все смотреть на железе.
Zliva
Есть проблемка с ADXL210AQC – он не работает. На Украине не могу нигде купить.
Остановил свой выбор на MMA7261QT (выходной сигнал аналог) и LIS302DL(выходной сигнал SPI/I2S). Кто-то работал с этими датчиками? Может, порекомендуете какие-то другие? Буду рад всем предложениям. Все равно покупать. Так что ШИМ наверное отпадает. Хотя плюсы в этом есть. Освоил ТС, это уже что-то.
Zliva
Настало время USB. Пока доставят акселерометры, не буду тратить время. Вы говорили, что в моем случае класс CDC вполне подойдет и тип передачи данных bulk, так я писал, что нужна гарантия доставки данных. Начитался Агурова. Кругом голова идет. Много информации в книгах, а четко выраженной последовательности нет, или я пока себе её не сформировал. Ну да ладно. Впринципе, со стороны МК проблем не вижу, а вот со стороны ПК нужно потрудится. Может у кого-то есть заготовка для инициализации дескрипторов для МК в случаи использования класса CDC? И еще, не нашол информации. RS-232 дет скорость 115,2кБит/с, в случаи использования CDC, я могу получить скорость 12 МБит/с, или я ошибаюсь?
Может когда-то по-играюсь с OTG через MS и с флеш карточкой.
head_sk
Цитата(Zliva @ Sep 6 2009, 01:38) *
Может у кого-то есть заготовка для инициализации дескрипторов для МК в случаи использования класса CDC?


Код
const char devDescriptor[] =  {
    /* Device descriptor */
    0x12,  // bLength
    0x01,  // bDescriptorType
    0x10,  // bcdUSBL
    0x01,  //
    0x02,  // bDeviceClass:    CDC class code
    0x00,  // bDeviceSubclass: CDC class sub code
    0x00,  // bDeviceProtocol: CDC Device protocol
    0x08,  // bMaxPacketSize0
    0xFF,  // idVendorL
    0xFF,  //
    0xFF,  // idProductL
    0xFF,  //
    0x10,  // bcdDeviceL
    0x01,  //
    0x00,  // iManufacturer    // 0x01
    0x00,  // iProduct
    0x00,  // SerialNumber
    0x01  // bNumConfigs
  };

  const char cfgDescriptor[] =  {
    /* ============== CONFIGURATION 1 =========== */
    /* Configuration 1 descriptor */
    0x09,  // CbLength
    0x02,  // CbDescriptorType
    0x43,  // CwTotalLength 2 EP + Control
    0x00, 0x02,  // CbNumInterfaces
    0x01,  // CbConfigurationValue
    0x00,  // CiConfiguration
    0xC0,  // CbmAttributes 0xA0
    0x00,  // CMaxPower

    /* Communication Class Interface Descriptor Requirement */
    0x09,  // bLength
    0x04,  // bDescriptorType
    0x00,  // bInterfaceNumber
    0x00,  // bAlternateSetting
    0x01,  // bNumEndpoints
    0x02,  // bInterfaceClass
    0x02,  // bInterfaceSubclass
    0x00,  // bInterfaceProtocol
    0x00,  // iInterface

    /* Header Functional Descriptor */
    0x05,  // bFunction Length
    0x24,  // bDescriptor type: CS_INTERFACE
    0x00,  // bDescriptor subtype: Header Func Desc
    0x10,  // bcdCDC:1.1
    0x01,

    /* ACM Functional Descriptor */
    0x04,  // bFunctionLength
    0x24,  // bDescriptor Type: CS_INTERFACE
    0x02,  // bDescriptor Subtype: ACM Func Desc
    0x00,  // bmCapabilities

    /* Union Functional Descriptor */
    0x05,  // bFunctionLength
    0x24,  // bDescriptorType: CS_INTERFACE
    0x06,  // bDescriptor Subtype: Union Func Desc
    0x00,  // bMasterInterface: Communication Class Interface
    0x01,  // bSlaveInterface0: Data Class Interface

    /* Call Management Functional Descriptor */
    0x05,  // bFunctionLength
    0x24,  // bDescriptor Type: CS_INTERFACE
    0x01,  // bDescriptor Subtype: Call Management Func Desc
    0x00,  // bmCapabilities: D1 + D0
    0x01,  // bDataInterface: Data Class Interface 1

    /* Endpoint 1 descriptor */
    0x07,  // bLength
    0x05,  // bDescriptorType
    0x83,  // bEndpointAddress, Endpoint 03 - IN
    0x03,  // bmAttributes      INT
    0x0A,  // wMaxPacketSize
    0x00, 0xFF,  // bInterval

    /* Data Class Interface Descriptor Requirement */
    0x09,  // bLength
    0x04,  // bDescriptorType
    0x01,  // bInterfaceNumber
    0x00,  // bAlternateSetting
    0x02,  // bNumEndpoints
    0x0A,  // bInterfaceClass
    0x00,  // bInterfaceSubclass
    0x00,  // bInterfaceProtocol
    0x00,  // iInterface

    /* First alternate setting */
    /* Endpoint 1 descriptor */
    0x07,  // bLength
    0x05,  // bDescriptorType
    0x01,  // bEndpointAddress, Endpoint 01 - OUT
    0x02,  // bmAttributes      BULK
    AT91C_EP_OUT_SIZE,  // wMaxPacketSize
    0x00, 0x00,  // bInterval

    /* Endpoint 2 descriptor */
    0x07,  // bLength
    0x05,  // bDescriptorType
    0x82,  // bEndpointAddress, Endpoint 02 - IN
    0x02,  // bmAttributes      BULK
    AT91C_EP_IN_SIZE,  // wMaxPacketSize
    0x00, 0x00  // bInterval
  };

  const char languageIdDescriptor[] =  {
    0x04, 0x03, 0x09, 0x04
  };

  const char manufacturerDescriptor[] =  {

    10, 3, 'F', 0, 'I', 0, 'R', 0, 'M', 0
  };

  const char serialNumberDescriptor[] =  {

    10, 3, '1', 0, '2', 0, '3', 0, 'A', 0
  };

  const char nameDeviseDescriptor[] =  {

    14, 3, 'D', 0, 'E', 0, 'V', 0, 'I', 0,'C',0,'E',0
  };
aaarrr
Цитата(Zliva @ Sep 6 2009, 02:38) *
Впринципе, со стороны МК проблем не вижу, а вот со стороны ПК нужно потрудится.

В случае CDC все как раз наоборот.

Цитата(Zliva @ Sep 6 2009, 02:38) *
И еще, не нашол информации. RS-232 дет скорость 115,2кБит/с, в случаи использования CDC, я могу получить скорость 12 МБит/с, или я ошибаюсь?

Тыц
head_sk
Советую использовать libusb
Zliva
Вот здесь скачал реализацию CDC, в IAR-е получил бинарник и залил в кристалл. Работает. В Keil-е не хочет. Вот код.
aaarrr
Здесь можете скачать атмеловские примеры для IAR, Keil и GCC.

Качество - ниже плинтуса, поэтому использовать не рекомендую (как и найденное вами).
Zliva
Может кто-то имеет нормальную, работоспособную версию реализации CDC? Версия с атмела тоже какая-то кучерявая.
aaarrr
Боюсь, бесплатно будут только "кучерявые" - на то они и примеры.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.