реклама на сайте
подробности

 
 
3 страниц V  < 1 2 3 >  
Reply to this topicStart new topic
> Таймер на Atmega8, Работает при симуляции, но не работает в железе
Tarbal
сообщение Oct 18 2013, 11:28
Сообщение #16


Профессионал
*****

Группа: Свой
Сообщений: 1 351
Регистрация: 21-05-10
Пользователь №: 57 439



Цитата(alexeyv @ Oct 18 2013, 07:11) *
2 Tarbal:
Где case 3: ??

Sorry

case 2:
if(button_pressed())
{
state = 3;
timeout = 5;
}
break;

case 3:
if(--timeout == 0)

Цитата(Палыч @ Oct 18 2013, 08:55) *
IMHO, вредный совет для разработки устройств с батарейным питанием.


Это почему это?
От прерывания можно просыпаться, но использовать его для обработки нажатия дребезжащей кнопки очень нехорошо. Я видел как люди боролись с нестингом, создавая ненужные сущности.
В итоге они создавали програмных монстров и франкенштейнов.

Цитата(shatov @ Oct 16 2013, 07:19) *
При симуляции всё работает, но при реализации на макетной плате ничего не выходит.


При симуляции у Вас нет дребезжащей кнопки, поэтому условие сравнивания количества нажатий с единицей проходит. В реальности количество нажатий больше единицы и сравнение с единиицей не выстреливает.

Сообщение отредактировал Tarbal - Oct 18 2013, 11:24
Go to the top of the page
 
+Quote Post
Палыч
сообщение Oct 18 2013, 12:45
Сообщение #17


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(Tarbal @ Oct 18 2013, 15:28) *
Это почему это?
От прерывания можно просыпаться, но использовать его для обработки нажатия дребезжащей кнопки очень нехорошо.

Чтобы не "создавать ненужные сущности".
Я понимаю, что кому то нравиться поллинг, кому то прерывания... Но, коль в данном случае мы вынуждены пользоваться прерыванием, то накладывать на него ещё и поллинг - это и есть "ненужные сущности". Методы борьбы с дребезгом кнопки, подключенной к линии генерации прерывания int0 - банальны: аккуратно запретить прерывание от int0 на время несколько бОльшее, чем время дребезга.

to TC
Прошу прощения, выше я Вам дал "вредный" совет - использовать прерывание по спаду для фиксации факта нажатия на кнопку. Дело в том, что выход из "Idle mode" возможен только по уровню, но никак не по перепаду...
Go to the top of the page
 
+Quote Post
Tarbal
сообщение Oct 18 2013, 14:03
Сообщение #18


Профессионал
*****

Группа: Свой
Сообщений: 1 351
Регистрация: 21-05-10
Пользователь №: 57 439



Цитата(Палыч @ Oct 18 2013, 16:45) *
Чтобы не "создавать ненужные сущности".
Я понимаю, что кому то нравиться поллинг, кому то прерывания... Но, коль в данном случае мы вынуждены пользоваться прерыванием, то накладывать на него ещё и поллинг - это и есть "ненужные сущности". Методы борьбы с дребезгом кнопки, подключенной к линии генерации прерывания int0 - банальны: аккуратно запретить прерывание от int0 на время несколько бОльшее, чем время дребезга.

to TC
Прошу прощения, выше я Вам дал "вредный" совет - использовать прерывание по спаду для фиксации факта нажатия на кнопку. Дело в том, что выход из "Idle mode" возможен только по уровню, но никак не по перепаду...


Мне не нравится ни поллинг ни прерывания. Я применяю то, что больше подходит.
Мое решение выверено временем я применял его в устройствах, которые больше 15 лет уже работают причем в больших количествах. Кстати и свидетелем неуемной борьбы с нестингом прерываний дребезжащего контакта я тоже был. Пока я не переделал на поллинг проблемы не кончались. Манипуляция с запретом прерываний на время это беда.


