Страница 1 из 1
кнопка и прерывания
Добавлено: Вт окт 21, 2014 19:56:20
sirha
подскажите пожалуста не пойму как опрашивать кнопку через прерывания
Код: Выделить всё
#include <mega8.h>
#include <delay.h>
void main(void)
{
PORTD=0x02;
DDRD=0x01;
label0:
while(PIND.1==1)
{
PORTD.0=0;
}
while (1)
{
PORTD.0=1;
delay_ms(10);
while(PIND.1==0)
{goto label0;}
}}
суть в том чтобы при нажатии на кнопку загорелся светодиод,при повторном нажатии он должен потухнуть,токо этот код плохо работает когда в цикле много всего,подскажите как его можно реализовать подругому - разными способами,на первом месте хотелось бы рассмотреть прерывания- исключая внешнее прерывания
Re: кнопка и прерывания
Добавлено: Вт окт 21, 2014 20:02:01
shads
Не темни... объясни сразу что за причина, по которой нужно использовать именно внешнее прерывание...
Просто - опрос кнопок правильнее делать в регулярном прерывании по таймеру\счетчику, а не по внешнему прерыванию...
Если только нужно будить устройство из сна, то это другое дело...
Re: кнопка и прерывания
Добавлено: Вт окт 21, 2014 20:04:48
sirha
shads писал(а):Не темни... объясни сразу что за причина, по которой нужно использовать именно прерывание...
просто хочу рассмотреть все способы кроме внешних прерываний
shads писал(а):Просто - опрос кнопок правильнее делать в регулярном прерывании по таймеру\счетчику
приведи пример кодом если несложно
Re: кнопка и прерывания
Добавлено: Вт окт 21, 2014 20:08:44
shads
Re: кнопка и прерывания
Добавлено: Вт окт 21, 2014 20:12:45
sirha
напиши тут пожалуйста,некоторые ветки не для codivision,хотелось бы на этом компиляторе
Re: кнопка и прерывания
Добавлено: Вт окт 21, 2014 20:21:56
shads
sirha писал(а):
напиши тут пожалуйста,некоторые ветки не для codivision,хотелось бы на этом компиляторе
Блин... я им не пользуюсь, и у меня все для AVRSTUDIO...
Ну ща попробую установить CV и поправить свою либу...
Re: кнопка и прерывания
Добавлено: Вт окт 21, 2014 20:56:15
sirha
shads писал(а):
Ну ща попробую установить CV и поправить свою либу...
буду ждать,спасибо

Re: кнопка и прерывания
Добавлено: Вт окт 21, 2014 22:02:46
shads

еле разобрался в ентом CV... срочно переходите на нормальный компилятор - AVRSTUDIO4+GCC

