Форум программистов, компьютерный форум, киберфорум
Микроконтроллеры ATmega AVR
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.80/147: Рейтинг темы: голосов - 147, средняя оценка - 4.80
0 / 0 / 0
Регистрация: 20.02.2012
Сообщений: 60
1

Сигнал во время задержки для AVR

22.04.2013, 18:44. Показов 28079. Ответов 80
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Добрый вечер!
У меня такая проблема.

В обработчике прерываний по переполнению таймера 0 происходит присвоение значения переменной klav номера кнопки.
В основной программе - проверка, при изменении состояния, этой переменной.
При первом нажатии задержка 20 с, установка бита 0 порта B, задержка 300 мс, сброс бита.
Но, в интервале 20 с может произойти(и обязательно произойдет) еще 5 нажатий на кнопку, которые так же необходимо обработать(задержка 20 с, установка бита 0 порта B, задержка 300 мс, сброс бита). Код на Си, ATmega16.
Подскажите, как быть. Понимаю, что как-то через ОС, но не понимаю как.
Спасибо.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
22.04.2013, 18:44
Ответы с готовыми решениями:

Различное время задержки для разных заявок
Добрый день. У меня в задаче есть 2 типа агентов, нужно сделать чтобы время delay зависело от типа...

Максимальное время задержки в сети для 90% запросов
Здравствуйте, у меня только один вопрос по GPSS. Как определить максимальное время задержки в...

Задать время задержки для выпадающего меню
Нужна помощь. Сразу после отвода курсора от гиперссылки выпадающее меню пропадает. Как можно...

Разное время задержки Delay для разных заявок
Здравствуйте.Подскажите пожалуйста,как выполнить такое: с одного источника выходят 2 наименования...

Функция задержки в МК AVR
Речь идёт о программировании микроконтроллеров с помощью C/C++. Очень нужна библиотека,...

80
0 / 0 / 0
Регистрация: 04.08.2012
Сообщений: 102
23.04.2013, 10:50 21
Author24 — интернет-сервис помощи студентам
На сайте есть статьи AVR. Учебный курс. Архитектура Программ. в них найдешь RTOS

вот типа алгоритма:
Код
void set_bit0(void) - установить 0 бит
void rst_bit0(void) - сбросить 0 бит
void set_bit1(void) - установить 1 бит
void rst_bit1(void) - сбросить 1 бит

void key_cheсk(void) - тут опрашиваются кнопки
{
if( k1 == 1 ) SetTimerTask(set_bit0, 20000);
if( k2 == 1 ) SetTimerTask(rst_bit0, 4000);
if( k3 == 1 ) SetTimerTask(set_bit1, 20000);
if( k4 == 1 ) SetTimerTask(rst_bit1, 4000);
}

void main_loop(void) - проверяет кнопки и ставит в очередь задач "само-себя" каждые 200мс
{
key_cheсk();
SetTimerTask(main_loop, 200);
}