Палыч, а хотите я расскажу вам про приоритеты прерываний то, что я знаю давно, а вы не знаете.
Go to the top of the page
 
+Quote Post
Палыч
сообщение Oct 18 2013, 16:45
Сообщение #19


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(Tarbal @ Oct 18 2013, 18:03) *
Я применяю то, что больше подходит.
И, это - правильно. Полностью с Вами согласен.
Цитата(Tarbal @ Oct 18 2013, 18:03) *
Манипуляция с запретом прерываний на время это беда.
Возможно, вы недопоняли... Речь шла не о полном (глобальном) запрете прерываний, а о врЕменном запрете только прерывания INT0,
Цитата(Tarbal @ Oct 18 2013, 18:03) *
Палыч, а хотите я расскажу вам про приоритеты прерываний то, что я знаю давно, а вы не знаете.
Если Вы знаете что-то такое о прерываниях в AVR, что не отражено в документации производителя, то - расскажите. Эта информация, вероятно, будет полезна многим. Наверное, уместнее будет это сделать в специально созданной для этого теме.
Go to the top of the page
 
+Quote Post
Tarbal
сообщение Oct 18 2013, 18:04
Сообщение #20


Профессионал
*****

Группа: Свой
Сообщений: 1 351
Регистрация: 21-05-10
Пользователь №: 57 439



Цитата(Палыч @ Oct 18 2013, 20:45) *
И, это - правильно. Полностью с Вами согласен.
Возможно, вы недопоняли... Речь шла не о полном (глобальном) запрете прерываний, а о врЕменном запрете только прерывания INT0,

Проходили это. Не нашли хорошего решения.


Цитата(Палыч @ Oct 18 2013, 20:45) *
Если Вы знаете что-то такое о прерываниях в AVR, что не отражено в документации производителя, то - расскажите. Эта информация, вероятно, будет полезна многим. Наверное, уместнее будет это сделать в специально созданной для этого теме.

Да я просто выпендриться захотел сгоряча. Однако есть один тонкий момент с пониманием приоритета прерывания, о котором мало кто думает. Знать может и знают, но не осознают.
Дело в том, что в мелких микропроцессорах если обрабатывается прерывание, другое прерывание вызвать обработчик не сможет. Однако есть такое понятие как приоритет прерываний. Что оно означает? Оно означает в каком порядке будут вызываться прерывания, которые ждали обработки, пока либо обрабатывалось прерывание, либо прерывания были запрещены.
Однако в более мощных процессорах есть приоритет прерывания, означающий, что прерывание может прервать обработчик низкоприоритетного прерывания. Таким образом есть два различных понятия, которые называются одинаково.

Сообщение отредактировал Tarbal - Oct 18 2013, 18:08
Go to the top of the page
 
+Quote Post
shatov
сообщение Oct 18 2013, 19:10
Сообщение #21





Группа: Новичок
Сообщений: 5
Регистрация: 17-09-13
Пользователь №: 78 360



Решил переделать программно, поставив вторую кнопку на INT1. Всё заработало.

#include <mega8.h>
#include <delay.h>

char sec=0;
int min=0;
int hour=0;
char secH=0, secL=0;
int flagbutton0=0, flagbutton1=1;
char dayH=0, dayL=0;

void(* resetFunc) (void) = 0; // Reset MC function

interrupt [EXT_INT0] void ext_int0_isr(void)
{
flagbutton0=1;
flagbutton1=0;
if (PIND.2==0&&PIND.3==0) {resetFunc();}
}

interrupt [EXT_INT1] void ext_int1_isr(void)
{
flagbutton1=1;
flagbutton0=0;
if (PIND.2==0&&PIND.3==0) {resetFunc();}
}

interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{
secL++;
if (secL>9) {secH++; secL=0; flagbutton0=0; flagbutton1=0;}
if (secH>5) {secH=0;}
if (sec>59) {min++; sec=0;}
if (min>59) {hour++; min=0;}
if (hour>23) {dayL++; hour=0;}
if (dayL>9) {dayH++; dayL=0;}
if (dayH>9) {dayH=0;}
}




void main(void)
{

PORTB=0x20;
DDRB=0x1F;
PORTD=0x0C;
DDRD=0xF3;
PORTC=0x00;
DDRC=0xFF;

ASSR=0x08;
TCCR2=0x05;
TCNT2=0x00;
OCR2=0x00;

GICR|=0xC0;
MCUCR=0xB1;
GIFR=0xC0;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x40;

#asm("sei");

while (1)
{while (flagbutton0==1)
{
switch(secL)
{
case 0:{PORTD=~0x40; PORTB.1=1; break;}
case 1:{PORTD=~0x71; PORTB.1=0; break;}
case 2:{PORTD=~0xA0; PORTB.1=1; break;}
case 3:{PORTD=~0x30; PORTB.1=1; break;}
case 4:{PORTD=~0x11; PORTB.1=0; break;}
case 5:{PORTD=~0x12; PORTB.1=1; break;}
case 6:{PORTD=~0x02; PORTB.1=1; break;}
case 7:{PORTD=~0x70; PORTB.1=0; break;}
case 8:{PORTD=~0x00; PORTB.1=1; break;}
case 9:{PORTD=~0x10; PORTB.1=1; break;}
};
}
while (flagbutton1==1)
{ switch(secH)
{
case 0:{PORTD=~0x40; PORTB.1=1; break;}
case 1:{PORTD=~0x71; PORTB.1=0; break;}
case 2:{PORTD=~0xA0; PORTB.1=1; break;}
case 3:{PORTD=~0x30; PORTB.1=1; break;}
case 4:{PORTD=~0x11; PORTB.1=0; break;}
case 5:{PORTD=~0x12; PORTB.1=1; break;}
case 6:{PORTD=~0x02; PORTB.1=1; break;}
case 7:{PORTD=~0x70; PORTB.1=0; break;}
case 8:{PORTD=~0x00; PORTB.1=1; break;}
case 9:{PORTD=~0x10; PORTB.1=1; break;}
};
}

PORTD=0x0C; PORTC=0x00; PORTB.0=0; PORTB.1=0;
#asm("sleep");
}
}

Спасибо всем за советы, многое для себя почерпнул.

P.S. Не хотел бы, чтобы моё сообщение послужило прерыванием дискуссии между Палыч и Tarbal "О создании ненужных сущностей"

в конце немного укоротил программу, т.к. для проверки работоспособности проще выводить ход секунд, чтобы не ждать, и убрал один индикатор, но суть осталась та же
Go to the top of the page
 
+Quote Post
Палыч
сообщение Oct 18 2013, 20:03
Сообщение #22


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(Tarbal @ Oct 18 2013, 22:04) *
...есть два различных понятия, которые называются одинаково.

Это Вы - погорячились. Приоритет - он, как говорится "и в Африке - приоритет". А, вот - реализация механизма прерываний в разных контроллерах/процессорах, действительно - разная... И хотя при описании работы этих разных механизмов используется термин "приоритет", однако его значение (а, термин "приоритет" означает: "старшинство", "важность", "первенство") не меняется.

