Przycisk rozróżniający długie i krótkie wciśnięcie

Proste przykłady do częstych pytań.
ODPOWIEDZ
Awatar użytkownika
niveasoft
Posty: 1207
Rejestracja: 17 sie 2015, 12:13
Kontakt:

Przycisk rozróżniający długie i krótkie wciśnięcie

Post autor: niveasoft » 18 mar 2017, 23:29

Kod chyba komentuje się sam. Może w osobnym wątku napiszę o konfiguracji Timerów.
  1. ' KOD PRZY KRÓTKIM NACIŚNIĘCIU ZMIENIA STAN LED_1, A PRZY DŁUGIM LED_2.
  2.  
  3. $regfile = "m16def.dat"
  4. $crystal = 8000000
  5. $hwstack = 64
  6. $swstack = 16
  7. $framesize = 128
  8.  
  9. Config Submode = New
  10.  
  11. Config Lcdpin = Pin , Db4 = Portc.5 , Db5 = Portc.4 , Db6 = Portc.3 , Db7 = Portc.2 , E = Portc.6 , Rs = Portc.7
  12. Config Lcd = 16x2
  13. Cursor Off , Noblink
  14. Cls
  15.  
  16. Config Porta.6 = Output : Led_1 Alias Porta.6
  17. Config Porta.7 = Output : Led_2 Alias Porta.7
  18.  
  19. Config Porta.0 = Input : Set Porta.0 : Switch Alias Pina.0
  20.  
  21. Dim Sw_cnt As Byte , Lock As Byte
  22.  
  23. Config Timer2 = Timer , Prescale = 1024 , Compare = Disconnect , Clear_timer = 1
  24.  COMPARE2 = 77                          '10ms @8MHz/1024
  25.  
  26. Lcd "Test..."
  27.  
  28.  
  29.  
  30. Do
  31.  
  32.  If TIFR.OCF2 = 1 Then                  'minęło 10ms, flagę ustawia Timer
  33.   TIFR.OCF2 = 1                         'flagi kasuje się wpisując jeden, nie zero
  34.  
  35.  
  36.    If Switch = 0 Then                   'jeśli wciśnięto przycisk
  37.     If Lock = 0 Then                    'a jeszcze nie ma blokady
  38.      If Sw_cnt < 50 Then                'tu jesteśmy co 10ms i jeśli jeszcze nie osiągneliśmy granicy
  39.       Incr Sw_cnt                       'to dodajemy do licznika Sw_cnt
  40.      Else                               'jeśli granica osiągnięta
  41.       Lock = 1                          'zablokuj dodawanie aż do puszczenia przycisku
  42.        Toggle Led_2                     '->zmień stan drugiej diody
  43.      End If
  44.     End If
  45.    Else                                 'kiedy zwalniamy przycisk
  46.     If Lock = 0 Then                    'a nie było to długie wciśnięcie
  47.      If Sw_cnt > 3 Then Toggle Led_1    'sprawdź czy to nie drganie styków 3x10ms = 30ms
  48.     End If                              '->zmień stan pierwszej diody
  49.      Lock = 0 : Sw_cnt = 0              'wyłącz blokadę i zeruj licznik
  50.    End If
  51.  
  52.  
  53.  End If
  54.  
  55. Loop
  56. End
marekszy
Posty: 99
Rejestracja: 20 lis 2016, 20:21

Re: Przycisk rozróżniający długie i krótkie wciśnięcie

Post autor: marekszy » 21 lis 2023, 12:19

Witam
Przyciski długi / krótki działają fajnie , ale jak dopisać aby jedno długie naciśnięcie załączyło led a drugi raz wyłączyło led.
W tej chwili toogle to załatwia (zmiana stanu na przeciwny), a potrzebuje aby wykonać jeszcze inne procedury.
Dałem else ale wyrzuca mi błąd
Awatar użytkownika
niveasoft
Posty: 1207
Rejestracja: 17 sie 2015, 12:13
Kontakt:

Re: Przycisk rozróżniający długie i krótkie wciśnięcie

Post autor: niveasoft » 21 lis 2023, 13:17

  1. If Flaga = 0 Then Flaga = 1 Else Flaga = 0  'ON/OFF
  2.  LED = Flaga
