Код ещё достаточно сырой . Т.к я управление под аппаратный таймер ещё не закончил, то управляющий импульс в 1.5мс делается аппаратно(таймером), а импульс в 20мс - программно :?
PORTB CLR_B(gservo);//В ПРОТЕУСЕ загорелся соответствующий пин!!!! delaysa(period);//Задержка в 20мс, ПОКА использую силы CPU }
Запомните: НИКОГДА НЕ ИСПОЛЬЗУЙТЕ ЗАДЕРЖКИ В ПРЕРЫВАНИЯХ!!!
Прерывания должны обрабатываться максимально быстро. Точка. Если вы хотите вставить задержку в прерывание значит, вы что-то делаете неправильно, подумайте как обойтись без задежки. Обязательно есть другой вариант, и он не на много сложнее!!
aesok писал(а):Запомните: НИКОГДА НЕ ИСПОЛЬЗУЙТЕ ЗАДЕРЖКИ В ПРЕРЫВАНИЯХ!!!
Я руководствовался шестой задачей курса AVR123.nm.ru Там ясно сказано:" Боле "тонко" можно подогнать время между прерываниями добавив в самом начале функции обработчика прерывания по переполнению таймера_0 нужное количество ассемблерных инструкций NOP."
К тому-же инструкция nop занимает всего 1 машинный цикл так что это не так много.
Другое дело что я попытался всё это дело в цикл запихнуть :D :D
aesok писал(а):подумайте как обойтись без задежки
А как тогда управлять сервами с помощью таймера???
ЗЫ Кстати а почему прерывания должны обрабатываться максимально быстро, там что ограничения стоят какие-то?
Вы правильно поняли идею и увеличили разрядность приниманмого числа до 4 знаков. Но посмотрите внимательно но размер масива szInput - он равен 3. А вы в него записываете 5 символов!!! Вам повезло что все сработало. Но если бы переменые были объявлены в таком порядке:
int angle; char szInput [3]; char s;
s оказалась бы на месте 4 элемента масива и командой szInput[3] = USART_Receive(); - была бы изменена.
Всегда внимательно следите за размерностью масивов!
Пока оставим пока только одну серву. С остальными позже.
Для управления одной сервой нужен сигнал в котором, вначале '1' поддерживаеться в течении 1,6+/-0.7 ms (назавем это t), потом '0' в течении (20 - t)ms. И так по кругу.
t = 1,6+/-0.7 ms
'1' - t ms '0' - (20 - t)ms '1' - t ms '0' - (20 - t)ms '1' - t ms '0' - (20 - t)ms .....
Так?
Вот это и нужно запрограмировать в обрадотчике прерывания.
void delaysa(unsigned int mks) { while(mks>0){ mks--; } }
Так делать задежки опасно. На разных уровнях оптимизации может получаться код разной длины, и соответственно будет разное время выполнения этой функции.
Но это не самое страшное, AVR-GCC очень умный компилятор. И он может проанализировать код, увидеть что переменная 'mks' не используеться после цикла, и решить что с ней ничего не надо делать в цикле, и выкинуть ее вместе с циклом. И вся эта функция выродиться в одну инструкцию 'ret'. А может быть и совсем удалена!!!
И еще для практической работы используйте оптимизацию '-0s', считайте что все другие режимы нужны для отладки компилятора.
Используйте макросы _delay_us и _delay_ms. Но в качестве параметра им можно передовать только константу!!!! Внимательно читайте их описание.