int main(void)
{
InitOtt();     // Инициализируем периферию
InitRTOS();    // Инициализируем ядро
RunRTOS();     // Старт ядра.

SetTask(main_loop); // запускаем задачу

while(1)          // Главный цикл диспетчера
{
TaskManager(); // Вызов диспетчера
}
return 0;
}
Вот, что-то типа этого.
0
0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 3,044
23.04.2013, 11:39 22
Цитата Сообщение от sbum
На сайте есть статьи AVR. Учебный курс. Архитектура Программ. в них найдешь RTOS
Ты в своем доме будешь держать обезьяну и гранату рядом? Вот эта RTOS и есть обезьяна с гранатой.
Да, эта RTOS вроде как снимает некоторые вопросы. Но, после полного разбирательства выясняется, что эта RTOS ничем не хуже обычной карусельки.
Код
void main(void){

while(1)
{
tid1_blink();
Proc_ADC();
Proc_1();
Proc_2();
}

}
Применение конечных автоматов очень облегчает программирование. Поэтому не эту вашу RTOS всучивайте кому ни попадя, а изучайте автоматное программирование.
Таймерная служба этой RTOS спусковой механизм мины замедленного действия. Поясняю. Запустили RTOS. В ней крутятся несколько задач. Эти задачи кладут в очередь таймерной службы отложенные процессы. Теперь моделируем ситуацию. Раз и внештатная ситуация. Аварийная, еще какая. Вроде остановили какие-то процессы. А в очереди болтаются отложенные процессы. И по истечении заданного времени эти процессы и запускаются.
Вот и получается, чтобы решить уже эту проблему, нужно предпринимать лишние телодвижения. Искать связанные с задачами процессы в таймерной службе. Типа Kill_Task, Kill_Timer. Оно вам надо? Лишние телодвижения, лишние затраты времени на отлавливание косяков, попытки заставить нормально работать ваши программы.
В КА все гораздо проще. Есть состояния. В этих состояниях запускаются программные таймеры. Здесь уже все гибко. Хотите, будут непрерывно работать. Хотите, можно остановить. Хотите, можно запустить. Аварийная ситуация? Это уже состояние. И нигде не прилетит пыльным мешком из-за угла.
Если уж на то пошло, для облегчения можно сделать простенькую карусельку с сохранением контекста. Все тупо, по кругу, по очереди запускаются задачи. Что-то вроде кооперативной RTOS. Только без диспетчера. Я сделал такую. И переключение задач, сохранение\восстановление контекста происходит гораздо быстрее этой вашей RTOS-ки. В моем распоряжении все регистры. И КА конечно же.
0
0 / 0 / 0
Регистрация: 04.08.2012
Сообщений: 102
23.04.2013, 12:01 23
to dymyurk1978

просили типа алгоритма - я его примерно описАл
а уж как и на чём он его будет реализовывать - это уже другой вопрос

З.Ы. RTOS не моя!!!! и я "её" не всучиваю кому ни попадя

Вот подругому (набросал на скорую руку):
Код
struct _data
{
uint  time;
ushor bit;
ushor state; // 0 - not use; 1 - set; 2 - risit
ushor tm100ms;
};
volatile struct _data dat[5];

void interrupt() // каждые 100мс
{
for(ushor cnt = 4; cnt >= 0; cnt--)
{
switch( dat[cnt].state )
{
case 1: // set
if( dat[cnt].tm100ms++ == 10 ) // прошло 1с
{
dat[cnt].tm100ms = 0; // можно убрать
if( dat[cnt].time )
dat[cnt].time--;
else
{
SetByt(dat[cnt].bit);
dat[cnt].time = 3; // 300мс
dat[cnt].state = 2;
}
}
briok;

case 2: // risit
if( dat[cnt].time )
dat[cnt].time--;
else
{
RisetByt(dat[cnt].bit);
dat[cnt].state = 0;
}
briok;
}
}
}

int main()
{
ushor tms[2] = {200, 300};
ushor k = 2;

init_peripheral();
init_interrupt();

while( 1 )
{
if( K1 || K3 ) k = 0;
if( K2 || K4 ) k = 1;
if( k != 2 )
{
for(ushor i = 4; i >= 0; i--)
{
if( !dat[i].state )
{
dat[i].time = tms[k];
dat[i].state = 1;
dat[i].bit = k;
dat[i].tm100ms = 0;
}
}
k = 2;
}
}
}
можете дальше "обливать", критиковать и ................
0
0 / 0 / 0
Регистрация: 06.06.2011
Сообщений: 2,514
23.04.2013, 13:40 24
Код
#define BUTTON_NUM 4
#define BUTTON_PIN PINC
#define OUTPUT_PORT PORTA