To najprostszy zapis który się rozwija do tego..
  1. If Flaga = 0 Then
  2.   Flaga = 1
  3.    'tu można Set LED, ale można lepiej
  4. Else
  5.   Flaga = 0
  6.   'tu można Reset LED, ale można lepiej
  7. End If
  8.   LED = Flaga   'tak jest oszczędniej
I w tym rozwiniętym pewnie mozesz sobie więcej rzeczy robić.

Czyli ten kod z pierwszego postu przerabiasz tak że musisz dodac End If
  1. If Sw_cnt > 3 Then Toggle Led_1
Zamieniasz na
  1. If Sw_cnt > 3 Then
  2.  
  3.  If Flaga = 0 Then
  4.    Flaga = 1
  5.    'tu można Set LED, ale można lepiej
  6.  Else
  7.    Flaga = 0
  8.   'tu można Reset LED, ale można lepiej
  9.  End If
  10.   LED = Flaga   'tak jest oszczędniej
  11.  
  12. End If  ' <<< dodane
marekszy
Posty: 99
Rejestracja: 20 lis 2016, 20:21

Re: Przycisk rozróżniający długie i krótkie wciśnięcie

Post autor: marekszy » 22 lis 2023, 10:23

Dzięki
działa tak jak chciałem, w sumie będą jeszcze 2 takie przyciski sw_ motor i sw_zegar ale to już raczej nie będzie problemu ,
pozmieniałem czasy dla przycisków bo wcisnąłem to do przerwania 4ms
zerknij czy to tak w miarę zgodnie ze sztuką ;)
  1. '*****************************petla glowna************************************
  2. Do
  3.   If Flaga_4ms = 1 Then                                     'co 4ms
  4.      Flaga_4ms = 0
  5.  
  6.      if poz_menu_temp = 0 then Wysw = T
  7.      if poz_menu_temp = 1 then wysw = Tu
  8.  
  9.        if flaga_temp = 1 then
  10.           poz_menu_temp = 1
  11.           set led_temp
  12.        end if
  13.        If flaga_temp = 0 then
  14.           poz_menu_temp = 0
  15.           reset led_temp
  16.        end if
  17.  
  18.      If sw_temp = 0 Then
  19.       If Lock = 0 Then
  20.        If Sw_cnt < 200 Then
  21.           Incr Sw_cnt
  22.          Else
  23.           Lock = 1
  24.        If flaga_temp = 0 then
  25.           Flaga_temp = 1
  26.          else
  27.           Flaga_temp = 0
  28.        end if
  29.  
  30.      End If
  31.     End If
  32.    Else
  33.     If Lock = 0 Then
  34.      If Sw_cnt > 10 Then
  35.      Toggle Led_zegar
  36.     End If                       ' to tylko do testu krotkiego wcisniecia
  37.     end if
  38.      Lock = 0 : Sw_cnt = 0
  39.    End If
  40.  
  41.  
  42.      gosub wyswietlanie
  43.   end If
  44.  
  45.   If Flaga_100ms = 1 Then
  46.      Flaga_100ms = 0
  47.   end if
  48.  
  49.   If Flaga_1s = 1 Then
  50.      Flaga_1s = 0
  51.      gosub temperatura
  52.   end If
  53.  
  54.  Loop
  55. End
  56.  
  57.  
  58.  
  59. '***************petla glowna koniec*****************
marekszy
Posty: 99
Rejestracja: 20 lis 2016, 20:21

Re: Przycisk rozróżniający długie i krótkie wciśnięcie

Post autor: marekszy » 23 lis 2023, 11:09

Jednak jest problem z dołożeniem kolejnych 2 przycisków sw_motor i sw_zegar o tych samych funkcjach co sw_temp , masz może jakiś pomysł ?
Awatar użytkownika
niveasoft
Posty: 1207
Rejestracja: 17 sie 2015, 12:13
Kontakt:

Re: Przycisk rozróżniający długie i krótkie wciśnięcie

Post autor: niveasoft » 23 lis 2023, 13:44

Nie wiem co tam może byc za problem, ale napisz jakie dokładnie piny. Są na tym samym porcie?
marekszy
Posty: 99
Rejestracja: 20 lis 2016, 20:21

Re: Przycisk rozróżniający długie i krótkie wciśnięcie

Post autor: marekszy » 23 lis 2023, 21:52

PIND.0 , PIND.1 , PIND.2
Awatar użytkownika
niveasoft
Posty: 1207
Rejestracja: 17 sie 2015, 12:13
Kontakt:

