Администрация форума не несёт ответственности за достоверность информации и оставляет за собой право редактировать или в особых случаях даже удалять посты без предупреждения. Спасибо за понимание.

Программирование ATMEL в BASCOM.

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Программирование ATMEL в BASCOM. » Вопросы - ответы » attiny13 управление одной кнопкой с таймером


attiny13 управление одной кнопкой с таймером

Сообщений 31 страница 57 из 57

31

Дабы не плодить темы спрошу здесь, т.к. по логике ближе... ;)

С ШИМами все нормально, а вот прерывание - не видит ни в какую...

Вроде, все, как всегда, стандартный подход к обработке...
Или что-то не так ?

Код:
$Regfile="m8adef.dat"
$Crystal=8000000
$hwstack=16
$swstack=16
$framesize=32
$baud = 19200

'$lib "mcsbyte.lbx"
'$lib "mcsbyteint.lib"

Config Timer1 = Pwm, Pwm = 8, Compare A Pwm = Clear Up, Compare B Pwm = Clear Up, Prescale = 8
Config Timer2 = Pwm, Compare Pwm = Clear Up, Prescale = 8
' PWM1A - Красный
' PWM1B - Зеленый
' PWM2   - Синий

Config Adc = Single, Prescaler = Auto, Reference = AVCC
Start Adc

Config Int0 = Rising
'Config Int0 = Low Level
On Int0 knopka Nosave
Enable Int0
'Gicr.6 = 1

Config PIND.2 = Input
Config PORTB.1 = Output
Config PORTB.2 = Output
Config PORTB.3 = Output

'CONFIG RND =  16

Dim a As Byte
Dim flag As Byte
Dim nomer As Byte
Dim knop As Bit
Dim rr As Word                            ' Данные АЦП регулятора красный
Dim rg As Word                           ' Данные АЦП регулятора зеленый
Dim rb As Word                           ' Данные АЦП регулятора синий
Dim rwm As Word                        ' Пересчет АЦП для ШИМ

'===================================================================
nachalo:
Do

If flag = 0 Then
'   Print "No press"
   rr = Getadc(0)
   rwm = rr\4
   Pwm1a = rwm                              ' красный
   rg = Getadc(1)
   rwm = rg\4
   Pwm1b = rwm                              ' зеленый
   rb = Getadc(2)
   rwm = rb\4
   Pwm2 = rwm                               ' синий
End If

If flag = 1 Then
   Pwm1a = 255                              ' красный
   Pwm1b = 255                              ' зеленый
   Pwm2 = 255                                ' синий
   flag = 0
   Wait 1
End If

Loop

End

'===================================================================
knopka:                                      ' Обработка прерывания INT0
'    push r24
    flag = 1
'    pop r24
'nop
Return

0

32

Точно какой флаг выставлять не помню ща на работе., но на сколько я помню, когда срабатывает прерывание, его нужно обязательно (прям там) сбрасывать гифром (иначе повторно не будет срабатывать).

0

33

Nord
Не нашёл в коде глобальное включение прерываний:Enable Interrupts

0

34

RDW написал(а):

Точно какой флаг выставлять не помню ща на работе., но на сколько я помню, когда срабатывает прерывание, его нужно обязательно (прям там) сбрасывать гифром (иначе повторно не будет срабатывать).

Да сбрасываю его...
Когда обработчик отправит в нужное место, там и сбрасываю.
И вполне достаточно было обнулить переменную флага...

Enable Interrupts не требуется, там есть Enable Int0

В данном случае - не ловится... ;)

Отредактировано Nord (2017-12-18 16:40:32)

0

35

Биг сорри, забыл схемку приложить...
http://s7.uploads.ru/t/A2kgL.jpg

Отредактировано Nord (2017-12-18 16:39:11)

0

36

Nord написал(а):

Когда обработчик отправит в нужное место, там и сбрасываю.
И вполне достаточно было обнулить переменную флага...


В исходнике не видно..

0

37

Nord написал(а):

Enable Interrupts не требуется, там есть Enable Int0

Включение конкретного прерывания не разрешит прерывания глобально.

+1

38

Nord написал(а):

Enable Interrupts не требуется, там есть Enable Int0