Цитата(Tarbal @ Oct 18 2013, 22:04) *
Не нашли хорошего решения.
Это - не значит, что его не существует.
Так уж сложилось, что в проектируемых мной устройствах кнопок, обычно, - "воз и маленькая тележка". Из-за необходимости экономить дефицитные ноги МК, они (кнопки) собираются в матрицу. Наилучшее решение в этом случае - применить поллинг для определения изменения их состояния. В тех немногочисленных устройствах, где кнопок немного и есть возможность "посадить" каждую из них на "свою" ногу МК поллинг используется уже "по-привычке", как хорошо отработанный приём работы с кнопками... Однако, было и устройство, где необходимо было довольно точно определять момент нажатия на кнопку (точнее - это был концевик движения суппорта). Кнопка (концевик) была "посажена" на линию прерывания, ну, а устранение дребезга описал выше Abell:
Цитата
в обработчике прерывания сразу же запрещать INT0, генерить задержку по свободному таймеру и разрешать
Единственное, что можно было бы добавить к этому описанию антидребезга: после запрета прерывания INT0 - сбросить флаг INTF0, который мог быть взведен внешним сигналом за интервал времени, прошедший между автоматической очисткой этого флага при входе в прерывание и моментом времени запрета прерывания.
Go to the top of the page
 
+Quote Post
Tarbal
сообщение Oct 18 2013, 20:52
Сообщение #23


Профессионал
*****

Группа: Свой
Сообщений: 1 351
Регистрация: 21-05-10
Пользователь №: 57 439



Цитата(shatov @ Oct 18 2013, 23:10) *
P.S. Не хотел бы, чтобы моё сообщение послужило прерыванием дискуссии между Палыч и Tarbal "О создании ненужных сущностей"


sm.gif Я дискуссию закончил.
Go to the top of the page
 
+Quote Post
Abell
сообщение Oct 19 2013, 05:37
Сообщение #24


профессиональный дилетант
****

Группа: Участник
Сообщений: 866
Регистрация: 16-03-06
Из: Шебекино - Лысьва - Тюмень
Пользователь №: 15 292



Цитата(shatov @ Oct 18 2013, 23:10) *
Решил переделать программно, поставив вторую кнопку на INT1. Всё заработало.

interrupt [EXT_INT0] void ext_int0_isr(void)
{
flagbutton0=1;
flagbutton1=0;
if (PIND.2==0&&PIND.3==0) {resetFunc();}
}

interrupt [EXT_INT1] void ext_int1_isr(void)
{
flagbutton1=1;
flagbutton0=0;
if (PIND.2==0&&PIND.3==0) {resetFunc();}
}

interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{
secL++;
if (secL>9) {secH++; secL=0; flagbutton0=0; flagbutton1=0;}
if (secH>5) {secH=0;}
if (sec>59) {min++; sec=0;}
if (min>59) {hour++; min=0;}
if (hour>23) {dayL++; hour=0;}
if (dayL>9) {dayH++; dayL=0;}
if (dayH>9) {dayH=0;}
}

Вот это правильно sm.gif только зачем две переменных завели, когда достаточно одной?

interrupt [EXT_INT0] void ext_int0_isr(void)
{
flagbutton=1;
if (PIND.2==0&&PIND.3==0) {resetFunc();}
}

interrupt [EXT_INT1] void ext_int1_isr(void)
{
flagbutton=2;
if (PIND.2==0&&PIND.3==0) {resetFunc();}
}

а в обработчике по таймеру после вывода индикации сбрасываете в 0, и все laughing.gif


--------------------
Скоро дело сказывается, да не скоро сказка делается, или тише будешь - дальше уедешь...

Go to the top of the page
 
+Quote Post
Палыч
сообщение Oct 19 2013, 06:53
Сообщение #25


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(Abell @ Oct 19 2013, 09:37) *
Вот это правильно

