|
|
  |
Таймер на Atmega8, Работает при симуляции, но не работает в железе |
|
|
|
Oct 18 2013, 11:28
|
Профессионал
    
Группа: Свой
Сообщений: 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
|
|
|
|
|
Oct 18 2013, 12:45
|

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

|
Цитата(Tarbal @ Oct 18 2013, 15:28)  Это почему это? От прерывания можно просыпаться, но использовать его для обработки нажатия дребезжащей кнопки очень нехорошо. Чтобы не "создавать ненужные сущности". Я понимаю, что кому то нравиться поллинг, кому то прерывания... Но, коль в данном случае мы вынуждены пользоваться прерыванием, то накладывать на него ещё и поллинг - это и есть "ненужные сущности". Методы борьбы с дребезгом кнопки, подключенной к линии генерации прерывания int0 - банальны: аккуратно запретить прерывание от int0 на время несколько бОльшее, чем время дребезга. to TC Прошу прощения, выше я Вам дал "вредный" совет - использовать прерывание по спаду для фиксации факта нажатия на кнопку. Дело в том, что выход из "Idle mode" возможен только по уровню, но никак не по перепаду...
|
|
|
|
|
Oct 18 2013, 14:03
|
Профессионал
    
Группа: Свой
Сообщений: 1 351
Регистрация: 21-05-10
Пользователь №: 57 439

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

Гуру
     
Группа: Свой
Сообщений: 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, что не отражено в документации производителя, то - расскажите. Эта информация, вероятно, будет полезна многим. Наверное, уместнее будет это сделать в специально созданной для этого теме.
|
|
|
|
|
Oct 18 2013, 18:04
|
Профессионал
    
Группа: Свой
Сообщений: 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
|
|
|
|
|
Oct 18 2013, 19:10
|
Группа: Новичок
Сообщений: 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 "О создании ненужных сущностей"
в конце немного укоротил программу, т.к. для проверки работоспособности проще выводить ход секунд, чтобы не ждать, и убрал один индикатор, но суть осталась та же
|
|
|
|
|
Oct 18 2013, 20:03
|

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

|
Цитата(Tarbal @ Oct 18 2013, 22:04)  ...есть два различных понятия, которые называются одинаково. Это Вы - погорячились. Приоритет - он, как говорится "и в Африке - приоритет". А, вот - реализация механизма прерываний в разных контроллерах/процессорах, действительно - разная... И хотя при описании работы этих разных механизмов используется термин "приоритет", однако его значение (а, термин "приоритет" означает: "старшинство", "важность", "первенство") не меняется. Цитата(Tarbal @ Oct 18 2013, 22:04)  Не нашли хорошего решения. Это - не значит, что его не существует. Так уж сложилось, что в проектируемых мной устройствах кнопок, обычно, - "воз и маленькая тележка". Из-за необходимости экономить дефицитные ноги МК, они (кнопки) собираются в матрицу. Наилучшее решение в этом случае - применить поллинг для определения изменения их состояния. В тех немногочисленных устройствах, где кнопок немного и есть возможность "посадить" каждую из них на "свою" ногу МК поллинг используется уже "по-привычке", как хорошо отработанный приём работы с кнопками... Однако, было и устройство, где необходимо было довольно точно определять момент нажатия на кнопку (точнее - это был концевик движения суппорта). Кнопка (концевик) была "посажена" на линию прерывания, ну, а устранение дребезга описал выше Abell: Цитата в обработчике прерывания сразу же запрещать INT0, генерить задержку по свободному таймеру и разрешать Единственное, что можно было бы добавить к этому описанию антидребезга: после запрета прерывания INT0 - сбросить флаг INTF0, который мог быть взведен внешним сигналом за интервал времени, прошедший между автоматической очисткой этого флага при входе в прерывание и моментом времени запрета прерывания.
|
|
|
|
|
Oct 19 2013, 05:37
|

профессиональный дилетант
   
Группа: Участник
Сообщений: 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;} } Вот это правильно  только зачем две переменных завели, когда достаточно одной? 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, и все
--------------------
Скоро дело сказывается, да не скоро сказка делается, или тише будешь - дальше уедешь...  
|
|
|
|
|
Oct 19 2013, 06:53
|

Гуру
     
Группа: Свой
Сообщений: 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. ...пожалуй, приведённого выше - достаточно...
|
|
|
|
|
Oct 19 2013, 07:01
|
Участник
  
Группа: Свой
Сообщений: 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 - будут крутиться, а минуты, часы и дни - не будут.
|
|
|
|
|
Oct 19 2013, 08:40
|

профессиональный дилетант
   
Группа: Участник
Сообщений: 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. ...пожалуй, приведённого выше - достаточно... ТС скорее всего только начинает свой трудный путь в освоении микроконтроллеров  Поэтому, как мне кажется, применить две кнопки - правильное направление, это и имел в виду. Если есть свободные порты - почему бы не использовать? Тем более, применением поллинга полностью гарантировать отсутствие дребезга не удастся, ведь в какой-то момент опроса там может быть и 0  В конечном итоге автор сам придет к правильным выводам. Применить два флага, когда достаточно одного - вот это неправильно, но опять-таки, это проблемы автора. Насчет корявости кода - полностью согласен, это беда всех начинающих, постепенно с опытом проходит. Если он будет нарабатываться, этот опыт. Ну мы же не будем писать для автора темы программу, за бесплатно, верно?  Пока же, как мне кажется, автор слабо представляет себе, как должно работать устройство и как объяснить это микроконтроллеру на понятном ему языке, ну это пройдет. Вообще, последнее время все чаще приходится сталкиваться с самодельными разработками, клиенты воют - просят переделать, такого насмотришься, что и этот мелкий проект вполне достойно смотрится  Еще один прикол сам не видел, но рассказывали, что кое-кто для AVR на бейсике пишет, вот это был шок, да...
--------------------
Скоро дело сказывается, да не скоро сказка делается, или тише будешь - дальше уедешь...  
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|