.....
В общем там примерчик управления 8-мю светиками с помощью 4-х кнопок... короткие нажатия - управляют младшими 4-мя светиками, длинные нажатия - управляют старшими 4-мя светиками...
Ито я не понял как там библиотеку создавать, все свалил в главный файл... так что - наверное сами разберетесь, как по отдельным файлам распихать...
Re: кнопка и прерывания
Добавлено: Ср окт 22, 2014 00:08:20
sirha
shads писал(а):
В общем там примерчик управления 8-мю светиками с помощью 4-х кнопок... короткие нажатия - управляют младшими 4-мя светиками, длинные нажатия - управляют старшими 4-мя светиками...
громоздко(,буду разбираться,а еше как -нибудь можно пороще
Re: кнопка и прерывания
Добавлено: Ср окт 22, 2014 00:19:17
shads
Ну ща сделаю для одной кнопки, чтобы проще было...
Re: кнопка и прерывания
Добавлено: Ср окт 22, 2014 00:25:27
sirha
shads писал(а):Ну ща сделаю для одной кнопки...
ПАСИБ я сам не специалист еще в программировании поэтому разобраться сразу не смогу,знаю не мало,в прерываниях слаб еще
Re: кнопка и прерывания
Добавлено: Ср окт 22, 2014 00:34:45
shads
Вот для одной кнопки...
Сложность кажущаяся только в прерывании... но это нужно для более менее грамотной обработки нажатий... Тут по другому никак...
Re: кнопка и прерывания
Добавлено: Ср окт 22, 2014 00:45:40
sirha
shads писал(а):Вот для одной кнопки...
Сложность кажущаяся только в прерывании....
буду разбираться
Re: кнопка и прерывания
Добавлено: Ср окт 22, 2014 01:59:23
shads
Еще чуть упростил обработку одной кнопки...
Теперь все выглядит как то так....
Спойлер
Код: Выделить всё
//анализ состояния кнопки
//если на линии - лог 1, то кнопка не нажата, когда кнопка нажата, то соотв на линии - лог 0.
//вот тут мы и вылавливаем лог 0 на линии, т.е. ждем когда результат сравнения будет противоположный значению TRUE (отрицание !)
if (! (BTN_PIN & BTN_LINE)){
//итак кнопка нажата, и мы инкрементируем счетчик защелки LockCoun, для отсеивания дребезга
//почему (BTN_LOCK_TIME/10), да потому что частота прерываний 100 Гц (т.е. 100 прерываний в секунду)
//а задаем мы время защелки в милисекундах (т.е. 1000 отсчетов в секунду)
//вот вам и разница в 10 раз... поэтому константу задержки и делим на 10...
if (LockCoun < (BTN_LOCK_TIME/10)){
LockCoun++;
//пока защелка не дощитала до значения (BTN_LOCK_TIME/10) - просто выскакиваем
return;
}
//ага... счетчик защелки дотикал, значит можно предварительно отметить, что факт фиксации нажатия свершился
BtnLockBit =1;
//дальше нужно посчитать время удержания кнопки, для того чтобы определить короткое это нажатие или длинное...
if (LongCoun >= (BTN_LONG_TIME/10))
//сюда попадем, если счетчик длительности нажатия уже равен константе длинного нажатия
//а это означает что он еще раньше дотикал до этого состояния,
//и следовательно, все что нужно в связи с этим уже было сделано, соответственно - просто выходим...
return;
//раз мы сюда проскочили, то время удержания пока что меньше чем нужно для фиксации длинного нажатия
//поэтому продолжаем инкремент переменной времени удержания
if (++LongCoun >= (BTN_LONG_TIME/10))
//ух ты... счетчик только что досчитал до значения времени длинного нажатия...
//это и есть момент фиксации длинного нажатия, устанавливаем бит длинного нажатия
BtnFlags |= BTN_LONG;
//ну и дальше мы уже будем выскакивать на идущей раньше строчке if (++LongCoun >= (BTN_LONG_TIME/10))
//до тех пор пока кнопка не отпустится...
}
else{
//клавиша отжата
//если кнопка до этого удерживалась, то нужно опять обработкть счетчик защелки, только в обратном направлении
if (LockCoun){
//начинаем декремент счетчика защелки, чтобы определить - это точно отжатие, или это просто звон некачественной кнопки
LockCoun --;
//защелка еще не обнулилась - возврат
return;
}
//ага... клавиша точно отпущена, смотрим, была ли она до этого определена как нажатая
// (! BtnLockBit) то же самое что (BtnLockBit == 0)
if (! BtnLockBit)
//увы... кнопка до этого не была нажата, поэтому выходим
//это место я назвал "СТАТИЧЕСКИЙ ВОЗВРАТ", т.к. программа именно тут выскакивает в режиме бездействия кнопок
return;
//так, это интересно... раз мы тут, то кнопка была ранее нажата...
if (LongCoun < (BTN_LONG_TIME/10))
//установка бита короткого нажатия
//ЕСЛИ значение счетчика времени удержания меньше чем время необходимое для длинного удержания,
//то значит это было короткое нажатие, соответстенно надо установить флаг короткого нажатия
//т.е. как вы поняли, установка флага короткого нажатия, происходит в момент отпускания кнопки, при условии
//что кнопка удерживалась меньше времени необходимого для фиксации длинного удержания
//ЕСЛИ же значение счетчика было равно времени длинного удержания, то мы обойдем эту строку,
//т.к. в таком случае, флаг длинного удержания кнопки, был уже установлен ранее строкой BtnFlags |= BTN_LONG;
BtnFlags |= BTN_SHRT;
//ну и хвосты подчистить надобно...
//отжатие зафиксировано
BtnLockBit =0;
//сброс счетчика длительности нажатия
LongCoun = 0;
}
Re: кнопка и прерывания
Добавлено: Ср окт 22, 2014 16:37:46
sirha
Тут как я понил работает прерывание по совпадению
тоесть когда OCR2=TCNT2 то сработает прерывание
я правильно считаю 100 гц?
OCR2=0x4E;
4e=78 это ведь такты
у Т2 8 бит наскоко я знаю, 255 тактов
вы задаете делитель 1024 на частоте 8 мгц
получаем 1024/8000000 =0,128 мс
100 гц = 10 мс
10мс/0,128 мс = 78 тактов за 10 мс
TCNT2=255-78=177 - НАЧАЛЬНОЕ ЗНАЧЕНИЕ ДЛЯ СЧЕТА
обьясните мне как считает счетчик ведь у вас TCNT2 нигде не написан - тоесть он равен 0????
и как токо досчитает до равенства OCR2 то сработает прерывания ведь так??
Re: кнопка и прерывания
Добавлено: Ср окт 22, 2014 19:36:42
shads
Режим CTC - это когда счетчик считает от нуля до значения в регистре OCR2...
При совпадении происходит сброс счетчика на 0 и происходит прерывание (если включено).
Счетчик при этом устанавливать не нужно... вообще все автоматом происходит...
Считаеш частоту прерываний вроде правильно, но я проще считал...
Исходная частота 8000000, делим на 1024 (делитель) получаем частоту приращения счетчика 8000000/1024=7812 Гц.
Т.е. у нас счетчик инкрементируется с частотой 7812 Гц... ну и раз нам нужно 100Гц, то соответственно получаем регистр сравнения: 7812/100=78... Что и наблюдаем в регистре сравнения... Частота точная не нужна, это не часы в конце концов, так что примерно имеем 100Гц...
ЗЫ
Кстати... если нужна точная привязка к реальному времени, то можно сделать так:
Предделитель установить на 256, регистр OCR2 = (250-1)... получаем прерывание с частотой ровно 125 Гц...
Остается сделать в прерывании программный делитель на 125, и вот вам 1 Гц с часовой точностью..... (если конечно от кварца работаем)
Re: кнопка и прерывания
Добавлено: Ср окт 22, 2014 20:27:56
sirha
shads писал(а):Режим CTC - это когда счетчик считает от нуля до значения в регистре OCR2...
При совпадении происходит сброс счетчика на 0 и происходит прерывание (если включено).
Счетчик при этом устанавливать не нужно... вообще все автоматом происходит...
а я невнимательно посмотрел на назначения битов wgm21 и 20
думал что режим с точной фазой и это в тупик меня привело,теперь дошло
