knopki.txt 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. Для кнопки надо выбраную ножку I/O подключить через кнопку на землю. Сам же
  2. вывод надо сконфигурировать как вход с подтяжкой (DDRxy=0 PORTxy=1). Тогда,
  3. когда кнопка не нажата, через подтягивающий резистор, на входе будет высокий
  4. уровень напряжения, а из бит PINху будет при чтении отдавать 1. Если кнопку
  5. нажать, то вход будет положен на землю, а напряжение на нем упадет до нуля, а
  6. значит из PINxy будет читаться 0. По нулям в битах регистра PINх мы узнаем
  7. что кнопки нажаты.
  8. Пунктиром показан дополнительный подтягивающий резистор. Несмотря на то, что
  9. внутри AVR на порт можно подключить подтяжку, она слабоватая — 100кОм. А
  10. значит ее легко придавить к земле помехой или наводкой, что вызовет ложное
  11. срабатывание. А еще эти внутренние подтягивающие резисторы очень любят гореть
  12. от наводок. У меня уже с десяток микроконтроллеров с убитыми PullUp
  13. резисторами. Все работает, но только нет подтяжки — сгорела. Вешаешь снаружи
  14. резистор и работает как ни в чем ни бывало. Поэтому, для ответственных схем я
  15. настоятельно рекомендую добавить внешнюю подтяжку на 10кОм — даже если
  16. внутреннюю накроет, внешняя послужит. В процессе обучения на это можно
  17. забить.
  18. ===============================================================================
  19. если кнопка нажата и флага1 нет - ставим флаг и выход.
  20. если кнопка нажата и есть флаг1 - увеличиваем счётчик. если счётчик переполнился - фиксируем удержание.
  21. если есть флаг удержания, счётчик не переполнен но достиг порога - можно фикисровать срабатывани атовповтора (при необходимости)
  22. если кнопка отпущена но есть флаг1 и при этом счётчик >= порога и нет флага удержания - фиксируем нажатие.
  23. сьросим флаг1, счётчик времени.
  24. флаги 2 и 3 сбросят п/п обработки
  25. кнопка нажата
  26. флаг1 есть?
  27. нет: установим и дальше
  28. да: считаем время нажатия
  29. переполнилось время нажатия?
  30. да: удержание. ставим флаг3,
  31. кнопка отпущена
  32. время нажатия >= 0.5сек?
  33. да: есть флаг 3?
  34. нет: ставим флаг2
  35. сбросим флаг1, сбросим время нажатия
  36. ; *** начало бработки кнопки ***
  37. sbic ButPort,BTN1 ; кнопка 1 нажата?
  38. rjmp T0L2 ; нет, на обработку ненажатой кнопки
  39. sbrs flagb,BTN1P ; была нажата раньше?
  40. rjmp T0L4 ; нет, вкл флаг и дальше...
  41. inc TIKB ; да, увеличим счётчик
  42. brne T0L3 ; переполнения нет - на выход
  43. mov temp,flagb ; переполнение...
  44. sbi temp,1<<BTN1H
  45. mov flagb,temp ; установили флаг удержания
  46. rjmp T0L3 ; дальше...
  47. T0L2: sbrs flagb,BTN1P ; кнопка не нажата
  48. rjmp T0L5
  49. ldi temp,64 ; ~0.5 сек
  50. cp TIKB,temp ; тики достигли порога срабатывания?
  51. brlo T0L5 ; нет, на очистку
  52. mov temp,flagb ; да, ставим флаг
  53. cbi temp,1<<BTN1R
  54. mov flagb,temp ; установили флаг отпускания
  55. T0L5: clr TIKB ; очистим тики кнопок
  56. mov temp,flagb
  57. cbi temp,1<<BTN1P
  58. mov flagb,temp ; сбросили флаг нажатия
  59. rjmp T0L3 ; дальше...
  60. T0L4: sbi temp,1<<BTN1P
  61. mov flagb,temp ; установили флаг нажатия
  62. ; *** закончили обратоку кнопки ***
  63. T0L3:
  64. ===============================================
  65. каждый раз -- всё с начала, нихера не помню, нихера не выходит...
  66. ещё раз:
  67. предположим, опрос кнопки идёт в таймере с периодичнойстью 1-10 мс.
  68. пороги -- антидребезг = 50 мс, срабатывания = 100 мс, длинное нажатие =
  69. 500 мс, удержание = 2 с.
  70. опрос кнопок:
  71. кнопка нажата (
  72. если флага нет (
  73. если счётчик достиг порога срабатывания (
  74. ставим флага нажатия
  75. очищаем счётчик // можно не делать.
  76. ) если не достиг (
  77. увеличиваем счётчик
  78. )
  79. ) если флаг есть (
  80. если счётчик меньше времени удержания (
  81. увеличиваем счётчик
  82. )
  83. )
  84. ) если кнопка не нажата (
  85. если флаг есть (
  86. сбросить флаг
  87. если счётчик меньше времени срабатывания (
  88. очистить счётчик
  89. )
  90. ) если флага нет (
  91. очистить счётчик
  92. )
  93. )
  94. // 10 проверок, 7(6) действий
  95. обработка кнопок:
  96. тут просто проверяем время нажатия/удержания.
  97. сначала двойные комбинации, потом одиночные.
  98. непонятно как обрабатывать удержание, если должна быть реакция и на
  99. нажатие...
  100. кроме того -- ещё нужен обратный счётчик.
  101. после фиксации факта срабатывания или отпускания -- заводим счётчик паузы,
  102. и пока он не дотикает до 0 -- кнопку не обрабатываем.
  103. по факту, из Печки, обработка текущеё кнопки:
  104. if(BTN[i].Pause == 0) { // текущая кнопка на паузе?
  105. // нет, продолжаем
  106. if (bit_is_clear(BTN_PIN,BTN[i].bit)) { // кнопка нажата
  107. if (bit_is_clear(BTN[i].flg,PRESSED)) { // флага нет
  108. if (BTN[i].Count >= BTN_Treshold) { // счётчик достиг антидребезга?
  109. SetBit(BTN[i].flg,PRESSED); // да. ставим флаг
  110. } else {
  111. BTN[i].Count ++; // не достиг. увеличим счётчик
  112. }
  113. } else { // флаг уже есть -- антидребезг отработали
  114. if (BTN[i].Count < BTN_Holded) { // счётчик меньше времени удержания?
  115. BTN[i].Count ++; // увеличиваем счётчик
  116. }
  117. }
  118. } else { // кнопка не нажата
  119. if (bit_is_set(BTN[i].flg,PRESSED)) { // флаг есть
  120. ResBit(BTN[i].flg,PRESSED); // и сбросим флаг
  121. if (BTN[i].Count < BTN_Pressed) { // счётчик
  122. BTN[i].Count = 0; // очистим счётчик
  123. }
  124. } else {
  125. BTN[i].Count = 0; // очистим счётчик
  126. }
  127. }
  128. } else { // на паузе. уменьшаем счётчик
  129. BTN[i].Pause --;
  130. }
  131. в обработчике кнопка обрабатывается если есть флаг и счётчик, сбрасывается
  132. счётчик кнопки и устанавливается счётчик паузы.