увы, требуется  :flirt:

+1

39

RDW написал(а):

когда срабатывает прерывание, его нужно обязательно (прям там) сбрасывать гифром (иначе повторно не будет срабатывать).

А поподробнее можно про гифр?
Это только с INTx как я понимаю или со всеми интами так нужно поступать???

0

40

-NMi- написал(а):

А поподробнее можно про гифр?Это только с INTx как я понимаю или со всеми интами так нужно поступать???

Вот здесь Прерывания INT0, INT1, PCINTx Atmega8_88_328 достаточно хорошо разложено.
Спасибо Александру за тот раздел - почти второй хелп... ;)

0

41

Yuriy.pv написал(а):

В исходнике не видно..

И куда оно делось ? ;)
Ищем flag = 0...

Отредактировано Nord (2017-12-19 08:05:47)

0

42

Глобальное включение прерываний спасло ситуацию, заработало...

Только вот непонятно...
В указанной теме:

Код:
'-------------------     Локально разрешаем прерывания     ---------------------
'-------------------------------------------------------------------------------
  Enable Int0       ' Разрешаем прерывание INT0
   'Или так
  Gicr.6 = 1       ' Разрешаем прерывание INT0
'-------------------------------------------------------------------------------
  Enable Int1       ' Разрешаем прерывание INT1
   'Или так
  Gicr.7 = 1       ' Разрешаем прерывание INT1
'-------------------------------------------------------------------------------
'-------------------     Глобально разрешаем прерывания     ---------------------
'-------------------------------------------------------------------------------
  Enable Interrupts
     'Или так
       SEI

Так и делалось мной всегда.
Включал локально и работало по всей программе...
А теперь вдруг Bascom'у глобальности захотелось... ;)

Всем спасибо за помощь !

Отредактировано Nord (2017-12-19 08:10:52)

0

43

Я же сказал "гифР" (gifr), а не "гицр"! Открой уже датащит, найди его и почитай, что и зачем там сбрасывать.  :mad: Тебе люди советую, что надо делать, а ты всё споришь на пустом месте. Зачем тогда спрашивать?

зы: т.к. из-за своего поведения, ТЫ отверг все версии (типа здесь никто ничего не понимает и у тебя УНИКАЛЬНАЯ ситуация, что глючит якобы баском корявый (с намеком на это), я не не стал смотреть в своём коде (детально), как правильно это нужно делать. Сам виноват, разбирайся и так всё разжевали.

Отредактировано RDW (2017-12-19 11:15:44)

0

44

Nord написал(а):

Вот здесь Прерывания INT0, INT1, PCINTx Atmega8_88_328 достаточно хорошо разложено.
Спасибо Александру за тот раздел - почти второй хелп... ;)


Чёт нифурычит ссылка.

0

45

-NMi- написал(а):

Чёт нифурычит ссылка.

Ну пройдите напрямую по названиям каталогов:
» Программирование ATMEL в BASCOM. » Примеры применения в среде Баском » Прерывания INT0, INT1, PCINTx Atmega8_88_328

0

46

-NMi- написал(а):

Чёт нифурычит ссылка.

В ссылке указано <bascomavr.ru>
Если переходить с <bascomavr.3bb.ru>, то будет ругаться...

0

47

Чёт почитал там всю ветку, посмотрел обработчики прерываний и ни в одном обработчике в "гифр" ниче никто не пишет. Может это на каких-то старых или новых процах так???
От себя: тыркал тиню85, 328р, м32юсб, м128, м2560  в хвост и в гриву со всеми аппаратными приблудами (кроме компаратора) и нигде ничё не сбрасывал.
Читал, конечно, особенно в старых статьях про 1323 или как-то около... но, я такого проца и не держал пинцетом.
Так шо мож не всем процам ентот -гифр- нужен???

0

48

-NMi- написал(а):

Так шо мож не всем процам ентот -гифр- нужен???

Регистр МК.
В разных можно встретить по-разному: GIFR или IEFR.
Отдельными битами указывает на появление прерывания.

В указанной теме про именно него действительно нет, но лично меня заинтересовало и я таки полистал даташит, еще до отсылания меня туда...

0

49