Re: Przycisk rozróżniający długie i krótkie wciśnięcie

Post autor: niveasoft » 24 lis 2023, 4:29

Proste jak swiński ogon. Sprawdza się cały port maskując nieużywane piny.
W ten sposób można sobie nawet sprawdzać wciśnięcie dwóch lub trzech przycisków na raz.
Zamiast sw_temp, sw_zegar i sw_motor dodajesz dwie zmienne typu byte Switches i Sw_mem.
Switches służy do odczytu całego portu a Sw_mem pamięta co było wciśniete jak już zwolnisz przycisk czyli przy krótkim naciśnięciu.
Te trzy przyciski rozróżniasz potem w Select Case.
Nie namawiam, ale ja to u siebie trzymam w osobnym SUB Przyciski bo jak kod ma potem kilkanaście tysiecy linii kodu to łatwiej jest sie poruszać po subach. Może w Mega8 sie takie zwykłe liniowe rozwiązanie jeszcze obroni...
  1. Dim Switches As Byte , Sw_mem As Byte
  2. Const Sw_mask = &B0000_0111                                 'PIND.0-PIND.2
  3.  
  4.    Switches = Pind And Sw_mask                              'sprawdz trzy przyciski na raz
  5.  
  6.    If Switches <> Sw_mask Then                              'jesli ktorykolwiek wcisniety
  7.     Sw_mem = Switches                                       'zapamietaj dla opcji zwolnienia przycisku
  8.     If Lock = 0 Then
  9.      If Sw_cnt < 200 Then
  10.       Incr Sw_cnt
  11.      Else
  12.       Lock = 1
  13.        Select Case Sw_mem
  14.         Case &B0000_0110                                    'PIND.0
  15.           'sw_temp
  16.         Case &B0000_0101                                    'PIND,1
  17.           'sw_zegar
  18.         Case &B0000_0011                                    'PIND.2
  19.           'sw_motor
  20.        End Select
  21.  
  22.      End If
  23.     End If
  24.    Else
  25.     If Lock = 0 Then
  26.      If Sw_cnt > 10 Then
  27.  
  28.        Select Case Sw_mem
  29.         Case &B0000_0110                                    'PIND.0
  30.          Toggle Led_zegar
  31.           'sw_temp
  32.         Case &B0000_0101                                    'PIND,1
  33.          Toggle Led_zegar
  34.           'sw_zegar
  35.         Case &B0000_0011                                    'PIND.2
  36.          Toggle Led_zegar
  37.           'sw_motor
  38.        End Select
  39.  
  40.      End If
  41.     End If
  42.      Lock = 0 : Sw_cnt = 0
  43.    End If
marekszy
Posty: 99
Rejestracja: 20 lis 2016, 20:21

Re: Przycisk rozróżniający długie i krótkie wciśnięcie

Post autor: marekszy » 24 lis 2023, 12:02

działa z trzema przyciskami ale powiedz jak teraz wystawić flagi - Flaga_temp dla sw_temp /Flaga_zegar dla sw_zegar / Flaga_motor dla sw_motor
tak ,żeby można pozbyć się toggle tak jak to miałem wcześniej
  1.        if flaga_temp = 1 then
  2.           poz_menu_temp = 1
  3.           set led_temp
  4.        end if
  5.        If flaga_temp = 0 then
  6.           poz_menu_temp = 0
  7.           reset led_temp
  8.        end if
  9.  
  10.      If sw_temp = 0 Then
  11.       If Lock = 0 Then
  12.        If Sw_cnt < 200 Then
  13.           Incr Sw_cnt
  14.          Else
  15.           Lock = 1
  16.        If flaga_temp = 0 then
  17.           Flaga_temp = 1
  18.          else
  19.           Flaga_temp = 0
  20.        end if
  21.  
  22.      End If
  23.     End If
  24.    Else
  25.     If Lock = 0 Then
  26.      If Sw_cnt > 10 Then
  27.      Toggle Led_zegar
  28.     End If                       ' to tylko do testu krotkiego wcisniecia
  29.     end if
  30.      Lock = 0 : Sw_cnt = 0
  31.    End If
marekszy
Posty: 99
Rejestracja: 20 lis 2016, 20:21

Re: Przycisk rozróżniający długie i krótkie wciśnięcie

Post autor: marekszy » 24 lis 2023, 17:29

