Микроконтроллеры, АЦП, память и т.д Темы касающиеся микроконтроллеров разных производителей, памяти, АЦП/ЦАП, периферийных модулей... |
21.10.2008, 20:43
|
|
Вид на жительство
Регистрация: 11.12.2006
Сообщений: 317
Сказал спасибо: 0
Сказали Спасибо 12 раз(а) в 11 сообщении(ях)
|
Весьма интересная задача для AVR (паралельное вычисление)
Сидю кодю.
Прога стала большая, и много всего нада в ней сделать.
Но, если все делать по очереди - все занимает много времени, и как следствие - мк не успевает.
Ести сл. слагаемые:
1. Базовая прога (мало что делает, но нада чтобы делала вовремя).
2. Периферия (читаю АЦП, пишу в ЦАП и т.д.)
3. Вывод на ЖКИ по прирыванию таймера каждые 0.2 сек.
И так.
Базовая прога занимается установкой пинов на вход или выход, пример:
Пин РВ1 -› 0, ждем 0.1 сек, РВ7 -› 1, ждем 3 сек, РВ7,РВ2,РВ1 -› 0 ждем 1 сек.
Паралельно должно отрисовать на ЖКИ, считать периферию.
Задача:
Как по тупому не ганять все в замкнутому циклу для создания временных интервалов (базовая прога), а про прериванию делать прорисокву ЖКИ и читать АЦП и т.д.??
Была идея взять другой таймер и по нем уже делать временные интервалы, но как с преривария возвращатся в разные щести программы - ВОПРОС!
Для примера:
Выводим щас на ЖКИ, приходит информация о продолжении базовой проги (время отсчитали), ждем завершения вывода на ЖКИ и сразу продолжаем базовую прогу. Как сделать на таймере?
|
|
|
|
21.10.2008, 21:26
|
|
Вид на жительство
Регистрация: 30.12.2006
Адрес: Junktown
Сообщений: 300
Сказал спасибо: 164
Сказали Спасибо 171 раз(а) в 59 сообщении(ях)
|
по идее, прерывание таймера можно сделать с интервалом, равным наименьшему из всех интервалов (судя по условиям, 0,1 с). Сделать несколько счетчиков, для каждой из задач свой. По переполнению этих счетчиков выполнять соответствующую задачу...
Также запуск АЦП делать по таймеру, а считывание с него - в прерывании по окончанию преобразования
|
|
|
|
21.10.2008, 21:45
|
|
Вид на жительство
Регистрация: 11.12.2006
Сообщений: 317
Сказал спасибо: 0
Сказали Спасибо 12 раз(а) в 11 сообщении(ях)
|
Возможно.
Тогда пару тупых вопросов.
1. Сработало преривание от таймера 1, тоесть начала выполнсять некоторая подрограмма (например вывод на ЖКИ). В то же время (ЖКИ еще не успел вывести всю информацию) таймер 2 пришел к переполнению и должен вызвать преривание по своему переполнению. Что будет на МК?
а) прервется выполнение преривания от таймера 1 и начнет выполнятся прерывние от таймера 2?
б) подождет окончания выполения преривания от таймера1 и потом начнется обработка преривания от таймера 2?
в) не будет прервано преривание от таймера 1, обработка преривания от таймера 2 не будет, поскольку на момент окончания обработки таймер 2 уже будет считать по новому кругу?
|
|
|
|
21.10.2008, 21:54
|
|
Вид на жительство
Регистрация: 11.12.2006
Сообщений: 317
Сказал спасибо: 0
Сказали Спасибо 12 раз(а) в 11 сообщении(ях)
|
Код:
|
Similarly, if one or more interrupt conditions occur while the Global Interrupt Enable
bit is cleared, the corresponding interrupt flag(s) will be set and remembered until the Global
Interrupt Enable bit is set, and will then be executed by order of priority. |
С даташита следует, что если при выполнении преривания происходит еще одно, тогда оно будет обработано после завершения уже обрабатываемого в порядке приоритета.
Правильно я понял?
Код:
|
The second type of interrupts will trigger as long as the interrupt condition is present. These
interrupts do not necessarily have interrupt flags. If the interrupt condition disappears before the
interrupt is enabled, the interrupt will not be triggered. |
Ниже написано что типо если ето другой тип приревания, тогда оно может не произойти если условие, которое его вызвало будет убрано до завершения предидущего.
Преривания переполнения таймеров к которому виду отнести?
К первому или второму?
Комманда CLI отключает преривания. Все преривания что происходят при этом будут сохранены и выполнены после SEI или нада ждать следубщего возникновение перивания? (как в первом или втором случаях?)
|
|
|
|
21.10.2008, 23:01
|
|
Временная регистрация
Регистрация: 06.12.2007
Сообщений: 91
Сказал спасибо: 0
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
на 1 таймере
Код:
|
unsigned char count;
interrupt tm1()
{
switch(count)
{
case 0:
задача 1
break;
case 1:
задача 2
break;
---------
case 5:
задача 6
break;
}
count++;
if (count == 6)count=0;
} |
__________________
разум когда-нибудь победит... (с)
|
|
|
|
22.10.2008, 00:58
|
|
Вид на жительство
Регистрация: 11.12.2006
Сообщений: 317
Сказал спасибо: 0
Сказали Спасибо 12 раз(а) в 11 сообщении(ях)
|
Спс за код. но сосвем не то.
Не в том вопрос как по очереди исполнять код.
Здача в задержке не в ущерб прериваниям.
И так, налобал на асме:
Код:
|
.equ Global_wait_counter = r16
;------ обработчик по переполнению таймера 1 -------
tcOVF:
tst Global_wait_counter
breq Global_wait_counter_is_zero
dec Global_wait_counter
Global_wait_counter_is_zero:
RETI
;---------------------------------------------------
ldi Global_wait_counter, 10 ; скоко нада ждать
Global_wait_counter_loop:
nop nop nop nop nop nop nop nop nop nop nop nop
tst Global_wait_counter
brne Global_mait_counter_loop |
Другими словами, есть пеерменная, которую декриментит при каждом преривании от таймера, например каждые 0.1 сек. Дальше в основном теле программы есть задатчик на ожидание в виде установки количества циклов по 0.1 сек, который просто крутиться на месте.
В то время как он крутится, основная программа остановлена, а преривания могут выполнятся в нормальнем режиме. По окончанию цикла (когда Global_wait_counter = 0) базовая программа продолжит выполнение.
Как такое решение. Мне самому оно не очень нравится.
Какие будут идеи о улучшению и критика возможних багов плиз.
|
|
|
|
22.10.2008, 09:16
|
|
Временная регистрация
Регистрация: 06.12.2007
Сообщений: 91
Сказал спасибо: 0
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
мне тоже.
Тот выриант, что предложил выше, будет обрабатывать в прерывании короткие задачи. Для длинных дополняем флагами. Которые будут обрабатываться в основном цикле.
Код:
|
typedef union {
struct{
unsigned z1:1;
unsigned z2:1;
unsigned z3:1;
}z;
unsigned char flag;
}un1_;
un1_ un1;
unsigned char count;
interrupt tm1()
{
switch(count)
{
case 0:
проверяем условие возникновения задачи1, если есть,то
un1.z.z1=1;
break;
case 1:
проверяем условие возникновения задачи2, если есть,то
un1.z.z2=1;
break;
---------
case 5:
задача 6
break;
}
count++;
if (count == 6)count=0;
}
main{
for (;;)
{
if (un1.flag !=0)
{
if (un1.z.z1==1)
{
выполняем задачу 1
un1.z.z1=0;
}
if (un1.z.z2==1)
{
выполняем задачу 2
un1.z.z2=0;
} |
Это так называемая вытесняемая многозадачность - пока не выполнится задача 1, задача 2 будет стоять в очереди.
Для того, чтобы скорректировать по приоритету,скажем, задача 2 приоритетней задачи 1, в условии условии выполнения задачи 1 сделать анализ флага задачи2 с досрочным выходом при его появлении.
Флаг задачи 1 при этом будет взведен и после выплнения задачи 2 получится повторное выполнение задачи 1.
Вообще-то существуют специальные ос под это дело - ртос, сальва и пр.
Лично я не юзал.
__________________
разум когда-нибудь победит... (с)
|
|
|
|
22.10.2008, 12:49
|
|
Вид на жительство
Регистрация: 11.12.2006
Сообщений: 317
Сказал спасибо: 0
Сказали Спасибо 12 раз(а) в 11 сообщении(ях)
|
Да, вариант харош для многоприоритетной программы.
У меня только 2 приоритета, высший для базовой программы, низший- для всего остального.
Мне побойдет и вариант на асме.
|
|
|
|
22.10.2008, 19:14
|
|
Почётный гражданин KAZUS.RU
Регистрация: 07.10.2007
Адрес: Луганск
Сообщений: 1,816
Сказал спасибо: 13
Сказали Спасибо 399 раз(а) в 214 сообщении(ях)
|
А нафига вообще основная программа? Всё делаю в прерываниях.
По твоей задаче - прерывание одного таймера 100 микросек - для вывода на ЖКИ побайтно,считываниеАЦП, запуск АЦП, считывание состоянгия входов и обрпботка (подавление дребезга), вывод состояния на ноги.
Дальше считаеш счётчики до необходимого интервала времени и вызываешь обработку задачи при срабатывании счётчика, таких задач можно на одном таймере вешать пока счётчики в ОЗУ закончатся или не хватит ресурчов по скорости.
Для задач которые будут обрабатыватся за время БОЛЬШЕЕ чем период 100 микросек, запусти второй таймер с периодом большим чем обработка самой длинной задачи, или разбей задачи на короткие участки и обрабатывай по кускам.
|
|
|
|
23.10.2008, 22:03
|
|
Вид на жительство
Регистрация: 11.12.2006
Сообщений: 317
Сказал спасибо: 0
Сказали Спасибо 12 раз(а) в 11 сообщении(ях)
|
Да, и лоработка кода.
Надо запретить в базовой программе все прирывания, которые могут мешать работе.
Код:
|
.equ Global_wait_counter = r16
;------ обработчик по переполнению таймера 1 -------
tcOVF:
tst Global_wait_counter
breq Global_wait_counter_is_zero
dec Global_wait_counter
Global_wait_counter_is_zero:
RETI
;---------------------------------------------------
SEI
ldi Global_wait_counter, 10 ; скоко нада ждать
Global_wait_counter_loop:
nop nop nop nop nop nop nop nop nop nop nop nop
tst Global_wait_counter
brne Global_mait_counter_loop
CLI |
Все работает и нормой держит базовую прогу и все приривания.
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 10:47.
|
|