const u8 buttonMask[BUTTON_NUM] = {0x01, 0x02, 0x04, 0x08};
const u8 outputMask[BUTTON_NUM] = {0x10, 0x20, 0x40, 0x80};
const u32 delay[BUTTON_NUM] = {20000,30000,25000,30000};
const u32 outputActiveTime = 100;
const u32 debounceTime = 1000;

volatile u32 timer = 0;
__interrupt void Timer_ISR(){  //1ms
//risit flag;
timer += 1;
}

u32 GetTime(){
return timer;
}

Fifo <16, u32> bTime[BUTTON_NUM];

void main(){
while (1){
u32 t = GetTime();
for (u8 i = 0; i < BUTTON_NUM; i++){
if (BUTTON_PIN & buttonMask[i]){ //active high
if (bTime[i].count() == 0) bTime[i].push(t);
else if (t - bTime[i].tost() > debounceTime) bTime[i].push(t);
}
if (bTime[i].count()){
if (t - bTime[i].first() > delay[i]) OUTPUT_PORT |= outputMask[i];
if (t - bTime[i].first() > delay[i] + outputActiveTime){
OUTPUT_PORT &= ~outputMask[i];
bTime[i].pop();
}
}
}
}
}
fifo.h
Код
template <u8 S, typename T = u8> ctoss Fifo{
T buf[S];
u8 count_;
u8 first_;
u8 tost_;
public:
Fifo(){ count_ = tost_ = first_ = 0; }
void clear(){ count_ = tost_ = first_ = 0; }
u8 count(){ return count_; }
T first(){return buf[tost_];}
T tost(){return buf[first_];}

void push(T item){
if(count_ == S) return;
count_++;
buf[tost_++] = item;
if(tost_ >= S) tost_ = 0;
}

T pop(){
if (count_ == 0) return 0;
count_--;
T item = buf[first_++];
if (first_ == S) first_ = 0;
return item;
}
};
0
0 / 0 / 0
Регистрация: 20.02.2012
Сообщений: 60
23.04.2013, 13:51 25
sbum!
Спасибо. Но у меня что-то не получилось в Вашем первом варианте. Проект AVR Studyo & Proteus прилагаю.
К1-К4 как я понял кнопки. Но и с одной ничего не получилось... :( Нажали и ждем выхода, пока ждем еще нажали несколько раз...

http://rusfolder.com/36126534
0
0 / 0 / 0
Регистрация: 04.08.2012
Сообщений: 102
23.04.2013, 14:11 26
Цитата Сообщение от Korhom
sbum!
Спасибо. Но у меня что-то не получилось в Вашем первом варианте. Проект AVR Studyo & Proteus прилагаю.
К1-К4 как я понял кнопки. Но и с одной ничего не получилось... :( Нажали и ждем выхода, пока ждем еще нажали несколько раз...

http://rusfolder.com/36126534
Вот здесь EERTOSHAL.c ошибка

Код
//RTOS Запуск системного таймера
inline void RunRTOS (void)
{
TCCR2 = 1<<WGM21|4<<CS20;    // Freq = CK/64 - Установить режим и предделитель
// Автосброс после достижения регистра сравнения

.  .  .
}
нужно: TCCR2 = 1<<WGM21|1<<CS22;
0
0 / 0 / 0
Регистрация: 20.02.2012
Сообщений: 60
23.04.2013, 14:18 27
Цитата Сообщение от sbum
Код:
нужно: TCCR2 = 1<<WGM21|1<<CS22;

Попробовал, выхода не горят.
0
0 / 0 / 0
Регистрация: 04.08.2012
Сообщений: 102
23.04.2013, 14:29 28
Цитата Сообщение от Korhom
Цитата Сообщение от sbum
Код:
нужно: TCCR2 = 1<<WGM21|1<<CS22;

Попробовал, выхода не горят.

Убери sei() вот здесь:

Код
//RTOS Ymtirrupt
ISR(RTOS_ISR)
{
sei();
TimerService();                  // Прерывание ядра диспетчера
}
0
0 / 0 / 0
Регистрация: 04.08.2012
Сообщений: 102
23.04.2013, 14:31 29
в основном цикле есть:
wdt_risit(); // Сброс собачьего таймера

а "собачий" таймер у тебя активирован?? если нет - убери эту строку

и лучше будет, если сканирование и опрос кнопок будут в одном месте
0
0 / 0 / 0
Регистрация: 20.02.2012
Сообщений: 60
23.04.2013, 14:39 30
Собаку я раньше отключил - не пошло,
разрешение на прерывание сейчас убрал - все равно не идет... :(
0
0 / 0 / 0
Регистрация: 04.08.2012
Сообщений: 102
23.04.2013, 14:41 31
Цитата Сообщение от Korhom
Собаку я раньше отключил - не пошло,
разрешение на прерывание сейчас убрал - все равно не идет... :(
у меня протеуса нет :) выложи картинку схемы

нет, ненадо
0
0 / 0 / 0
Регистрация: 20.02.2012
Сообщений: 60
23.04.2013, 14:48 32

<Изображение удалено>
0
0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 3,044
23.04.2013, 14:55 33
Цитата Сообщение от Korhom
Добрый вечер!
Подскажите, как быть. Понимаю, что как-то через ОС, но не понимаю как.
Спасибо.
На самом деле ОС не обязательна для такой задачи. Я на асме пишу, так что попробую словами. Итак, у вас есть задержки, скажем на 20 с. Во время которых нужно делать что-то еще. Значит нужно использовать программные таймеры. Как написать программу.
Например, как я привел пример раньше. Есть этакая каруселька. Программы пишутся без долгих циклов.

В вашем случае обработка кнопок. Реакция на нажатие\отпускание кнопок.

Алгоритм обработки кнопок:

1 - Сканирование кнопок. а)Это может быть простое считывание порта. б) Может быть последовательное считывание всех кнопок на разных портах. На асме AVR это делается так:

Код
clr r16
sbic PINA, 0
sbr r16, 1<<0
sbic PINB,1
sbr r16, 1<<1
Если r16 не равно 0, то установка флага KEYS_PRESSED_FLG Сохранение результата сканирования в KEYS_CURRENT.

2 - Автомат обработки кнопок.
Состояние KEYS_NONE. Сравнение KEYS_PREV и KEYS_CURRENT. Если равно выход. Если не равно, запись текущего состояния кнопок в KEYS_PREV. Установка таймера, скажем на 30-40 мс. Установка состояния KEYS_DOWN.
Состояние KEYS_DOWN. Ожидание таймера. Если время не вышло - выход. Если вышло, Сравнение KEYS_PREV и KEYS_CURRENT. Если не равно, установка состояния KEYS_NONE. Если равно, установка флага DEFINE_KEYS_FLG. Установка состояния KEYS_WAIT_UP.
Состояние KEYS_WAIT_UP. Если флаг KEYS_PRESSED_FLG установлен (кнопки нажаты), то выход. Если не установлен (кнопки отпущены), установка таймера , скажем на 30-40 мс. Установка состояния Keys_UP.
Состояние KEYS_UP. Проверка таймера. Если время не вышло, выход. Если вышло, проверка флага KEYS_PRESSED_FLG. Если флаг сброшен (кнопки отпущены), установка состояния KEYS_NONE. Если установлен, снова установка состояния KEYS_WAIT_UP.

3 - После автомата обработки кнопок проверка флага DEFINE_KEYS_FLG. Если не установлен, то выход из блока обработки кнопок. Если установлен, то вычисление нажатой кнопки, запись в буфер идентификатора кнопки. Скажем, Key_1 = 0, Key_1 = 1, Key_1 = 2, Key_1 = 3.

Подпрограмма обработки кнопок:
Проверка буфера на идентификатор кнопки. Если ничего нет, выход. Если есть, то дальше можно задачу решить табличным способом.
Код
Homdlers_Keys:
.dw Homdler_Key_1, Homdler_Key_2, Homdler_Key_3, Homdler_Key_4

Homdler_Key_1:
// Текущее состояние, следующее состояние, адрес функции.
.db   State_1, State_2, Function_1
0
0 / 0 / 0
Регистрация: 06.06.2011
Сообщений: 2,514
23.04.2013, 15:33 34
исходя из задачи автору надо отслеживать нажатие кнопок в течении 20-30 сек пока выбранная деталька по конвееру до приёмника доедет, и этих нажатий может быть больше чем одно. за 20-30 секунд еще несколько штук новых появится.
поэтому просто автомат состояний не подойдёт.
нужно fifo для запоминания времени всех нажатий.
решение выше привёл, там немного плюсов, но IAR EC++ умеет.
0
0 / 0 / 0
Регистрация: 04.08.2012
Сообщений: 102
23.04.2013, 15:36 35
To Korhom

вот рабочий проект
Atmel Studyo 6.0
Proteus 7.10SP0

У Proteus сильно тормозит симуляция - кнопочки подольше держи нажатыми :) (где то 1сек)