Да,но,в нативном даташите черным по белому написано (для 328р) шо флаг из регистра прерываний сбрасывается на аппаратном уровне и сбрасывать там ничо ненадо... вроде как.

0

50

-NMi- написал(а):

посмотрел обработчики прерываний и ни в одном обработчике в "гифр" ниче никто не пишет.

Про GIFR вот тут немножко написано:

GIFR

interrupt-debounce-self.bas

$regfile = "2313def.dat"
$crystal = 4000000

Config Pind.6 = Output
Config Pind.2 = Input
Config Int0 = Falling
Config Debounce = 50

Dim Wtime As Byte
Const Debouncetime = 75

On Int0 Stopbutton

Cls

Wtime = 255

Enable Interrupts
Enable Int0

Do
  Set Portd.6
  Waitms Wtime
  Reset Portd.6
  Waitms Wtime
Loop

Stopbutton:
  Lcd "stop!"
  Waitms Debouncetime
  Gifr = 64
Return

End

В эту продпрограмму всего лишь добавлен оператор задержки waitms. Поскольку на время обработки прерывания отключаются, программа среагирует только на первый импульс. Выберите значение константы Debouncetime так, чтобы оно было больше наибольшего времени дребезга используемых кнопок. Также в BASCOM есть команда Debounce, которую тоже можно использовать в прерываниях.

Что за GIFR?

В вышеприведенном примере, в подрограмме прерывания есть странная строка Gifr=64. Что это за Gifr за такой? Уберите эту строчку и посмотрите, что получится: практически в любом случае "stop!" будет выведено на ЖКИ два раза. Как же такое возможно?
А посмотрите вот этот пример: interrupt-deb-pre.bas

$regfile = "2313def.dat"
$crystal = 4000000

Config Pind.6 = Output
Config Pind.2 = Input
Config Int0 = Falling

Dim Wtime As Byte

On Int0 Stopbutton

Cls
Set Portd.6
Waitms 3000
Reset Portd.6
Wtime = 255

Enable Interrupts
Enable Int0

Do
  Set Portd.6
  Waitms Wtime
  Reset Portd.6
  Waitms Wtime
Loop

Stopbutton:
  Lcd "stop!"
  Waitms 75
Return

End

После очистки ЖКИ включается светодиод. Затем следует трехсекундная задержка, после чего гаснет светодиод и включаются прерывания. Теперь сбросьте МК и попробуйте нажать кнопку, пока включен светодиод. У вас есть три секунды, так что думаю, у вас не возникнет проблем (а иначе - вам делать нечего тут! прим. WildCat'a). После погасания светодиода включается Int0, и вы заметите, что программа переходит к подпрограмме Stopbutton. Поэтому, даже если вы нажмете кнопку перед включением прерываний, данные о срабатывании где-то сохранятся, и после включения прерывание немедленно выполнится.

Вот что происходит в AT90S2313 (да и в других МК AVR). Даже если соответствующее прерывание НЕ включено, данные о его срабатывании хранятся в "General Interrupt Flag Register" (GIFR или Главный Регистр Флагов Прерываний). Это один из тех редчайших случаев, когда даже пользователям BASCOM придется вникнуть во внутреннее строение AVR (я вас не заставляю!) Регистр GIFR имеет восемь бит, из которых шестой и седьмой зарезервированы для Int0 и Int1 соответственно:

И вот что происходит в нашей программе interrupt-debounce-self.bas: В подпрограмме обработки, когда прерывания выключены, данные о срабатывании все равно приходят из-за дребезга контактов. Прерывания отмечаются в GIFR нулевым битом. Для Int0 это шестой бит, для Int1 - седьмой. Все, что нужно сделать для устранения нашей проблемы - это установить соответствующие биты в GIFR перед командой Return в подпрограмме обработки. Тогда дальнейшие (бесполезные) прерывания после продолжения работы обрабатываться не будут.

Это отсюда:
http://decada.org.ru/project/lessons/bascom_avr/10/

Отредактировано Adagumer (2017-12-23 21:42:39)

0

51

Эт кто кОдил-та, школьнеГ шоль? Хде энто видано,шо вайты в обработчике прерываний торчали...!!!
Вы, это, того, долго программируете,то? А? "фраза из К/Ф Москва слезам не верит"

0

52

-NMi- написал(а):

Вы, это, того, долго программируете,то? А? "фраза из К/Ф Москва слезам не верит"

Там ссылка, откуда код... ;)
Чего зря на человека наезжать ? ;)