Гм-м-м.... Правильно? Ужасно! Лучше бы уж тогда ТС внял советам Tarbal и использовал бы прерывание для выхода из Idle, а состояние кнопки определял поллингом... ТС не привел текст программы к удобоваримому виду, лазить по DS и переводить константы - лень, то - "наглазок":
1. Вторая кнопка введена в устройство только лишь для того, чтобы исправить пробелы в программировании ТС. Функциональной необходимости в ней нет.
2. Кнопка, подключенная на int0, не выведет МК из спячки, поскольку прерывание настроено на перепад сигнала из высокого уровня в низкий.
3. Прерывания на int1, настроены на низкий уровень сигнала, поэтому при нажатии и удержании в нажатом состоянии подключенной к int1 кнопки будут формироваться множественные прерывания по int1. Фактически при выходе из прерывания МК снова войдет в процедуру прерывания по int1.
4. Вызов resetFunc() переведёт МК в состояние близкое к состоянию "по включению питания", при этом обнулятся переменные, ради подсчета которых и затевалась разработка устройства. Это - такая задумка: сбросить показания счетчика при нажатии двух кнопок? Тогда, возможно, смысл во второй кнопке есть...
5. Перевод устройства в "исходное" состояние (когда оба флага равны нулю) производится таймером при переходе единиц секунд через ноль (т.е. когда secL>9). Поскольку нажатие на кнопку производится в случайный момент времени, то время до перехода в "исходное" будет варьироваться от 9 до 1 сек.
6. Переход в спящий режим осуществляется в конце каждого цикла main loop. Поэтому индикация будет осуществляться исключительно потому, что непрерывно происходят прерывания по int1, которые из спящего режима МК выводят (см. п.3)
7. ...пожалуй, приведённого выше - достаточно...
Go to the top of the page
 
+Quote Post
ae_
сообщение Oct 19 2013, 07:01
Сообщение #26


Участник
***

Группа: Свой
Сообщений: 462
Регистрация: 2-04-07
Из: Иркутск
Пользователь №: 26 695



Цитата(shatov @ Oct 19 2013, 04:10) *
...
char sec=0;
...
char secH=0, secL=0;
...
secL++;
if (secL>9) {secH++; secL=0; flagbutton0=0; flagbutton1=0;}
if (secH>5) {secH=0;}
if (sec>59) {min++; sec=0;}
...

У Вас объявлены sec,secL,secH, но sec нигде далее в программе не изменяется, значит и проверка "if (sec>59) {min++; sec=0;}" никогда не выполнится.
secL,secH - будут крутиться, а минуты, часы и дни - не будут.
Go to the top of the page
 
+Quote Post
smk
сообщение Oct 19 2013, 07:25
Сообщение #27


Гуру
******

Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446



Вот такую строчку допишите: #include <avr/interrupt.h>
А Вы наверно в кодевижине... тогда не надо.


--------------------
Живи днем так, чтобы ночью ты спал спокойно.
Go to the top of the page
 
+Quote Post
Abell
сообщение Oct 19 2013, 08:40
Сообщение #28


профессиональный дилетант
****

Группа: Участник
Сообщений: 866
Регистрация: 16-03-06
Из: Шебекино - Лысьва - Тюмень
Пользователь №: 15 292



Цитата(Палыч @ Oct 19 2013, 10:53) *
Гм-м-м.... Правильно? Ужасно! Лучше бы уж тогда ТС внял советам Tarbal и использовал бы прерывание для выхода из Idle, а состояние кнопки определял поллингом...
1. Вторая кнопка введена в устройство только лишь для того, чтобы исправить пробелы в программировании ТС. Функциональной необходимости в ней нет.
2. Кнопка, подключенная на int0, не выведет МК из спячки, поскольку прерывание настроено на перепад сигнала из высокого уровня в низкий.
3. Прерывания на int1, настроены на низкий уровень сигнала, поэтому при нажатии и удержании в нажатом состоянии подключенной к int1 кнопки будут формироваться множественные прерывания по int1. Фактически при выходе из прерывания МК снова войдет в процедуру прерывания по int1.
4. Вызов resetFunc() переведёт МК в состояние близкое к состоянию "по включению питания", при этом обнулятся переменные, ради подсчета которых и затевалась разработка устройства. Это - такая задумка: сбросить показания счетчика при нажатии двух кнопок? Тогда, возможно, смысл во второй кнопке есть...
5. Перевод устройства в "исходное" состояние (когда оба флага равны нулю) производится таймером при переходе единиц секунд через ноль (т.е. когда secL>9). Поскольку нажатие на кнопку производится в случайный момент времени, то время до перехода в "исходное" будет варьироваться от 9 до 1 сек.
6. Переход в спящий режим осуществляется в конце каждого цикла main loop. Поэтому индикация будет осуществляться исключительно потому, что непрерывно происходят прерывания по int1, которые из спящего режима МК выводят (см. п.3)
7. ...пожалуй, приведённого выше - достаточно...