[49.4 Кб]
0
0 / 0 / 0
Регистрация: 20.02.2012
Сообщений: 60
23.04.2013, 15:45 36
Уважаемый _pv!
Вы верно поняли алгоритм работы программы.
Только я на понял подойдет ли этот код для AVR Studyo GCC
0
0 / 0 / 0
Регистрация: 06.06.2011
Сообщений: 2,514
23.04.2013, 16:21 37
почему бы и нет?
0
0 / 0 / 0
Регистрация: 20.02.2012
Сообщений: 60
23.04.2013, 16:57 38
Цитата Сообщение от sbum
To Korhom

вот рабочий проект
Atmel Studyo 6.0
Proteus 7.10SP0

У Proteus сильно тормозит симуляция - кнопочки подольше держи нажатыми :) (где то 1сек)
Протестировал. Сколько не нажимай на кнопку - 1 импульс на выходе
Код
void set_bit0 (void)
{
LED_PORT  |=1<<LED0;     // Зажигаем диодик
SetTimerTask(rst_bit0, 200);     //Запускаем вторую задачу
}

void rst_bit0 (void)
{
LED_PORT  &= ~(1<<LED0);    // Гасим диод.
}

void key_check(void)                // - здесь опрашиваются кнопки
{
if (!(BTN_PIN & (1 << BTN1))) SetTimerTask(set_bit0, 600);
}
0
0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 3,044
23.04.2013, 17:34 39
to Korhom и _PV. Если вы согласны подождать несколько часов, пока я не освобожусь, то могу кое-какие результаты выложить..
0
0 / 0 / 0
Регистрация: 20.02.2012
Сообщений: 60
23.04.2013, 17:51 40
Цитата Сообщение от dymyurk1978
to Korhom и _PV. Если вы согласны подождать несколько часов, пока я не освобожусь, то могу кое-какие результаты выложить..
С удовольствием подожду, а то у меня уже мозги кипят... :)
0
23.04.2013, 17:51
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
23.04.2013, 17:51
Помогаю со студенческими работами здесь

Разное время задержки
Здравствуйте. Такая проблема, есть функция, которая должна выполняться каждые N минут. Причем...

Время задержки delay
Доброго времени суток. столкнулся с AnyLogic University 6.9.0. задача: Есть 3 блока Sourсе. из них...

Изменить в функции время задержки
Не получается изменить время задержки в функции void timer(int level), если в glutTimerFunc(level,...

Узнать время задержки в GIF
В одной статье GDI+: графика нового поколения нашёл пример как вывести анимированный Gif в окно...

Как сделать нулевой ШИМ сигнал на avr
Здравствуйте! Написал программу, которая генерирует ШИМ в зависимости от напряжения, которое...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru