Strona 1 z 1

problem z zerowaniem bitów podczas select case

: 17 wrz 2024, 19:52
autor: elektrofil
Witam, mam problem z w miarę prostym programem. za pomocą wejścia int 0 mam wędrujące 0 na portach d4...d7
mój problem polega na ustawianiu wszystkich wyjść w stan 0 podczas zmiany kroku.
wklejam link do filmu, nie jest zbyt dobrze to ujęte lecz jak się przyjrzeć to widać zapalanie się wszystkich ledów, czyli stanu 0 na portach.
  1. $regfile = "m328pdef.dat"'Zdefiniuj odpowiedni mikrokontroler (np. ATmega328P)
  2. $crystal = 16000000    ' Ustaw częstotliwość zegara (np. 16 MHz)
  3. $hwstack = 64
  4. $swstack = 64
  5. $framesize = 64
  6. $baud =115200
  7.  
  8. $projecttime = 155
  9.  
  10. ' Definicje pinów
  11. config  Portd.2=input       ' Pin D2 czujnika światła
  12. sensorState alias pind.2
  13. ' Ustawienie pinów jako wejścia i wyjścia
  14.  
  15. config  portd.4=output   ' porty sterujące tranzystorami
  16. config  portd.5=output
  17. config  portd.6=output
  18. config  portd.7=output
  19.  
  20. set portd.2                    ' włączenie podciągania int0
  21. set portd.4                  ' Wstępne wyłączenie transoptorów
  22. set portd.5
  23. set portd.6
  24. set portd.7
  25.  
  26. Declare Sub UpdateMotorStep
  27. Dim currentStep As Byte
  28. Dim stateChanged As Bit
  29.  
  30. ' Konfiguracja przerwania
  31. Config Int0 = change    ' Przerwanie na zmianę stanu (można dopasować)
  32. on int0 interrupt
  33. enable int0
  34. enable interrupts
  35.  
  36.  
  37.  
  38.     ' Inicjalizacja zmiennych
  39.     sensorState = 0
  40.     stateChanged = 0
  41.     currentStep = 1
  42.  
  43.     ' Komunikacja szeregowa
  44.     Baud = 115200
  45. '    Waitms 1 ' Czekaj, aby upewnić się, że port szeregowy jest gotowy
  46.     Print "Program started. Waiting for sensor changes..."
  47.  
  48. ' Główna pętla
  49. Do
  50.     If stateChanged = 1 Then
  51.         Call UpdateMotorStep
  52.         stateChanged = 0
  53.  
  54.     endif
  55. Loop
  56.  
  57. ' Funkcja aktualizująca krok silnika
  58. sub UpdateMotorStep:
  59.   '(  ' Wyłącz wszystkie tranzystory
  60.  '     set portd.3
  61.       set portd.4
  62.       set portd.5
  63.       set portd.6
  64.       waitms 500
  65.     ' Włącz następny tranzystor
  66.     ')
  67.     select case currentStep
  68.   case 1
  69.   print "case1"
  70.     reset portd.4
  71.     set portd.5
  72.     set portd.6
  73.     set portd.7
  74.  
  75.   case 2
  76.   print "case2"
  77.    set portd.4
  78.    reset portd.5
  79.    set portd.7
  80.    set portd.6
  81.  
  82.   case 3
  83.   print "case3"
  84.       set portd.5
  85.       set portd.4
  86.       reset portd.6
  87.       set portd.7
  88.  
  89.   case 4
  90.   print "case4"
  91.     set portd.4
  92.     set portd.5
  93.     set portd.6
  94.     reset portd.7
  95.  
  96.   case else
  97.   print "else"
  98.       set portd.3
  99.       set portd.4
  100.       set portd.5
  101.       set portd.6
  102.  
  103.     end select
  104.  
  105.     ' Wyświetl informacje
  106.     '(
  107.     toggle portb.5
  108.     If sensorState = 2 Then
  109.         Print "Sensor: HIGH"
  110.     Else
  111.         Print "Sensor: LOW"
  112.     End If
  113.     Print "Active transistors: "; currentstep
  114.     'reset portb.5
  115. ')
  116.     ' Przejdź do następnego kroku
  117.     currentStep = currentStep+1
  118.     if currentstep>4 then
  119.      currentstep=1
  120.     endif
  121.  
  122. end sub
  123.  
  124.  
  125. ' Obsługa przerwania
  126. Interrupt:
  127.     sensorState = pind.2
  128.  
  129.  '
  130.   reset portb.5
  131.   '  sensorState = Pin(sensorPin) ' Odczytaj stan pinu czujnika
  132.     stateChanged = 1
  133.     waitms 10
  134.     nop
  135.  
  136.     set portb.5
  137.  '   Gifr = &B01000000                                     'Ustawianie flagi INTF0 w rejestrze GIFR
  138. return
  139.  

Re: problem z zerowaniem bitów podczas select case

: 17 wrz 2024, 20:08
autor: niveasoft
Piszesz D3-D6 a ja w kodzie widzę D4-D7.
Proponowałbym to zrobić tak jak przy multipleksowaniu.
Najpierw wyłączasz te cztery piny za jednym zamachem przy wejściu w Sub ale nie dotykasz stanu reszty. To się robi instrukcją OR.
Potem tylko w poszczególnych Case robisz reset a Bascom sam zrobi AND.
  1. PORTD = PORTD Or &B1111_0000 'ustaw bity 4-7
  2. Select Case
  3.  Case : Reset PORTD.4
  4.  Case : Reset PORTD.5
  5.  Case : Reset PORTD.6
  6.  Case : Reset PORTD.7
  7. End Select
Chyba że chcesz żeby nie było przerwy w wysterowaniu to musisz przygotować sobie zmienną i ja za jednym zamachem załadować do portu.
  1. Dim Ustaw As Byte
  2. Ustaw = PORTD Or &B1111_0000 'ustaw bity 4-7
  3. Select Case
  4.  Case : Reset Ustaw.4
  5.  Case : Reset Ustaw.5
  6.  Case : Reset Ustaw.6
  7.  Case : Reset Ustaw.7
  8. End Select
  9. PORTD = Ustaw
Pewnie można by to jeszcze jakoś zoptymalizować ;)
Radzę też zadeklarować stateChanged jako Byte bo to żadna oszczędność a nawet wiecej roboty dla Bascoma bo musi załadować zmienną do rejestru, zrobić OR w przerwaniu i z rejestru do zmiennej a normalnie by zrobił STS 1 do załadowanej zmiennej, a żeby sprawdzić te zmienną w programie musi ją załadować, zrobic AND i dopiero porównać a tak robi porównanie z 1 i jest szybciej. W dodatku nie powinno się używać Bitów które są w programie w przerwaniu.

Re: problem z zerowaniem bitów podczas select case

: 18 wrz 2024, 9:48
autor: elektrofil
Dziękuję bardzo, pomogło.