tak to zrobiłem i działa , może nie jest to pięknie ale..., potrzebuję jeszcze dodać blokowanie przycisków aby po wybraniu jednego kolejny zadziałał dopiero po wyjściu z pierwszego
  1. Do
  2.   If Flaga_4ms = 1 Then                                     'co 4ms
  3.      Flaga_4ms = 0
  4.  
  5.      if poz_menu_temp = 0 then Wysw = T
  6.      if poz_menu_temp = 1 then wysw = Tu
  7.      if poz_menu_motor = 1 then wysw = motor
  8.      if poz_menu_zegar = 1 then wysw = zegar
  9.  
  10.  
  11. Const Sw_mask = &B00011100                                  'PIND.0-PIND.2
  12.  
  13.    Switches = Pind And Sw_mask                              'sprawdz cztery przyciski na raz
  14.  
  15.    If Switches <> Sw_mask Then                              'jesli ktorykolwiek wcisniety
  16.     Sw_mem = Switches                                       'zapamietaj dla opcji zwolnienia przycisku
  17.     If Lock = 0 Then
  18.      If Sw_cnt < 200 Then
  19.       Incr Sw_cnt
  20.      Else
  21.       Lock = 1
  22.        Select Case Sw_mem
  23.         Case &B00010100                                    'PIND.3 sw_temp
  24.         If flaga_temp = 0 then
  25.           Flaga_temp = 1
  26.           Flaga_zegar =0
  27.           Flaga_motor = 0
  28.          else
  29.           Flaga_temp = 0
  30.           Flaga_zegar =0
  31.           Flaga_motor = 0
  32.         end if
  33.  
  34.        if flaga_temp = 1 then
  35.           poz_menu_temp = 1
  36.           'wysw = tu
  37.           migaj_t = 1
  38.        end if
  39.        If flaga_temp = 0 then
  40.           poz_menu_temp = 0
  41.           migaj_t = 0
  42.        end if
  43.  
  44.  
  45.         Case &B00011000                                    'PIND,2 sw_zegar
  46.  
  47.         If flaga_zegar = 0 then
  48.           Flaga_zegar = 1
  49.           Flaga_motor =0
  50.           Flaga_temp = 0
  51.          else
  52.           Flaga_temp = 0
  53.           Flaga_zegar =0
  54.           Flaga_motor = 0
  55.         end if
  56.  
  57.        if flaga_zegar = 1 then
  58.           poz_menu_zegar = 1
  59.           'wysw = zegar
  60.           migaj_z = 1
  61.        end if
  62.        If flaga_zegar = 0 then
  63.           poz_menu_zegar = 0
  64.           poz_menu_temp = 0
  65.           migaj_z = 0
  66.        end if
  67.  
  68.  
  69.         Case &B00001100                                    'PIND.4 sw_motor
  70.  
  71.         If flaga_motor = 0 then
  72.           Flaga_motor = 1
  73.           Flaga_zegar =0
  74.           Flaga_temp = 0
  75.          else
  76.           Flaga_temp = 0
  77.           Flaga_zegar =0
  78.           Flaga_motor = 0
  79.         end if
  80.  
  81.        if flaga_motor = 1 then
  82.           poz_menu_motor = 1
  83.           migaj_m = 1
  84.        end if
  85.        If flaga_motor = 0 then
  86.           poz_menu_motor = 0
  87.           poz_menu_temp = 0
  88.           migaj_m = 0
  89.        end if
  90.  
  91.        End Select
  92.  
  93.      End If
  94.     End If
  95.    Else
  96.     If Lock = 0 Then
  97.      If Sw_cnt > 10 Then
  98.  
  99.        Select Case Sw_mem
  100.         Case &B00010100                                    'PIND.3 sw_temp
  101.          Toggle Led_temp
  102.         Case &B00011000                                    'PIND,2 sw_zegar
  103.          Toggle Led_zegar
  104.           'sw_zegar
  105.         Case &B00001100                                    'PIND.4 sw_motor
  106.          Toggle Led_motor
  107.           'sw_motor
  108.        End Select
  109.  
  110.      End If
  111.     End If
  112.      Lock = 0 : Sw_cnt = 0
  113.    End If
  114.  
  115.  
  116.      Gosub Miganie_t
  117.      Gosub Miganie_m
  118.      Gosub Miganie_z
  119.      gosub wyswietlanie
  120.   end If
ODPOWIEDZ