+1

53

Никто ничо никак.
Усё нормуль.

0

54

И так, рассказываю последний раз, для тех, кто не умеет/понимает как правильно работать с прерываниями (общее).

При срабатывании прерывания (так или иначе) происходит переход по вектору на выполнение подпрограммы, а основной поток/код, который выполнялся - прерывается и его адрес заносится в стэк. При выходе из прерывания (подпрограммы), значения счетчика обратно загружаются из стэка и продолжается выполнение основного потока/кода программы.

Из выше сказанного следует, что существует основных два правила работы с прерыванием:

1. подпрограмма прерывания должна успевать выполняться ДО прихода следующего прерывания;
2. на время выполнения подпрограммы прерывания, мы запрещаем его.

Когда это работа с таймером или другими регламентированными временными рамками, то можно предсказать/рассчитать время отпускаемое на прерывание и следовательно можно подсчитать время выполнения подпрограммы прерывания (успеет выполнится или нет).
В нашем случае идет обработка "кнопки" (прерывание по ножке МК), нам неизвестно время прихода/нажатия кнопки и ещё хуже, у нас есть место дребезга (непредсказуемое, многократное срабатывание). Да можно дополнительно повесить на вход триггер шмитта (для устранения дребезга), но мы то хотим как можно проще и дешевле сделать (тогда придется подумать нормально о алгоритме работы).
В итоге, мы должны при срабатывании прерывания его отключить, а потом восстановить.
Так же нужно учитывать, что у Атмег/Тини флаги прерывания сами не восстанавливаются во всех случаях, а именно на INT (при выходе). Придет одно срабатывание и всё - затык.
В коде это выглядит просто:

Код:
$regfile = "attiny85.dat"
...
Config Int0 = Low Level                                     ' Типы: Change/Falling/Rising/Low Level
On Int0 Btn_on
Enable Int0
Enable Interrupts
...
...
Btn_on:
   Disable Int0

   ... здесь что-то делаем ...

   ' INT0 = 64 INT1 = 128 регистр событий прерываний, выставляются даже если запрещены прерывания (Gifr.intf0 = 1 - Clear Int0 flag)
   Gifr = 64
   Enable Int0
Return

В конце прерывания обратно разрешаем его срабатывание гифром.

Т.к. у нас из-за гифра и так происходит затык с прерыванием, то запрещать его необязательно (Disable/Enable), но об общем правиле надо всё равно помнить, чтобы где на грабли не наступить. В общем без датащита на МК/процессоры никуда, т.к. регистры меняются и архитектура - это всё надо учитывать.
Алгоритмы обработок кнопок могут быть разные (все не опишешь), но основных решений - это: обработку делать в самом прерывании или в общем потоке программы, а прерывание просто автоматом только разрешать очередное прерывание INT:

Код:
Btn_on:
   Gifr = 64 ' для INT0
Return

+3

55

Ничо опять не понял...
Замути на 328р в протеусе проект, возьми один таймер и соедини с ногой INTх его. Посмотрим, шо будет и как с гифром.

0

56

-NMi-, читайте внимательно, для Вас выделяю главный тезис сего опуса.

RDW написал(а):

В общем без датащита на МК/процессоры никуда, т.к. регистры меняются и архитектура - это всё надо учитывать.

В 328-й меге нет гифра, там есть еифр. Но это не всё! там и биты в другом порядке, т.е сбросить флаг прерывания бит будет равен 3 или 1. Если правильно помню. Так что

RDW написал(а):

В общем без датащита на МК/процессоры никуда, т.к. регистры меняются и архитектура - это всё надо учитывать.

Это дглавное!

0

57

Покш-гениально!
Имеем:
On_int0_interrupt:
push r0
ldi r0,1
sts {нужно_чёто_сотвАрить},r0
pop r0
reti

И Ано чЁто работает)))

0


Вы здесь » Программирование ATMEL в BASCOM. » Вопросы - ответы » attiny13 управление одной кнопкой с таймером