ТС скорее всего только начинает свой трудный путь в освоении микроконтроллеров sm.gif Поэтому, как мне кажется, применить две кнопки - правильное направление, это и имел в виду. Если есть свободные порты - почему бы не использовать? Тем более, применением поллинга полностью гарантировать отсутствие дребезга не удастся, ведь в какой-то момент опроса там может быть и 0 sm.gif В конечном итоге автор сам придет к правильным выводам.
Применить два флага, когда достаточно одного - вот это неправильно, но опять-таки, это проблемы автора.
Насчет корявости кода - полностью согласен, это беда всех начинающих, постепенно с опытом проходит. Если он будет нарабатываться, этот опыт. Ну мы же не будем писать для автора темы программу, за бесплатно, верно? sm.gif
Пока же, как мне кажется, автор слабо представляет себе, как должно работать устройство и как объяснить это микроконтроллеру на понятном ему языке, ну это пройдет.
Вообще, последнее время все чаще приходится сталкиваться с самодельными разработками, клиенты воют - просят переделать, такого насмотришься, что и этот мелкий проект вполне достойно смотрится laughing.gif Еще один прикол сам не видел, но рассказывали, что кое-кто для AVR на бейсике пишет, вот это был шок, да...


--------------------
Скоро дело сказывается, да не скоро сказка делается, или тише будешь - дальше уедешь...

Go to the top of the page
 
+Quote Post
Палыч
сообщение Oct 19 2013, 09:09
Сообщение #29


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(Abell @ Oct 19 2013, 12:40) *
применением поллинга полностью гарантировать отсутствие дребезга не удастся, ведь в какой-то момент опроса там может быть и 0
При программном антидребезге что при использовании прерываний, что при использовании поллинга метод отсечения дребезга одинаков - после фиксации изменения состояния на линии ввода на некоторое время прекратить анализ состояния. При использовании прерываний этот анализ выполняет аппаратура, при поллинге - программа.


Цитата(Abell @ Oct 19 2013, 12:40) *
ТС скорее всего только начинает свой трудный путь в освоении микроконтроллеров
Ага, очень похоже на лаб работу по дисциплине "Микропроцессорная техника" biggrin.gif
Go to the top of the page
 
+Quote Post
Tarbal
сообщение Oct 20 2013, 15:57
Сообщение #30


Профессионал
*****

Группа: Свой
Сообщений: 1 351
Регистрация: 21-05-10
Пользователь №: 57 439



Я многие годы делаю так:

1. Настраиваю таймер вызывать обработчик прерывания раз в 10 мС
2. при входе делаю только rt_cnt++;
3. вечный цикл:

santi_seconds = 100;
while(1)
{
while(rt_cnt==0)
{}
rt_cnt--;
//Here do each 10 ms action

if(--santi_seconds==0)
{
//Here do each second action
santi_seconds = 100;
if(++seconds==60)
{
seconds = 0;
if(++minutes==60)
{
minutes = 0;
//Here do each hour action

}
//Here do each minute action
}

}

}

Возможны опечатки. Сходу написал.

Сообщение отредактировал Tarbal - Oct 20 2013, 16:51
Go to the top of the page
 
+Quote Post

3 страниц V  < 1 2 3 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 01:20
Рейтинг@Mail.ru


Страница сгенерированна за 0.01506 секунд с 7
ELECTRONIX ©2004-2016