Problem z zapisem do eeprom więcej niż 2 zmiennych

Pytania, kody i porady dotyczące nie tylko Bascom.
Awatar użytkownika
Michał6201
Posty: 165
Rejestracja: 03 paź 2015, 20:07

Problem z zapisem do eeprom więcej niż 2 zmiennych

Post autor: Michał6201 » 12 mar 2017, 19:13

Witam Wszystkich

Mam pewien problem z częściowo nie działającym programem do zegarka w moim samochodzie.

Opiszę w skrócie jak działa mój układ.
Sercem układu jest Atmega16 taktowana zewnętrznym kwarcem 11.0592MHz, po szynie I2C podpięty jest zegarek PCF8583 oraz pamięć eeprom 24C02.
Do UART podłączony jest moduł bluetooth BTM222 służący do komunikacji urządzenia ze smartfonem.
Urządzenie wyświetla na LCD 2x16 znaków datę i godzinę, po naciśnięciu przycisku program przeskakuje na drugi ekran, gdzie wyświetla się temperatura in/out, po kolejnym naciśnięciu przycisku pojawia się kolejny ekran, na którym wyświetlane jest napięcie instalacji samochodowej. Ponowne naciśnięcie przycisku powoduje powrót do ekranu głównego z godziną i datą.
Aplikację na smartfona napisałem w AppInventor i działa poprawnie. Ustawienie godziny i daty działa, zapisanie stanu led do pamięci eeprom również działa.
Wymyśliłem sobie, że dodatkowo w celach edukacyjnych spróbuję zapisywać do pamięci eeprom - datę przeglądu technicznego ( w programie zmienne C wysyła datę do smartfona, a zmienna Q zapisuje datę w eeprom) i również to działa.

Postanowiłem pójść krok dalej i spróbować zapisać kolejne zmienne w eeprom - datę wymiany oleju silnikowego (w programie zmienne A oraz B), a także datę końca ubezpieczenia OC (zmienne I oraz K).
Daty wprowadzam w aplikacji na smartfonie, wysyłam je do układu, odczyt danych również odbywa się w aplikacji na smartfonie. Niestety próby zapisu zmiennych wymiany oleju silnikowego i OC nie działają.

Format daty, którą wysyłam z aplikacji do procka, to np.: 12-03-2017

W sumie leci: Q12-03-2017 i na końcu 10 oraz 13

Jeśli chcę, odczytać tą datę, to wysyłam do procka zmienną C i 1.

Do procka leci: C1 i na końcu 10 oraz 13

Kolejne zmienne zapisuję w analogiczny sposób, ale one już nie działają.

W załączeniu przesyłam kod z głównego pliku:
  1.  
  2. $regfile = "m16adef.dat"                                    ' Typ procesora
  3.  $baud = 19200
  4.   $crystal = 11059200
  5. $hwstack = 64
  6. $swstack = 64
  7. $framesize = 64
  8.  
  9. Echo Off
  10.  
  11. Config Submode = New
  12.  
  13. Const Addressw = 168
  14. Const Addressr = 169
  15. Config Twi = 100000
  16.  
  17. ' Konfiguracja LCD 2X16
  18. Config Lcdpin = Pin , E = Portb.0 , Rs = Portb.1 , Db7 = Portb.2 , Db6 = Portb.3 , Db5 = Portb.4 , Db4 = Portb.5 , Wr = Portb.6
  19. Config Lcd = 16x2                                           'nowy sposob zapisu
  20. Cursor Off
  21. Cls
  22.  
  23. ' Zezwolenie na przerwanie zewnętrzne
  24. Enable Interrupts
  25.  
  26.  'Konfiguracja TIMERA do obsługi UART
  27. Config Timer1 = Timer , Prescale = 256 , Compare_a = Disconnect , Compare_b = Disconnect , Clear Timer = 1
  28. Enable Compare1a : On Compare1a Przerwanie : Compare1a = 43199
  29.  
  30. Dim 1s As Byte  ' zmienna czasu
  31.  
  32. $include "Config_PCF8583.bas"
  33.  
  34. Config Serialin0 = Buffered , Size = 25 ' Buforowanie uart (UART odbierany w przerwaniu - rozmiar 25 znaków)
  35.  
  36. $include "Config_DS18B20.bas"
  37. Config 1wire = PortD.6 ' Konfiguracja 1-WIRE
  38.  
  39. $include "Config_Volt.bas"
  40.  
  41. ' Zmienne uart
  42. Dim Bufor As Byte
  43. Dim T_str As String * 25
  44. Dim T As String * 1
  45. Dim Ilosc_liter As Byte
  46. Dim Wartosc As word
  47. Dim Wartosc_t As String * 25
  48.  
  49. ' zmienna sterująca diodą led
  50. Dim L As Byte
  51.  Dim Stare_l As Byte
  52.  
  53. ' Zmienne zapisujące datę przeglądu technicznego do eeprom
  54. Dim N As Byte
  55. Dim Q As Byte
  56. Dim Q_str As String * 25
  57. Dim Buff(20) As Byte At Q_str Overlay
  58.  
  59. ' Zmienne zapisujące datę wymiany oleju do EEPROM
  60. Dim A As Byte
  61. Dim A_str As String * 25
  62. Dim I As Byte
  63. Dim I_str As String * 25
  64.  
  65. ' zmienna inicjująca wysłanie danych przez bluetooth
  66. Dim C As Byte ' wysłanie daty przeglądu
  67. Dim B As Byte ' wysłanie daty wymiany oleju
  68. Dim K As Byte ' wysłanie daty ubezpieczenia
  69.  
  70. Deflcdchar 1,6,21,13,6,6,13,21,6 'Bluetooth
  71.  
  72. ' Konfiguracja portu usypiania
  73. Config Portd.7 = Input : Portd.7 = 1 : Motor Alias Pind.7       ' silnik włączony = 0 / wyłączony = 1
  74.  
  75.  
  76.   ' Konfiguracja portów dla klawiatury
  77. Config Portd.2 = Input : Portd.2 = 1 : F1 Alias Pind.2
  78.  
  79.    ' Konfiguracja opóźnienia włączenia podświetlenia LCD
  80. Config Portd.4 = Input : Portd.4 = 1 : Int_pcf Alias Pind.4 ' Wejście sygnału z Pinu INT PCF8583
  81. Dim Lock As Byte ' Zmienna pomocnicza (flaga) do odliczenia 5 sekund
  82. Dim Licznik As Byte
  83. Dim Jest_5_impulsow As Byte
  84.  
  85.  
  86.   ' Konfiguracja zmiennych dla Menu Screen
  87. Dim Menu As Byte
  88. Dim Refresh As Byte
  89.  
  90.  ' Konfiguracja portu LED kontrolka gołoledzi
  91. Config Portd.5 = Output : Portd.5 = 1 : Led_glaze Alias Portd.5       ' kontrolka gołoledzi
  92.  
  93.  
  94. 'sub zapisuje Eeprom wartością pod podanym adresem
  95. Sub Write_eeprom(byval Adres As Byte , Byval Value As Byte)
  96.     I2cstart
  97.     I2cwbyte Addressw
  98.     I2cwbyte Adres
  99.     I2cwbyte Value
  100.     I2cstop
  101.     Waitms 10
  102. End Sub
  103.  
  104.  
  105. 'funkcja zwraca wartosć bajtu pod podanym adresem w eepromie
  106. Function Read_eeprom(byval Adres As Byte ) As Byte
  107.    I2cstart
  108.    I2cwbyte Addressw
  109.    I2cwbyte Adres
  110.    I2cstart
  111.    I2cwbyte Addressr
  112.    I2crbyte Read_eeprom , Nack
  113.    I2cstop
  114. End Function
  115.  
  116. L = Read_eeprom(2)  'odczyt L spod miejsca 2
  117.  clear serialin0
  118. ' ==============GŁÓWNA PĘTLA=================
  119. Do
  120.  
  121. Q_str = T_str
  122. 'A_str = T_str
  123. ' I_str = T_str
  124.  
  125. If L = 1 Then Led = 0 ' LED WYŁĄCZONA
  126. If L = 2 Then Led = 1 ' LED WŁĄCZONA
  127.  
  128. If C = 1 Then Gosub Wyslij
  129. If Q > 0 Then Gosub Zapisz
  130.  
  131. If A > 0 Then Gosub Zapisz_oil
  132. If B = 1 Then Gosub Wyslij_oil
  133.  
  134. If I > 0 Then Gosub Zapisz_ubezp
  135. If K = 1 Then Gosub Wyslij_ubezp
  136.  
  137. If Refresh = 1 Then                                        'odswiezanie co sekunde albo na żądanie
  138. Refresh = 0
  139. End If
  140.  
  141. Select Case Menu
  142.  
  143. Case 0
  144. '==========GŁÓWNY EKRAN Z GODZINĄ I DATĄ==============
  145.  
  146. Blad = Pcf8583_gettime()               ' odczytaj godzinę i date z układu PCF8583 , funkcja zwraca kod błędu
  147. If Blad = 2 Then                       ' jeżeli uszkodzona data
  148. Locate 1 , 1 : Lcd "   SET  CLOCK   "  ' wyświetl komunikat
  149. Locate 2 , 1 : Lcd Spc(20)
  150. Elseif Blad = 1 Then                   ' jeżeli błąd magistrali I2C
  151. Locate 1 , 1 : Lcd "    E R R O R   "  ' wyświetl komunikat
  152. Lcd Spc(11)
  153. Locate 2 , 1 : Lcd "   B U S  I2C   "
  154. Elseif Blad = 0 Then                   ' jeżeli prawidłowo odczytane dane
  155. Call Displaytime()                     ' wyświetl zegar
  156. End If
  157.  
  158. Case 1
  159. '=========EKRAN Z TEMPERATURĄ IN/OUT=================
  160. Call Displaytemp()
  161.  
  162. Case 2
  163. '=========EKRAN Z POMIAREM NAPIĘCIA POKŁADOWEGO==============
  164. Call Displayvolt()
  165.  
  166. End Select
  167.  
  168. Debounce F1 , 0 , Menu_sub , Sub  ' Każde naciśnięcie przycisku F1 powoduje przejscie do kolejnego ekranu
  169.  
  170.  
  171. If Motor = 1 then : Waitms 5 : Bitwait Motor , Set : Gosub Uspij ' Jeśłi silnik wyłączony, to idź do procedury Usypiania
  172. end if
  173.  
  174. Call Display_led_glaze()   ' Sterowanie kontrolką gołoledzi
  175.  
  176. 'co sekunde
  177. If 1s = 1 Then  ' jesli uplynela sekunda (te flage ustawia Timer)
  178. 1s = 0          ' skasuj flage by w petli dokonywalo sie to tylko raz na 1s
  179.  
  180. End If
  181.  
  182. Bufor = Ischarwaiting()
  183. If Bufor = 1 Then Gosub Odczytaj_uart                    ' Jeśli w buforze pojawią się dane z uart,to idź do procedury odbioru danych
  184.  
  185. Loop
  186. End
  187.  
  188.  
  189. ' ===============KONIEC GŁÓWNEJ PĘTLI=========================
  190.  
  191. $include "PCF8583.bas"
  192.  
  193. $include "DS18B20.bas"
  194.  
  195. $include "Volt.bas"
  196.  
  197. 'odmierzanie czasu
  198. Przerwanie:
  199. 1s = 1
  200. Return
  201.  
  202. ' Przewijanie ekranów
  203. Menu_sub:
  204. Incr Menu
  205. If Menu > 2 Then Menu = 0
  206. Cls : Refresh = 1
  207. Return
  208.  
  209. ' Procedura odbioru danych z UART
  210. Odczytaj_uart:
  211.  
  212.    T_str = ""                                               'usuniecie tego co jest
  213.    Do
  214.       Bufor = Waitkey()
  215.       Locate 1 , 10 : Lcd Bufor                             ' nowa linijka
  216.  
  217.      If Bufor = 13 Then Exit Do                             'jak enter to wyjdź
  218.      If Bufor = 10 Then Exit Do                             ' nowa linia
  219.      If Refresh = 1 Then Exit Do
  220.  
  221.  
  222.  
  223.  
  224.  
  225.      T_str = T_str + Chr(bufor)
  226.    Loop
  227.        Locate 1 , 10 : Lcd Bufor                            ' nowa linijka
  228.  
  229.  
  230.          Ilosc_liter = Len(t_str)
  231.          T = Mid(t_str , 1 , 1)
  232.            Delchar T_str , 1
  233.              Wartosc = Val(t_str)
  234.  
  235.  
  236.     Select Case T
  237.   ' Zegarek
  238.     Case "M"
  239.       Minute = Wartosc
  240.     Case "H"
  241.       Hour = Wartosc
  242.     Case "S"
  243.       Second = Wartosc
  244.  
  245.  ' dioda
  246.       Case "L"
  247.       L = Wartosc
  248.  
  249.  ' kalendarz
  250.       Case "Z"
  251.       Day = Wartosc
  252.       Case "W"
  253.       Month = Wartosc
  254.       Case "Y"
  255.       Year = Wartosc
  256.  
  257.  ' zapis danych
  258.       Case "Q"        ' zmienna zapisu daty przeglądu technicznego
  259.       Q = Wartosc
  260.       Case "C"        ' zmienna wysłania daty przeglądu technicznego
  261.       C = Wartosc
  262.       Case "A"        ' zmienna zapisu daty wymiany oleju silnikowego
  263.       A = Wartosc
  264.       Case "B"        ' zmienna wysłania daty wymiany oleju silnikowego
  265.       B = Wartosc
  266.       Case "I"        ' zmienna zapisu daty kolejnego ubezpieczenia
  267.       I = Wartosc
  268.       Case "K"        ' zmienna wysłania daty kolejnego ubezpieczenia
  269.       K = Wartosc
  270.  
  271.          Cls
  272.     End Select
  273.  
  274.    Blad = Pcf8583_storetime(second , Minute , Hour , Day , Month , Year)
  275.  
  276.  
  277.  
  278.  ' ========================Zapis warotści zmiennej LED do 24C02===========================================
  279.  
  280.   If Stare_l <> L Then
  281.    Stare_l = L
  282.     Call Write_eeprom(2 , L)
  283.   end if
  284.  
  285.  
  286.  
  287.  ' ========================Zapis daty przeglądu technicznego do 24C02=====================================
  288.  
  289. Zapisz:
  290. Do
  291. If Q > 0 then
  292. Q_str = T_str
  293. For N = 1 To 20
  294. Call Write_eeprom(n + 5 , Buff(n))                     'przekazując można robić obliczenia
  295. Next
  296. end if
  297. Q = 0
  298. Return
  299. Loop
  300.  
  301. ' ========================Odczyt daty przeglądu techniczengo i wysłanie danych do smartfona================
  302.  
  303. Wyslij:
  304. Do
  305. For N = 1 To 20
  306. Buff(n) = Read_eeprom(n + 5)
  307. Next
  308. Print Q_str
  309. C = 0
  310.   return
  311. loop
  312.  
  313.  ' ========================Zapis daty wymiany oleju silnikowego do 24C02===================================
  314.  
  315. Zapisz_oil:
  316. Do
  317. If A > 0 Then
  318. A_str = T_str
  319. For N = 1 To 20
  320. Call Write_eeprom(n + 26 , Buff(n))
  321. Next
  322. end if
  323. A = 0
  324. Return
  325. Loop
  326.  
  327.  
  328.  ' =====================Odczyt daty wymiany oleju silnikowego i wysłanie danych do smartfona===============
  329.  
  330. Wyslij_oil:
  331. Do
  332. For N = 1 To 20
  333. Buff(n) = Read_eeprom(n + 26)
  334. Next
  335. Print A_str
  336. B = 0
  337. Return
  338. loop
  339.  
  340. ' ========================Zapis daty ubezpieczenia do 24C02===================================
  341.  
  342. Zapisz_ubezp:
  343. Do
  344. If I > 0 Then
  345. I_str = T_str
  346. For N = 1 To 20
  347. Call Write_eeprom(n + 55 , Buff(n))
  348. Next
  349. end if
  350. I = 0
  351. Return
  352. Loop
  353.  
  354. ' =====================Odczyt daty ubezpieczenia i wysłanie danych do smartfona===============
  355.  
  356. Wyslij_ubezp:
  357. Do
  358. For N = 1 To 20
  359. Buff(n) = Read_eeprom(n + 55)
  360. Next
  361. Print I_str
  362. K = 0
  363. Return
  364. loop
  365.  
  366.  
  367.  
  368.  
  369.  
  370.  
  371.  ' ======================Procedura stanu uśpienia gdy silnik wyłączony=====================================
  372. Uspij:
  373. Cls
  374. Motor = 1
  375. Do
  376.  Led_glaze = INT_PCF
  377.  
  378. If Motor = 1 then Display off : Podswietlenie = 0  ' Jeśli silnik wyłączony, to wyłącz LCD i podświetlenie
  379.  
  380. 'Led_glaze = 1 ' Kontrolka gołoledzi wyłączona
  381.           'end if
  382. If Motor = 0 then ' Jeśli silnik włączony, to:
  383.  
  384. ' ########################## Odpowiada za opóźnienie 5 sekund włączenia LCD ############################
  385.  If Int_pcf = 0 Then      'jeśli PCF ustalił stan niski
  386.   Lock = 1                'to zapamietaj, ustaw flage
  387.  Else                     'jesli PCF ustawil już stan wysoki
  388.   If Lock = 1 Then        'a byl wczesniej stan niski (flaga)
  389.    Lock = 0               'skasuj flage do czasu kolejnego niskiego stanu
  390.     Incr Licznik          'tylko raz na zmiane stanu zwiekszamy licznik
  391.     If Licznik = 5 Then   ' jeśli licznik osiągnął wartość 5 (5sekund), to
  392.      Licznik = 0          ' zeruj licznik
  393.       Jest_5_impulsow = 1 'przejdź do włączenia podświetlenia
  394.     End If
  395.   End If
  396.  End If
  397.  If Jest_5_impulsow = 1 Then
  398.   Jest_5_impulsow = 0
  399. ' ######################## Koniec części opóźniającej włączenie LCD ###################################
  400.  
  401. Podswietlenie = 1 ' włącz podświetlenie
  402. Display on        ' włącz wyswietlacz
  403. cls               ' wyczyść wyswietlacz
  404.    ' Wyczyść informacje zgromadzone w Buforze UART
  405. return            ' wracaj do głównego programu
  406. end if
  407.    end if
  408.          'end if
  409. Loop
  410.  
Bardzo proszę Was o pomoc w rozwiązaniu tego problemu. Jeśli coś niejasno opisałem, to piszcie.
Ostatnio zmieniony 13 mar 2017, 19:29 przez Michał6201, łącznie zmieniany 1 raz.
Awatar użytkownika
niveasoft
Posty: 1313
Rejestracja: 17 sie 2015, 12:13
Kontakt:

Re: Problem z zapisem do eeprom więcej niż 2 zmiennych

Post autor: niveasoft » 12 mar 2017, 20:37

Temat przypomniał mi, ze muszę popracować nad właściwym formatowaniem kodów.

Twój kod mógłby być napisany lepiej, ale chyba zrozumiałem istotę problemu.

Kiedy odbierasz dane w tym Subie Odczytaj_uart to po rozpoznaniu literki przypisujesz wartość podobnie nazwanym zmiennym.
Czyli dla literki M zmienna M otrzyma wartość wysłaną zaraz za ta literką. Jest tu jednak rzecz na którą powinieneś zwrócić uwagę.

Funkcja Val() nie potrafi sprowadzić wartości 12-03-2017 do wartości odpowiadającej choćby jednemu bajtowi.
Po prostu te myślniki to nie jest żadna wartość. Dodatkowo w Helpie możesz przeczytać, że jeśli użyjesz niepoprawnych znaków to w rezultacie możesz otrzymać zero albo nieprawidłowy wynik.

Potem w pętli głównej sprawdzasz czy zmienna Q ma wartość większą od zera i pewnie jej nie ma ze względu na to co napisałem wyżej.

Rozwiązaniem może być zamiana zapisu
  1. Case "Q"        ' zmienna zapisu daty przeglądu technicznego
  2.          Q = Wartosc

na coś takiego ;)
  1. Case "Q"        ' zmienna zapisu daty przeglądu technicznego
  2.          Q = 1
Proste co? :D
Kod ten jednak warto by napisać inaczej ...
Awatar użytkownika
Michał6201
Posty: 165
Rejestracja: 03 paź 2015, 20:07

Re: Problem z zapisem do eeprom więcej niż 2 zmiennych

Post autor: Michał6201 » 13 mar 2017, 20:17

Cześć

Zmieniłem zapis daty z 12-03-2017 na 12032017.
Niestety efekt jest taki sam. Dane zostają zapisane do eeprom tylko w przypadku pierwszej zmiennej, natomiast pozostałe dane nie zapisują się. Tzn. dzieje się tu trochę dziwna rzecz. Zapisałem wszystkie trzy zmienne i przy odczycie pamięta te wartości, natomiast po wyłączeniu zasilania lub resecie procka dane znikają z eeprom poza tą pierwszą zmienną. Ta pierwsza zmienna pięknie się odczytuje.

Mało tego zapisanie tylko jednego znaku do tych dwóch pozostałych zmiennych np.: A3 i na końcu 10 oraz 13, sprawia że mogę odczytać później wartość "3", ale pamiętana ona jest tylko do wyłączenie zasilania/resetu procka.

Pierwsza zmienna jaką zapisuję i która działa i jest pamiętna zawsze, ma wartość z myślnikami,czyli Q12-03-2017 i tu bez różnicy co wpiszę.

Dlatego nie rozumiem, dlaczego w przypadku pierwszej zmiennej działa wszystko, a z pozostałymi dwiema zmiennymi dzieją się takie cuda.

Jest jeszcze jeden problem, może to on powoduje te problemy, a mianowicie - odłączenie zasilania od samego modułu BT powoduje zawieszenie programu. Mam odczyt na lcd tego co się dzieje podczas odłączenie zasilania od BT - moduł wysyła przypadkowe liczby dwucyfrowe np.: 50 lub 52 itd.
Rozłączenie komunikacji ze smartfonem daje podobne rezultaty - BT wysyła do procka przypadkową liczbę, która powoduje zawieszenie programu. Może tu jest problem?
Awatar użytkownika
niveasoft
Posty: 1313
Rejestracja: 17 sie 2015, 12:13
Kontakt:

Re: Problem z zapisem do eeprom więcej niż 2 zmiennych

Post autor: niveasoft » 13 mar 2017, 20:22

Zmień najpierw Q = Wartosc na Q = 1 jak napisałem to pogadamy. Po co Ci rada jak i tak robisz inaczej? :D
Sprawę zawieszania też się omówi, ale nie wszystko na raz.

Możliwe że prostota tego rozwiązania własnie je rozkłada. Jedna literka odpowiada za zapis reszty a literka Q to zwykłe 81 lub 51Hex
Lepiej byłoby rozpoznawać całe zwroty typu "AT+Q"
Awatar użytkownika
Michał6201
Posty: 165
Rejestracja: 03 paź 2015, 20:07

Re: Problem z zapisem do eeprom więcej niż 2 zmiennych

Post autor: Michał6201 » 13 mar 2017, 20:51

Zmieniłem:
  1. ' zapis danych
  2.       Case "Q"        ' zmienna zapisu daty przeglądu technicznego
  3.       Q = 1
  4.       Case "C"        ' zmienna wysłania daty przeglądu technicznego
  5.       C = 1
  6.       Case "A"        ' zmienna zapisu daty wymiany oleju silnikowego
  7.       A = 1
  8.       Case "B"        ' zmienna wysłania daty wymiany oleju silnikowego
  9.       B = 1
  10.       Case "I"        ' zmienna zapisu daty kolejnego ubezpieczenia
  11.       I = 1
  12.       Case "K"        ' zmienna wysłania daty kolejnego ubezpieczenia
  13.       K = 1
Bez zmian działanie programu. Pierwsza zmienna zapisana, pozostałem dwie zmienne po odłączeniu zasilania/reset procka znikają.

A może ta pamięć za mała jest i nie zapisują się pozostałe zmienne? Możesz zerknąć czy ja dobrze wpisałem numery komórek do zapisu danych?
  1.  
  2.  ' ========================Zapis daty wymiany oleju silnikowego do 24C02===================================
  3.  
  4. Zapisz_oil:
  5. Do
  6. If A > 0 Then
  7. A_str = T_str
  8. For N = 1 To 20
  9. Call Write_eeprom(n + 26 , Buff(n))
  10. Next
  11. end if
  12. A = 0
  13. Return
  14. Loop
Awatar użytkownika
niveasoft
Posty: 1313
Rejestracja: 17 sie 2015, 12:13
Kontakt:

Re: Problem z zapisem do eeprom więcej niż 2 zmiennych

Post autor: niveasoft » 14 mar 2017, 0:06

Okay. Nie widziałem się w tym bałaganie więc pozwoliłem sobie to przepisać.
Będziesz musiał przepisać lekko swoją apkę na telefon ale to chyba nie problem skoro może to projektowi wyjść na dobre.

Teraz program reaguje na komendy : TIM, ATL, ATP, ATU i ATO
Są to skróty TIM od TIME, ATL od AT Lamp, ATP - Przegląd, ATU - Ubezpieczenie, ATO - Olej
Żeby coś wysłać i zapisać musisz to wysłac ze znakiem "=" . Przykład dla czasu "TIM=23:08:55"
Przykład dla ubezpieczenia "ATU=01-01-18"
Dane zostaną zapisane w eeprom jako trzy bajty.

Kiedy chcesz zapytać o ubezpieczenie wystarczy że wyślesz "ATU?" a procesor odpowie "ATU=01-01-18"
Czyli żeby zapytać wysyłasz komendę ze znakiem zapytania.

Program pisałem na sucho więc jakiś błąd mógł się wkraść i co nieco pewnie można jeszcze zoptymalizować ;)
Na drugi raz podeślij też te pliki które się inkluduje bo nie można bez nich potem kontrolnie kompilować.
  1. $regfile = "m16adef.dat"                                    ' Typ procesora
  2. $baud = 19200
  3. $crystal = 11059200
  4. $hwstack = 64
  5. $swstack = 32
  6. $framesize = 64
  7.  
  8. Echo Off
  9.  
  10. Config Submode = New
  11.  
  12. Config Serialin0 = Buffered , Size = 25                     ' UART odbierany w przerwaniu z buforem
  13.  
  14. Const _valcheck = 1                                         ' wartości ładowane do Val() będa sprawdzane
  15.  
  16. Const Addressw = 168
  17. Const Addressr = 169
  18.  
  19. $lib "i2c_twi.lbx"
  20.  Config Scl = Portc.0
  21.  Config Sda = Portc.1
  22.   I2cinit
  23. Config Twi = 100000
  24.  
  25.  
  26. ' Konfiguracja LCD 2X16
  27. Config Lcdpin = Pin , E = Portb.0 , Rs = Portb.1 , Db7 = Portb.2 , Db6 = Portb.3 , Db5 = Portb.4 , Db4 = Portb.5 , Wr = Portb.6
  28. Config Lcd = 16x2                                           'nowy sposob zapisu
  29.  Deflcdchar 1 , 6 , 21 , 13 , 6 , 6 , 13 , 21 , 6           'Bluetooth
  30. Cursor Off
  31. Cls
  32.  
  33.  'Konfiguracja TIMERA
  34. Config Timer1 = Timer , Prescale = 256 , Compare_a = Disconnect , Compare_b = Disconnect , Clear_timer = 1
  35.  Compare1a = 43199
  36.  
  37. ' Konfiguracja portu usypiania
  38. Config Portd.7 = Input : Portd.7 = 1 : Motor Alias Pind.7       ' silnik włączony = 0 / wyłączony = 1
  39. ' Konfiguracja portów dla klawiatury
  40. Config Portd.2 = Input : Portd.2 = 1 : F1 Alias Pind.2
  41. ' Konfiguracja opóźnienia włączenia podświetlenia LCD
  42. Config Portd.4 = Input : Portd.4 = 1 : Int_pcf Alias Pind.4 ' Wejście sygnału z Pinu INT PCF8583
  43. ' Konfiguracja portu LED kontrolka gołoledzi
  44. Config Portd.5 = Output : Portd.5 = 1 : Led_glaze Alias Portd.5       ' kontrolka gołoledzi
  45.  
  46.  
  47. $include "Config_PCF8583.bas"
  48.  
  49.  
  50. '$include "Config_DS18B20.bas"
  51. Config 1wire = PortD.6 ' Konfiguracja 1-WIRE
  52.  
  53. '$include "Config_Volt.bas"
  54.  
  55. ' Zmienne uart
  56. Dim Char As Byte , Helpb As Byte , Helpstr As String * 10
  57. Dim T_str As String * 25
  58.  
  59. ' zmienna sterująca diodą led
  60. Dim L As Byte , Stare_l As Byte
  61.  
  62. ' Zmienne zapisujące datę przeglądu technicznego do eeprom
  63. Dim N As Byte
  64. Dim Q_str As String * 15
  65. Dim Buff(16) As Byte At Q_str Overlay
  66.  
  67. Dim Lock As Byte , Licznik As Byte , Jest_5_impulsow As Byte
  68.  
  69. ' Konfiguracja zmiennych dla Menu Screen
  70. Dim Menu As Byte , Refresh As Byte
  71.  
  72.  
  73. Dim Got_str As Byte , Cmd_timeout As Byte , Option As Byte
  74. Dim One As Byte , Two As Byte , Three As Byte
  75.  
  76. Lampka Alias 5
  77. Przeglad Alias 10
  78. Olej Alias 15
  79. Polisa Alias 20
  80.  
  81. 'sub zapisuje Eeprom wartością pod podanym adresem
  82. Sub Write_eeprom(byval Adres As Byte , Byval Value As Byte)
  83.    I2cstart
  84.    I2cwbyte Addressw
  85.    I2cwbyte Adres
  86.    I2cwbyte Value
  87.    I2cstop
  88.    Waitms 5        ' przy 3ms występuje problem z zapisem kolejnych bajtów
  89. End Sub
  90.  
  91. 'funkcja zwraca wartosć bajtu pod podanym adresem w eepromie
  92. Function Read_eeprom(byval Adres As Byte ) As Byte
  93.    I2cstart
  94.    I2cwbyte Addressw
  95.    I2cwbyte Adres
  96.    I2cstart
  97.    I2cwbyte Addressr
  98.    I2crbyte Read_eeprom , Nack
  99.    I2cstop
  100. End Function
  101.  
  102. Sub Write_ee(byval Address As Byte )
  103.  
  104.  For N = 1 To 3
  105.   Call Write_eeprom(address , Buff(n))
  106.    Incr Address
  107.  Next
  108.  
  109. End Sub
  110.  
  111. Sub Read_ee(byval Address As Byte )
  112.   For N = 1 To 3
  113.    Buff(n) = Read_eeprom(address)
  114.    If Buff(n) > 99 Then Buff(n) = 99
  115.     Incr Address
  116.   Next
  117. End Sub
  118.  
  119. Sub Send_answear(byval Command As String)
  120.   Helpstr = Command + "="
  121.   If Buff(1) < 10 Then Helpstr = Helpstr + "0"
  122.    Helpstr = Helpstr + Str(buff(1)) + "-"
  123.   If Buff(2) < 10 Then Helpstr = Helpstr + "0"
  124.    Helpstr = Helpstr + Str(buff(2)) + "-"
  125.   If Buff(3) < 10 Then Helpstr = Helpstr + "0"
  126.    Helpstr = Helpstr + Str(buff(3))
  127.     Print Helpstr
  128. End Sub
  129.  
  130. Function Find(byval Command As String)as Byte
  131.  
  132.   Find = 0 : Helpb = Instr(t_str , Command)                 'szukaj wyrażenia
  133.  
  134.     If Helpb > 0 Then
  135.       Helpb = Helpb + 3
  136.       Helpstr = Mid(t_str , Helpb , 1)
  137.       Select Case Helpstr
  138.        Case "=" : Find = 1
  139.        Case "?" : Find = 2
  140.       End Select
  141.     End If
  142.  
  143. End Function
  144.  
  145. Sub Get_three_values()
  146.  
  147.  'in Helpb stored position of the found command
  148.  '             format TIM=23-05-00
  149.   Incr Helpb
  150.    Helpstr = Mid(t_str , Helpb , 2)
  151.    Char = Val(helpstr)
  152.    If Err = 0 Then One = Char
  153.   Helpb = Helpb + 3
  154.    Helpstr = Mid(t_str , Helpb , 2)
  155.    Char = Val(helpstr)
  156.    If Err = 0 Then Two = Char
  157.   Helpb = Helpb + 3
  158.    Helpstr = Mid(t_str , Helpb , 2)
  159.    Char = Val(helpstr)
  160.    If Err = 0 Then Three = Char
  161.  
  162.  
  163. End Sub
  164.  
  165.  
  166. L = Read_eeprom(lampka)
  167.  
  168. Enable Interrupts
  169.  
  170. ' ==============GŁÓWNA PĘTLA=================
  171. Do
  172.  
  173.    'co sekunde
  174.    If Tifr.ocf1a = 1 Then                                   ' jesli uplynela sekunda (te flage ustawia Timer)
  175.     Tifr.ocf1a = 1                                          ' skasuj flage by w petli dokonywalo sie to tylko raz na 1s
  176.      Refresh = 1
  177.  
  178.     If Cmd_timeout > 0 Then
  179.      Decr Cmd_timeout
  180.       If Cmd_timeout = 0 Then T_str = ""
  181.     End If
  182.    End If
  183.  
  184.    If 0 < Ischarwaiting() Then
  185.  
  186.  
  187.       Char = Inkey()
  188.  
  189.       Select Case Char
  190.        Case 10
  191.        Case 13 : Got_str = 1
  192.        Case Else
  193.         T_str = T_str + Chr(char)
  194.       End Select
  195.  
  196.       If Len(t_str) > 24 Then Got_str = 1
  197.  
  198.       If Got_str = 1 Then
  199.  
  200.         Option = Find( "ATL")
  201.  
  202.          Select Case Option
  203.           Case 1
  204.            Call Get_three_values()
  205.            If Stare_l <> One Then
  206.             Stare_l = One
  207.             L = One
  208.              Call Write_eeprom(lampka , L)
  209.            End If
  210.  
  211.          End Select
  212.  
  213.         Option = Find( "ATO")
  214.  
  215.          Select Case Option
  216.           Case 1
  217.            Call Get_three_values()
  218.             Buff(1) = One
  219.             Buff(2) = Two
  220.             Buff(3) = Three
  221.              Call Write_ee(olej)
  222.           Case 2
  223.            Call Read_ee(olej)
  224.             Call Send_answear( "ATO")
  225.          End Select
  226.  
  227.         Option = Find( "ATP")
  228.  
  229.          Select Case Option
  230.           Case 1
  231.            Call Get_three_values()
  232.             Buff(1) = One
  233.             Buff(2) = Two
  234.             Buff(3) = Three
  235.              Call Write_ee(przeglad)
  236.           Case 2
  237.            Call Read_ee(przeglad)
  238.             Call Send_answear( "ATP")
  239.          End Select
  240.  
  241.  
  242.         Option = Find( "ATU")
  243.  
  244.          Select Case Option
  245.           Case 1
  246.            Call Get_three_values()
  247.             Buff(1) = One
  248.             Buff(2) = Two
  249.             Buff(3) = Three
  250.              Call Write_ee(polisa)
  251.           Case 2
  252.            Call Read_ee(polisa)
  253.             Call Send_answear( "ATU")
  254.          End Select
  255.  
  256.  
  257.         Option = Find( "TIM")
  258.  
  259.          If Option = 1 Then
  260.           Call Get_three_values()
  261.            Hour = One
  262.            Minute = Two
  263.            Second = Three
  264.             Blad = Pcf8583_storetime(second , Minute , Hour , Day , Month , Year)
  265.          End If
  266.  
  267.  
  268.         Got_str = 0
  269.       Else
  270.        Cmd_timeout = 2
  271.       End If
  272.  
  273.    End If
  274.  
  275.  
  276.  
  277.    If Refresh = 1 Then                                        'odswiezanie co sekunde albo na żądanie
  278.  
  279.       Select Case Menu
  280.  
  281.          Case 0
  282.           '==========GŁÓWNY EKRAN Z GODZINĄ I DATĄ==============
  283.  
  284.             Blad = Pcf8583_gettime()               ' odczytaj godzinę i date z układu PCF8583 , funkcja zwraca kod błędu
  285.             If Blad = 2 Then                       ' jeżeli uszkodzona data
  286.                Locate 1 , 1 : Lcd "   SET  CLOCK   "  ' wyświetl komunikat
  287.                Locate 2 , 1 : Lcd Spc(20)
  288.             Elseif Blad = 1 Then                   ' jeżeli błąd magistrali I2C
  289.                Locate 1 , 1 : Lcd "    E R R O R   "  ' wyświetl komunikat
  290.                Lcd Spc(11)
  291.                Locate 2 , 1 : Lcd "   B U S  I2C   "
  292.             Elseif Blad = 0 Then                   ' jeżeli prawidłowo odczytane dane
  293.                Call Displaytime()                     ' wyświetl zegar
  294.             End If
  295.  
  296.          Case 1
  297.           '=========EKRAN Z TEMPERATURĄ IN/OUT=================
  298.             'Call Displaytemp()
  299.  
  300.          Case 2
  301.           '=========EKRAN Z POMIAREM NAPIĘCIA POKŁADOWEGO==============
  302.             'Call Displayvolt()
  303.  
  304.       End Select
  305.  
  306.  
  307.       Refresh = 0
  308.    End If
  309.  
  310.    Debounce F1 , 0 , Menu_sub , Sub  ' Każde naciśnięcie przycisku F1 powoduje przejscie do kolejnego ekranu
  311.  
  312.  
  313.    If Motor = 1 Then Gosub Uspij                            ' Jeśłi silnik wyłączony, to idź do procedury Usypiania
  314.  
  315.    'Call Display_led_glaze()   ' Sterowanie kontrolką gołoledzi
  316.  
  317.  
  318.  
  319. Loop
  320. End
  321.  
  322.  
  323. ' ===============KONIEC GŁÓWNEJ PĘTLI=========================
  324.  
  325. $include "PCF8583.bas"
  326. '$include "DS18B20.bas"
  327. '$include "Volt.bas"
  328.  
  329.  
  330.  
  331. ' Przewijanie ekranów
  332. Menu_sub:
  333.  Incr Menu : If Menu > 2 Then Menu = 0
  334.    Cls : Refresh = 1
  335. Return
  336.  
  337.  ' ======================Procedura stanu uśpienia gdy silnik wyłączony=====================================
  338. Uspij:
  339.    Cls
  340.    Motor = 1
  341.    Do
  342.       Led_glaze = INT_PCF
  343.  
  344.       If Motor = 1 then Display off : Podswietlenie = 0  ' Jeśli silnik wyłączony, to wyłącz LCD i podświetlenie
  345.  
  346.     'Led_glaze = 1 ' Kontrolka gołoledzi wyłączona
  347.           'end if
  348.       If Motor = 0 then ' Jeśli silnik włączony, to:
  349.  
  350.        ' ########################## Odpowiada za opóźnienie 5 sekund włączenia LCD ############################
  351.          If Int_pcf = 0 Then      'jeśli PCF ustalił stan niski
  352.             Lock = 1                'to zapamietaj, ustaw flage
  353.          Else                     'jesli PCF ustawil już stan wysoki
  354.             If Lock = 1 Then        'a byl wczesniej stan niski (flaga)
  355.                Lock = 0               'skasuj flage do czasu kolejnego niskiego stanu
  356.                Incr Licznik          'tylko raz na zmiane stanu zwiekszamy licznik
  357.                If Licznik = 5 Then   ' jeśli licznik osiągnął wartość 5 (5sekund), to
  358.                   Licznik = 0          ' zeruj licznik
  359.                   Jest_5_impulsow = 1 'przejdź do włączenia podświetlenia
  360.                End If
  361.             End If
  362.          End If
  363.          If Jest_5_impulsow = 1 Then
  364.             Jest_5_impulsow = 0
  365.         ' ######################## Koniec części opóźniającej włączenie LCD ###################################
  366.  
  367.             Podswietlenie = 1 ' włącz podświetlenie
  368.             Display on        ' włącz wyswietlacz
  369.             cls               ' wyczyść wyswietlacz
  370.           ' Wyczyść informacje zgromadzone w Buforze UART
  371.             return            ' wracaj do głównego programu
  372.          end if
  373.       end if
  374.          'end if
  375.    Loop
Awatar użytkownika
Michał6201
Posty: 165
Rejestracja: 03 paź 2015, 20:07

Re: Problem z zapisem do eeprom więcej niż 2 zmiennych

Post autor: Michał6201 » 14 mar 2017, 22:49

Dziękuję Ci za pomoc, jak zwykle kawał roboty i czasu poświęciłeś dla mnie.

Aplikację muszę zbudować od podstaw. Póki co zrobiłem wysyłanie czasu i daty do procka.
Jest mały problem - jeśli minuty lub godziny to jedności,np.: 09:05:01, to aplikacja wysyła czas w tym formacie: TIM=9:5:1 i wtedy źle wyświetla czas zegarku. Nie wiem dlaczego tak się dzieje, bo przecież w pliku PCF8583.bas jest zapisane:
  1. Sub Displaytime()
  2.  
  3.    Locate 1 , 1          ' <<<<<<<<-ustaw sobie gdzie ma wyświetlać
  4.  
  5.   If Hour < 10 Then Lcd "0" : Lcd Hour ; ":"
  6.   If Minute < 10 Then Lcd "0" : Lcd Minute ; ":"
  7.   If Second < 10 Then Lcd "0" : Lcd Second
  8.  
  9.    Lcd Spc(8)            ' 8 spacji
  10.  
  11.  
  12.  
  13.    Locate 2 , 2          ' <<<<<<<<-ustaw sobie gdzie ma wyświetlać
  14.  
  15.    Lcd Lookupstr(weekday , Weekdays) ; " "
  16.    If Day < 10 Then Lcd "0" : Lcd Day ; "-"
  17.    If Month < 10 Then Lcd "0" : Lcd Month ; "-" ; Year
  18.    'Lcd Spc(8)                                               ' 8 spacji
  19.  
  20.  
  21. End Sub
  22.  
  23. Weekdays:
  24.  
  25.     Data "Nie" , "Pon" , "Wto" , "Sro" , "Czw" , "Pt " , "Sob"
  26.  
Więc automatycznie program jeśli wykryje np. minuty <10, to ma nadpisywać "0"
Jednak tak się nie dzieje, bo aplikacja wysyła ciąg znaków: TIM=9:22:33, więc skoro nie ma zera przed 9, to automatycznie przesuwa wszystko w lewą stronę w tym przypadku o jedno miejsce.

To samo się dzieje z datą.

Wcześniej było tak, że minuty to była osobna zmienna, godziny, osobna zmienna, a sekundy osobna, dzięki temu program mógł nadpisać zerami, jeśli minuty, to np.: 8.

Niestety nie mam jak tego zrobić w aplikacji na smartfona, ponieważ ona zaczytuje czas i datę z androida i automatycznie podstawia wartości w formacie 9:5:6
Jak temu zaradzić?

W załączeniu przesyłam całość programu razem z plikiem include do zegarka:

Główny plik:
  1. ' 14.03.2017
  2.  
  3.      $regfile = "m16adef.dat"                                    ' Typ procesora
  4.     $baud = 19200
  5.     $crystal = 11059200
  6.     $hwstack = 64
  7.     $swstack = 32
  8.     $framesize = 64
  9.  
  10.     Echo Off
  11.  
  12.     Config Submode = New
  13.  
  14.     Config Serialin0 = Buffered , Size = 25                     ' UART odbierany w przerwaniu z buforem
  15.  
  16.     Const _valcheck = 1                                         ' wartości ładowane do Val() będa sprawdzane
  17.  
  18.     Const Addressw = 168
  19.     Const Addressr = 169
  20.  
  21.     $lib "i2c_twi.lbx"
  22.      Config Scl = Portc.0
  23.      Config Sda = Portc.1
  24.       I2cinit
  25.     Config Twi = 100000
  26.  
  27.  
  28.     ' Konfiguracja LCD 2X16
  29.     Config Lcdpin = Pin , E = Portb.0 , Rs = Portb.1 , Db7 = Portb.2 , Db6 = Portb.3 , Db5 = Portb.4 , Db4 = Portb.5 , Wr = Portb.6
  30.     Config Lcd = 16x2                                           'nowy sposob zapisu
  31.      Deflcdchar 1 , 6 , 21 , 13 , 6 , 6 , 13 , 21 , 6           'Bluetooth
  32.     Cursor Off
  33.     Cls
  34.  
  35.      'Konfiguracja TIMERA
  36.     Config Timer1 = Timer , Prescale = 256 , Compare_a = Disconnect , Compare_b = Disconnect , Clear_timer = 1
  37.      Compare1a = 43199
  38.  
  39.     ' Konfiguracja portu usypiania
  40.     Config Portd.7 = Input : Portd.7 = 1 : Motor Alias Pind.7       ' silnik włączony = 0 / wyłączony = 1
  41.     ' Konfiguracja portów dla klawiatury
  42.     Config Portd.2 = Input : Portd.2 = 1 : F1 Alias Pind.2
  43.     ' Konfiguracja opóźnienia włączenia podświetlenia LCD
  44.     Config Portd.4 = Input : Portd.4 = 1 : Int_pcf Alias Pind.4 ' Wejście sygnału z Pinu INT PCF8583
  45.     ' Konfiguracja portu LED kontrolka gołoledzi
  46.     Config Portd.5 = Output : Portd.5 = 1 : Led_glaze Alias Portd.5       ' kontrolka gołoledzi
  47.  
  48.  
  49.     $include "Config_PCF8583.bas"
  50.  
  51.  
  52.     $include "Config_DS18B20.bas"
  53.     Config 1wire = PortD.6 ' Konfiguracja 1-WIRE
  54.  
  55.     $include "Config_Volt.bas"
  56.  
  57.     ' Zmienne uart
  58.     Dim Char As Byte , Helpb As Byte , Helpstr As String * 10
  59.     Dim T_str As String * 25
  60.  
  61.     ' zmienna sterująca diodą led
  62.     Dim L As Byte , Stare_l As Byte
  63.  
  64.     ' Zmienne zapisujące datę przeglądu technicznego do eeprom
  65.     Dim N As Byte
  66.     Dim Q_str As String * 15
  67.     Dim Buff(16) As Byte At Q_str Overlay
  68.  
  69.     Dim Lock As Byte , Licznik As Byte , Jest_5_impulsow As Byte
  70.  
  71.     ' Konfiguracja zmiennych dla Menu Screen
  72.     Dim Menu As Byte , Refresh As Byte
  73.  
  74.  
  75.     Dim Got_str As Byte , Cmd_timeout As Byte , Option As Byte
  76.     Dim One As Byte , Two As Byte , Three As Byte
  77.  
  78.     Lampka Alias 5
  79.     Przeglad Alias 10
  80.     Olej Alias 15
  81.     Polisa Alias 20
  82.  
  83.     'sub zapisuje Eeprom wartością pod podanym adresem
  84.     Sub Write_eeprom(byval Adres As Byte , Byval Value As Byte)
  85.        I2cstart
  86.        I2cwbyte Addressw
  87.        I2cwbyte Adres
  88.        I2cwbyte Value
  89.        I2cstop
  90.        Waitms 3
  91.     End Sub
  92.  
  93.     'funkcja zwraca wartosć bajtu pod podanym adresem w eepromie
  94.     Function Read_eeprom(byval Adres As Byte ) As Byte
  95.        I2cstart
  96.        I2cwbyte Addressw
  97.        I2cwbyte Adres
  98.        I2cstart
  99.        I2cwbyte Addressr
  100.        I2crbyte Read_eeprom , Nack
  101.        I2cstop
  102.     End Function
  103.  
  104.     Sub Write_ee(byval Address As Byte )
  105.  
  106.      For N = 1 To 3
  107.       Call Write_eeprom(address , Buff(n))
  108.        Incr Address
  109.      Next
  110.  
  111.     End Sub
  112.  
  113.     Sub Read_ee(byval Address As Byte )
  114.       For N = 1 To 3
  115.        Buff(n) = Read_eeprom(address)
  116.        If Buff(n) > 99 Then Buff(n) = 99
  117.         Incr Address
  118.       Next
  119.     End Sub
  120.  
  121.     Sub Send_answear(byval Command As String)
  122.       Helpstr = Command + "="
  123.       If Buff(1) < 10 Then Helpstr = Helpstr + "0"
  124.        Helpstr = Helpstr + Str(buff(1)) + "-"
  125.       If Buff(2) < 10 Then Helpstr = Helpstr + "0"
  126.        Helpstr = Helpstr + Str(buff(2)) + "-"
  127.       If Buff(3) < 10 Then Helpstr = Helpstr + "0"
  128.        Helpstr = Helpstr + Str(buff(3))
  129.         Print Helpstr
  130.     End Sub
  131.  
  132.     Function Find(byval Command As String)as Byte
  133.  
  134.       Find = 0 : Helpb = Instr(t_str , Command)                 'szukaj wyrażenia
  135.  
  136.         If Helpb > 0 Then
  137.           Helpb = Helpb + 3
  138.           Helpstr = Mid(t_str , Helpb , 1)
  139.           Select Case Helpstr
  140.            Case "=" : Find = 1
  141.            Case "?" : Find = 2
  142.           End Select
  143.         End If
  144.  
  145.     End Function
  146.  
  147.     Sub Get_three_values()
  148.  
  149.      'in Helpb stored position of the found command
  150.      '             format TIM=23-05-00
  151.       Incr Helpb
  152.        Helpstr = Mid(t_str , Helpb , 2)
  153.        Char = Val(helpstr)
  154.        If Err = 0 Then One = Char
  155.       Helpb = Helpb + 3
  156.        Helpstr = Mid(t_str , Helpb , 2)
  157.        Char = Val(helpstr)
  158.        If Err = 0 Then Two = Char
  159.       Helpb = Helpb + 3
  160.        Helpstr = Mid(t_str , Helpb , 2)
  161.        Char = Val(helpstr)
  162.        If Err = 0 Then Three = Char
  163.  
  164.  
  165.     End Sub
  166.  
  167.  
  168.     L = Read_eeprom(lampka)
  169.  
  170.     Enable Interrupts
  171.  
  172.     ' ==============GŁÓWNA PĘTLA=================
  173.     Do
  174.  
  175.        'co sekunde
  176.        If Tifr.ocf1a = 1 Then                                   ' jesli uplynela sekunda (te flage ustawia Timer)
  177.         Tifr.ocf1a = 1                                          ' skasuj flage by w petli dokonywalo sie to tylko raz na 1s
  178.          Refresh = 1
  179.  
  180.         If Cmd_timeout > 0 Then
  181.          Decr Cmd_timeout
  182.           If Cmd_timeout = 0 Then T_str = ""
  183.         End If
  184.        End If
  185.  
  186.        If 0 < Ischarwaiting() Then
  187.  
  188.  
  189.           Char = Inkey()
  190.  
  191.           Select Case Char
  192.            Case 10
  193.            Case 13 : Got_str = 1
  194.            Case Else
  195.             T_str = T_str + Chr(char)
  196.           End Select
  197.  
  198.           If Len(t_str) > 24 Then Got_str = 1
  199.  
  200.           If Got_str = 1 Then
  201.  
  202.             Option = Find( "ATL")
  203.  
  204.              Select Case Option
  205.               Case 1
  206.                Call Get_three_values()
  207.                If Stare_l <> One Then
  208.                 Stare_l = One
  209.                 L = One
  210.                  Call Write_eeprom(lampka , L)
  211.                End If
  212.  
  213.              End Select
  214.  
  215.             Option = Find( "ATO")
  216.  
  217.              Select Case Option
  218.               Case 1
  219.                Call Get_three_values()
  220.                 Buff(1) = One
  221.                 Buff(2) = Two
  222.                 Buff(3) = Three
  223.                  Call Write_ee(olej)
  224.               Case 2
  225.                Call Read_ee(olej)
  226.                 Call Send_answear( "ATO")
  227.              End Select
  228.  
  229.             Option = Find( "ATP")
  230.  
  231.              Select Case Option
  232.               Case 1
  233.                Call Get_three_values()
  234.                 Buff(1) = One
  235.                 Buff(2) = Two
  236.                 Buff(3) = Three
  237.                  Call Write_ee(przeglad)
  238.               Case 2
  239.                Call Read_ee(przeglad)
  240.                 Call Send_answear( "ATP")
  241.              End Select
  242.  
  243.  
  244.             Option = Find( "ATU")
  245.  
  246.              Select Case Option
  247.               Case 1
  248.                Call Get_three_values()
  249.                 Buff(1) = One
  250.                 Buff(2) = Two
  251.                 Buff(3) = Three
  252.                  Call Write_ee(polisa)
  253.               Case 2
  254.                Call Read_ee(polisa)
  255.                 Call Send_answear( "ATU")
  256.              End Select
  257.  
  258.  
  259.             Option = Find( "TIM")
  260.  
  261.              If Option = 1 Then
  262.               Call Get_three_values()
  263.                Hour = One
  264.                Minute = Two
  265.                Second = Three
  266.                 Blad = Pcf8583_storetime(second , Minute , Hour , Day , Month , Year)
  267.              End If
  268.  
  269.                        Option = Find( "DAT")
  270.  
  271.              If Option = 1 Then
  272.               Call Get_three_values()
  273.                Day = One
  274.                Month = Two
  275.                Year = Three
  276.                 Blad = Pcf8583_storetime(second , Minute , Hour , Day , Month , Year)
  277.              End If
  278.  
  279.  
  280.  
  281.             Got_str = 0
  282.           Else
  283.            Cmd_timeout = 2
  284.           End If
  285.  
  286.        End If
  287.  
  288.  
  289.  
  290.        If Refresh = 1 Then                                        'odswiezanie co sekunde albo na żądanie
  291.  
  292.           Select Case Menu
  293.  
  294.              Case 0
  295.               '==========GŁÓWNY EKRAN Z GODZINĄ I DATĄ==============
  296.  
  297.                 Blad = Pcf8583_gettime()               ' odczytaj godzinę i date z układu PCF8583 , funkcja zwraca kod błędu
  298.                 If Blad = 2 Then                       ' jeżeli uszkodzona data
  299.                    Locate 1 , 1 : Lcd "   SET  CLOCK   "  ' wyświetl komunikat
  300.                    Locate 2 , 1 : Lcd Spc(20)
  301.                 Elseif Blad = 1 Then                   ' jeżeli błąd magistrali I2C
  302.                    Locate 1 , 1 : Lcd "    E R R O R   "  ' wyświetl komunikat
  303.                    Lcd Spc(11)
  304.                    Locate 2 , 1 : Lcd "   B U S  I2C   "
  305.                 Elseif Blad = 0 Then                   ' jeżeli prawidłowo odczytane dane
  306.                    Call Displaytime()                     ' wyświetl zegar
  307.                 End If
  308.  
  309.              Case 1
  310.               '=========EKRAN Z TEMPERATURĄ IN/OUT=================
  311.                 Call Displaytemp()
  312.  
  313.              Case 2
  314.               '=========EKRAN Z POMIAREM NAPIĘCIA POKŁADOWEGO==============
  315.                 Call Displayvolt()
  316.  
  317.           End Select
  318.  
  319.  
  320.           Refresh = 0
  321.        End If
  322.  
  323.        Debounce F1 , 0 , Menu_sub , Sub  ' Każde naciśnięcie przycisku F1 powoduje przejscie do kolejnego ekranu
  324.  
  325.  
  326.        If Motor = 1 Then Gosub Uspij                            ' Jeśłi silnik wyłączony, to idź do procedury Usypiania
  327.  
  328.        Call Display_led_glaze()   ' Sterowanie kontrolką gołoledzi
  329.  
  330.  
  331.  
  332.     Loop
  333.     End
  334.  
  335.  
  336.     ' ===============KONIEC GŁÓWNEJ PĘTLI=========================
  337.  
  338.     $include "PCF8583.bas"
  339.     $include "DS18B20.bas"
  340.     $include "Volt.bas"
  341.  
  342.  
  343.  
  344.     ' Przewijanie ekranów
  345.     Menu_sub:
  346.      Incr Menu : If Menu > 2 Then Menu = 0
  347.        Cls : Refresh = 1
  348.     Return
  349.  
  350.      ' ======================Procedura stanu uśpienia gdy silnik wyłączony=====================================
  351.     Uspij:
  352.        Cls
  353.        Motor = 1
  354.        Do
  355.           Led_glaze = INT_PCF
  356.  
  357.           If Motor = 1 then Display off : Podswietlenie = 0  ' Jeśli silnik wyłączony, to wyłącz LCD i podświetlenie
  358.  
  359.         'Led_glaze = 1 ' Kontrolka gołoledzi wyłączona
  360.               'end if
  361.           If Motor = 0 then ' Jeśli silnik włączony, to:
  362.  
  363.            ' ########################## Odpowiada za opóźnienie 5 sekund włączenia LCD ############################
  364.              If Int_pcf = 0 Then      'jeśli PCF ustalił stan niski
  365.                 Lock = 1                'to zapamietaj, ustaw flage
  366.              Else                     'jesli PCF ustawil już stan wysoki
  367.                 If Lock = 1 Then        'a byl wczesniej stan niski (flaga)
  368.                    Lock = 0               'skasuj flage do czasu kolejnego niskiego stanu
  369.                    Incr Licznik          'tylko raz na zmiane stanu zwiekszamy licznik
  370.                    If Licznik = 5 Then   ' jeśli licznik osiągnął wartość 5 (5sekund), to
  371.                       Licznik = 0          ' zeruj licznik
  372.                       Jest_5_impulsow = 1 'przejdź do włączenia podświetlenia
  373.                    End If
  374.                 End If
  375.              End If
  376.              If Jest_5_impulsow = 1 Then
  377.                 Jest_5_impulsow = 0
  378.             ' ######################## Koniec części opóźniającej włączenie LCD ###################################
  379.  
  380.                 Podswietlenie = 1 ' włącz podświetlenie
  381.                 Display on        ' włącz wyswietlacz
  382.                 cls               ' wyczyść wyswietlacz
  383.               ' Wyczyść informacje zgromadzone w Buforze UART
  384.                 return            ' wracaj do głównego programu
  385.              end if
  386.           end if
  387.              'end if
  388.        Loop
  389.  
PCF8583.BAS
  1. $nocompile
  2.  
  3.  
  4.  
  5. '-------------------------------------------------------------------------------
  6.  
  7. Sub Displaytime()
  8.  
  9.    Locate 1 , 1          ' <<<<<<<<-ustaw sobie gdzie ma wyświetlać
  10.  
  11.   If Hour < 10 Then Lcd "0" : Lcd Hour ; ":"
  12.   If Minute < 10 Then Lcd "0" : Lcd Minute ; ":"
  13.   If Second < 10 Then Lcd "0" : Lcd Second
  14.  
  15.    Lcd Spc(8)            ' 8 spacji
  16.  
  17.  
  18.  
  19.    Locate 2 , 2          ' <<<<<<<<-ustaw sobie gdzie ma wyświetlać
  20.  
  21.    Lcd Lookupstr(weekday , Weekdays) ; " "
  22.    If Day < 10 Then Lcd "0" : Lcd Day ; "-"
  23.    If Month < 10 Then Lcd "0" : Lcd Month ; "-" ; Year
  24.    'Lcd Spc(8)                                               ' 8 spacji
  25.  
  26.  
  27. End Sub
  28.  
  29. Weekdays:
  30.  
  31.     Data "Nie" , "Pon" , "Wto" , "Sro" , "Czw" , "Pt " , "Sob"
  32.  
  33. '-------------------------------------------------------------------------------
  34.  
  35. Pobierz_dni:
  36.  
  37.     Ilosc_dni = Lookup(month , Dni_w_miesiacu)
  38.     Rok_przestepny = Year Mod 4
  39.     If Rok_przestepny = 0 And Month = 2 Then       ' jeżeli rok przestępny i luty
  40.         Ilosc_dni = 29   ' to luty ma 29 dni
  41.     End If
  42.     If Day > Ilosc_dni Then Day = Ilosc_dni       ' zabezpieczenie
  43.  
  44. Return
  45.  
  46. Dni_w_miesiacu:
  47.  
  48.     Data 0 , 31 , 28 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31
  49.  
  50. '-------------------------------------------------------------------------------
  51.  
  52.  
  53.  
  54.  
  55.  
  56. '*******************************************************************************
  57. '*
  58. '*   plik:    PCF8583.bas
  59. '*   wersja:  1.0
  60. '*
  61. '*   autor:   Tomasz Sadzikowski (mundi1970@gmail.com)
  62. '*   data:    24.01.2013
  63. '*
  64. '*   kompilator: BASCOM Version 2.0.7.6.001
  65. '*
  66. '*   UWAGA!!! funkcje wykorzystują 7 bajtów pamięci ram układu PCF8583
  67. '*   Od adresu 0x10 zaczyna się 240 bajtów wolnej pamięci ram. Pierwsze
  68. '*   7 bajtów wykorzystane, pozostała część jest wolna.
  69. '*
  70. '*   UWAGA!!! zmienne  globalne Hour (byte), Minute (byte), Second (byte),
  71. '*   Day (byte), Month (byte), Year (word), Weekday (byte), nie są zdefiniowane
  72. '*
  73. '*   UWAGA!!! plik Config_PCF8583.bas jest powiązany z plikiem PCF8583.bas
  74. '*   Sposób dołączania plików do własnego programu:
  75. '*
  76. '*      $include "Config_PCF8583.bas"
  77. '*
  78. '*      Dim ....
  79. '*
  80. '*      Do
  81. '*      .......
  82. '*      Loop
  83. '*      End
  84. '*
  85. '*      $include "PCF8583.bas"
  86. '*
  87. '*******************************************************************************
  88.  
  89.  
  90. ' Funkcja odczytuje godzinę i datę z układ PCF8583 i zapisuje w zmiennych
  91. ' globalnych:  Hour (byte), Minute (byte),  Second (byte), Day (byte),
  92. ' Month (byte), Year (word), Weekday (byte).
  93. ' funkcja zwraca:
  94. ' 0 - ok
  95. ' 1 - bład magistrali I2C
  96. ' 2 - uszkodzone dane w pamięci RAM układu PCF8583 (dane potrzebne do obliczenia aktualnego roku)
  97.  
  98. Function Pcf8583_gettime() As Byte
  99.  
  100.    Local Temp_b As Byte , Error As Byte
  101.  
  102.    Error = Pcf8583_read(rtc_bufor(_base + Pcf8583_seconds) , Pcf8583_seconds , 5)       ' odczytaj 5 bajtów od adresu 0x02, i zapisz do tablicy zaczynającej się od rtc_seconds (rtc_bufor(3))
  103.    If Error = 0 Then     ' jeżeli nie było błędu
  104.       Error = Pcf8583_read(pcf8583_dane_bufor(_base) , Pcf8583_free_ram , 7)       ' odczytaj 7 bajtów od adresu 0x10 (dec 16), i zapisz do tablicy zaczynającej się od pcf8583_dane_bufor(1)
  105.       If Error = 0 Then  ' jeżeli nie było błędu
  106.          Error = Pcf8583_sprawdz_dane()       ' sprawdź czy dane w pamięci RAM układu PCF8583 nie są uszkodzone
  107.          If Error = 0 Then       ' jeżeli nie było błędu
  108.  
  109.             Second = Makedec(rtc_seconds)       ' sekundy
  110.             Minute = Makedec(rtc_minutes)       ' minuty
  111.             Hour = Makedec(rtc_hours)       ' godziny
  112.  
  113.             Temp_b = Rtc_year_date       ' rok
  114.             Shift Temp_b , Right , 6
  115.             Temp_b = Makedec(temp_b)
  116.             Year = Pcf8583_kalendarz_baza + Temp_b       '  baza + wartość kalendarza czteroletniego
  117.  
  118.             If Temp_b <> Pcf8583_year_old Then       ' jeżeli zmienił się rok
  119.                If Temp_b = 0 And Pcf8583_year_old = 3 Then       ' jeżeli skończył się kalendarz czteroletni
  120.                   Year = Year + 4       ' zmień bazę kalendarza
  121.                End If
  122.                Error = Pcf8583_store_year(year)       ' zapisz dane o aktualnym roku w układzie PCF8583
  123.             End If
  124.  
  125.             Temp_b = Rtc_year_date And &B0011_1111       ' dzień
  126.             Day = Makedec(temp_b)
  127.  
  128.             Temp_b = Rtc_weekdays_months       ' dzień tygodnia
  129.             Shift Temp_b , Right , 5
  130.             Weekday = Makedec(temp_b)
  131.  
  132.             Temp_b = Rtc_weekdays_months And &B0001_1111       ' miesiąc
  133.             Month = Makedec(temp_b)
  134.          Else
  135.            Error = 2     ' 2 - uszkodzone dane w pamięci RAM
  136.          End If
  137.       End If
  138.    End If
  139.  
  140.    Pcf8583_gettime = Error       ' funkcja zwraca 0 - ok, 1 - błąd I2C, 2 - uszkodzone dane w pamięci RAM
  141.  
  142. End Function
  143.  
  144. '-------------------------------------------------------------------------------
  145. ' Funkcja zapisuje godzinę i datę do układu PCF8583. Dzień tygodnia jest obliczany
  146. ' automatycznie na podstawie daty.
  147. ' wejście: sekundy, minuty, godziny, dzień, miesiąc i rok
  148. ' funkcja zwraca:
  149. ' 0 - ok
  150. ' 1 - błąd I2C
  151.  
  152. Function Pcf8583_storetime(byval S As Byte , Byval M As Byte , Byval H As Byte , Byval D As Byte , Byval Mm As Byte , Byval Y As Word) As Byte
  153.  
  154.    Local Temp_b As Byte , Error As Byte
  155.  
  156.    Rtc_seconds = Makebcd(s)       ' sekundy
  157.    Rtc_minutes = Makebcd(m)       ' minuty
  158.    Rtc_hours = Makebcd(h)       ' godziny
  159.  
  160.    Rtc_year_date = Makebcd(d)       ' dzień i rok
  161.    Temp_b = Y Mod 4
  162.    Temp_b = Makebcd(temp_b)
  163.    Shift Temp_b , Left , 6
  164.    Rtc_year_date = Rtc_year_date Or Temp_b
  165.  
  166.    Rtc_weekdays_months = Makebcd(mm)       ' dzień tygodnia i miesiąc
  167.    Temp_b = Oblicz_dzien_tygodnia(d , Mm , Y)       ' na podstawie daty oblicz dzień tygodnia
  168.    Temp_b = Makebcd(temp_b)
  169.    Shift Temp_b , Left , 5
  170.    Rtc_weekdays_months = Rtc_weekdays_months Or Temp_b
  171.  
  172.    Error = Pcf8583_write(rtc_bufor(_base + Pcf8583_seconds) , Pcf8583_seconds , 5)       ' zapisz 5 bajtów od adresu 0x02, dane pobierz z tablicy zaczynającej się od rtc_bufor(3)
  173.  
  174.    If Error = 0 Then     ' jeżeli nie był błędu
  175.       Error = Pcf8583_store_year(y)       ' zapisz dane o aktualnym roku w układzie PCF8583
  176.    End If
  177.  
  178.    Pcf8583_storetime = Error       ' funkcja zwraca 0 - ok, 1 - błąd I2C
  179.  
  180. End Function
  181.  
  182. '-------------------------------------------------------------------------------
  183.  
  184. ' Funkcja odczytuje określoną ilość danych z układu Pcf8583.
  185. ' wejście:
  186. ' bufor - tablica w której mają być zapisane dane.
  187. ' adres - adres ram układu Pcf8583 od którego zaczyna się odczyt
  188. ' ilosc_bajtow - ilość danych do odczytu
  189. ' funkcja zwraca:
  190. ' 0 = ok, 1 = błąd I2C
  191.  
  192. Function Pcf8583_read(byref Bufor()as Byte , Byval Adres As Byte , Byval Ilosc_bajtow As Byte) As Byte
  193.  
  194.    Local Dana As Byte , Index As Byte , Pozycja As Byte
  195.  
  196.    Index = 1
  197.    Pozycja = _base       ' UWAGA!!! Jeżeli Config Base = 0 to chyba powinno być :) Pozycja = 0
  198.  
  199.    I2cstart
  200.    If Err = 0 Then       ' sprawdź czy wystąpił błąd
  201.       I2cwbyte Pcf8583w  ' wyślij adres układu Pcf8583 tryb zapis
  202.       If Err = 0 Then    ' sprawdź czy wystąpił błąd
  203.          I2cwbyte Adres  ' adres ram w Pcf8583 od którego zacznie się odczyt
  204.          If Err = 0 Then ' sprawdź czy wystąpił błąd
  205.             I2cstart
  206.             I2cwbyte Pcf8583r       ' wyślij adres układu Pcf8583 tryb odczyt
  207.             If Err = 0 Then       ' sprawdź czy wystąpił błąd
  208.                Do
  209.                   If Index = Ilosc_bajtow Then       ' jeżeli ostatni bajt to
  210.                      I2crbyte Dana , Nack       ' odczytaj bajt z Pcf8583  (NACK)
  211.                   Else   ' jeżeli nie to
  212.                      I2crbyte Dana , Ack       ' odczytaj bajt z Pcf8583 (ACK)
  213.                   End If ' odczytaj daną
  214.                   Bufor(pozycja) = Dana       ' zapisz w tablicy
  215.                   Incr Pozycja       ' zwiększ Pozycje o 1
  216.                   Incr Index       ' zwiększ Index o 1
  217.                Loop Until Err = 1 Or Index > Ilosc_bajtow       ' opuść pętle jeżeli pobrano wszystkie dane lub wystąpił błąd
  218.             End If
  219.          End If
  220.       End If
  221.       I2cstop
  222.    End If
  223.  
  224.    Pcf8583_read = Err    ' zwracany kod
  225.  
  226. End Function
  227.  
  228. '-------------------------------------------------------------------------------
  229. ' Funkcja zapisuje określoną ilość danych do układu Pcf8583.
  230. ' wejście:
  231. ' bufor - tablica z której mają być pobierane dane do zapisu
  232. ' adres - adres ram układu Pcf8583 od którego zaczyna się zapis
  233. ' ilosc_bajtow - ilość danych do zapisu
  234. ' funkcja zwraca:
  235. ' 0 = ok, 1 = błąd I2C
  236.  
  237. Function Pcf8583_write(byref Bufor()as Byte , Byval Adres As Byte , Byval Ilosc_bajtow As Byte) As Byte
  238.  
  239.    Local Dana As Byte , Index As Byte , Pozycja As Byte
  240.  
  241.    Index = 1
  242.    Pozycja = _base       ' UWAGA!!! Jeżeli Config Base = 0 to chyba powinno być :) Pozycja = 0
  243.  
  244.    I2cstart
  245.    If Err = 0 Then       ' sprawdź czy wystąpił błąd
  246.       I2cwbyte Pcf8583w  ' wyślij adres układu Pcf8583 tryb zapis
  247.       If Err = 0 Then    ' sprawdź czy wystąpił błąd
  248.          I2cwbyte Adres  ' wyślij adres ram w Pcf8583 od którego zacznie się zapis
  249.          If Err = 0 Then ' sprawdź czy wystąpił błąd
  250.             Do
  251.                Dana = Bufor(pozycja)       ' odczytaj daną z tablicy
  252.                I2cwbyte Dana       ' i wyślij dane do Pcf8583
  253.                Incr Pozycja       ' zwiększ Pozycje o 1
  254.                Incr Index       ' zwiększ Index o 1
  255.             Loop Until Err = 1 Or Index > Ilosc_bajtow       ' opuść pętle jeżeli zapisano wszystkie dane lub wystąpił błąd
  256.          End If
  257.       End If
  258.       I2cstop
  259.    End If
  260.  
  261.    Pcf8583_write = Err   ' zwracany kod
  262.  
  263. End Function
  264.  
  265. '-------------------------------------------------------------------------------
  266. ' Funkcja zapisuje w PCF8583 dane potrzebne do obliczenia aktualnym roku
  267. ' (PCF8583 posiada tylko czteroletni kalendarz). Zapisywane są takie dane:
  268. ' ID (word), baza kalendarza (word), wartość kalendarza czteroletniego (byte)
  269. ' i suma kontrolna (word) - całość 7 bajtów
  270. ' wejście: - rok (word)
  271. ' funkcja zwraca:  0 - ok, 1 - błąd I2C
  272.  
  273. Function Pcf8583_store_year(byval Year As Word) As Byte
  274.  
  275.    Local Temp_b As Byte
  276.  
  277.    Pcf8583_data_id = Rok_id       ' ID &H55AA
  278.    Temp_b = Year Mod 4
  279.    Pcf8583_year_old = Makebcd(temp_b)       ' zapamiętaj wartość kalendarza czteroletniego (0-3)
  280.    Pcf8583_kalendarz_baza = Year - Temp_b       ' 2000, 2004, 2008 .....
  281.    Pcf8583_crc16 = Crc16(pcf8583_dane_bufor(_base) , 5)       ' oblicz sumę kontrolną danych
  282.  
  283.    Pcf8583_store_year = Pcf8583_write(pcf8583_dane_bufor(_base) , Pcf8583_free_ram , 7)       ' zapisz 7 bajtów od adresu 0x10 (dec 16), dane pobierz z tablicy zaczynającej się od pcf8583_dane_bufor(1)
  284.                                                             ' funkcja zwraca 0 - ok, 1 - błąd I2C
  285. End Function
  286.  
  287. '-------------------------------------------------------------------------------
  288. ' Funkcja sprawdza czy dane potrzebne do obliczenia aktualnego roku,
  289. ' zawarte w tablicy globalnej Pcf8583_dane_bufor() nie są uszkodzone.
  290. ' Sprawdzany jest id i suma kontrolna. Dane do bufora należy wcześniej
  291. ' odczytać funkcją Pcf8583_read().
  292. ' funkcja zwraca: 0 = ok, 1 = błąd
  293.  
  294. Function Pcf8583_sprawdz_dane() As Byte
  295.  
  296.    Local Crc As Word
  297.  
  298.    Pcf8583_sprawdz_dane = 1       ' błąd dane uszkodzone
  299.  
  300.    Crc = Crc16(pcf8583_dane_bufor(_base) , 5)       ' oblicz sumę kontrolną Pcf8583_data_id,  Pcf8583_kalendarz_baza i Pcf8583_year_old
  301.    If Crc = Pcf8583_crc16 Then       ' sprawdź czy suma kontrolna się zgadza
  302.       If Pcf8583_data_id = Rok_id Then       ' sprawdź czy id (&H55AA) się zgadza
  303.          Pcf8583_sprawdz_dane = 0       ' brak błędu
  304.       End If
  305.    End If
  306.  
  307. End Function
  308.  
  309. '-------------------------------------------------------------------------------
  310. ' Funkcja oblicza na podstawie daty jaki jest dzień tygodnia. Funkcje napisano
  311. ' na podstawie przykładu w Pascalu ze strony http://pl.wikipedia.org/wiki/Kalendarz_wieczny
  312. '
  313. ' Wejście:
  314. ' - dzien , miesiąc , rok
  315. '
  316. ' Wyjście:
  317. ' 0 - niedziela
  318. ' 1 - poniedziałek
  319. ' 2 - wtorek
  320. ' 3 - środa
  321. ' 4 - czwartek
  322. ' 5 - piątek
  323. ' 6 - sobota
  324.  
  325. Function Oblicz_dzien_tygodnia(day As Byte , Month As Byte , Year As Word) As Byte
  326.  
  327.    Local M As Integer , C As Integer , D As Integer , N As Integer , Temp As Integer
  328.  
  329.    M = Month + 9 : M = M Mod 12 : M = M + 1 : If M > 10 Then Year = Year - 1
  330.    C = Year \ 100 : D = Year Mod 100
  331.    N = 13 * M : N = N - 1 : N = N \ 5 : N = N + D : Temp = D \ 4
  332.    N = N + Temp : Temp = C \ 4 : N = N + Temp : Temp = 5 * C : N = N + Temp
  333.    N = N + Day : N = N Mod 7
  334.  
  335.    Oblicz_dzien_tygodnia = N
  336.  
  337. End Function
  338.  
  339. '----------------------------------------------------------
Config_PCF8583.bas
  1. $nocompile
  2.  
  3.  
  4. ' Konfiguracja szyny I2C
  5. Config Scl = Portc.0
  6. Config Sda = Portc.1
  7. I2cinit
  8.  
  9.  Config Portb.7 = Output : Portb.7 = 1 : Podswietlenie Alias Portb.7       'Konfiguracja podswietlenia
  10.  Config Portd.3 = Output : Portd.3 = 1 : Led Alias Portd.3       'Konfiguracja LED
  11.  
  12. '-------------------------------------------------------------------------------
  13. Declare Sub Displaytime()
  14. '-------------------------------------------------------------------------------
  15. ' zmienne globalne
  16. Dim Second As Byte
  17. Dim Minute As Byte
  18. Dim Hour As Byte
  19. Dim Day As Byte
  20. Dim Month As Byte
  21. Dim Year As Word
  22. Dim Weekday As Byte
  23.  
  24. Dim Blad As Byte
  25. Dim Ilosc_dni As Byte
  26. Dim Rok_przestepny As Byte
  27.  
  28. '### TYMCZASOWE USTAWIANIE ZEGARA ###
  29. ' początkowe wartości
  30. ' Minute = 16
  31. ' Hour = 22
  32. ' Day = 01
  33. ' Month = 5
  34. ' Year = 2015
  35. ' Blad = Pcf8583_storetime(second , Minute , Hour , Day , Month , Year)
  36. '### ----------------------------------
  37.  
  38.  
  39. '*******************************************************************************
  40. '*
  41. '*   plik:    Config_PCF8583.bas
  42. '*   wersja:  1.0
  43. '*
  44. '*   autor:   Tomasz Sadzikowski (mundi1970@gmail.com)
  45. '*   data:    24.01.2013
  46. '*
  47. '*   kompilator: BASCOM Version 2.0.7.6.001
  48. '*
  49. '*   UWAGA!!! funkcje wykorzystują 7 bajtów pamięci ram układu PCF8583
  50. '*   Od adresu 0x10 zaczyna się 240 bajtów wolnej pamięci ram. Pierwsze
  51. '*   7 bajtów wykorzystane, pozostała część jest wolna.
  52. '*
  53. '*   UWAGA!!! zmienne  globalne Hour (byte), Minute (byte), Second (byte),
  54. '*   Day (byte), Month (byte), Year (word), Weekday (byte), nie są zdefiniowane
  55. '*
  56. '*   UWAGA!!! plik Config_PCF8583.bas jest powiązany z plikiem PCF8583.bas
  57. '*   Sposób dołączania plików do własnego programu:
  58. '*
  59. '*      $include "Config_PCF8583.bas"
  60. '*
  61. '*      Dim ....
  62. '*
  63. '*      Do
  64. '*      .......
  65. '*      Loop
  66. '*      End
  67. '*
  68. '*      $include "PCF8583.bas"
  69. '*
  70. '*******************************************************************************
  71.  
  72.  
  73. ' dokumentacja układu PCF8583 dostępna na stronie :
  74. ' http://www.nxp.com/documents/data_sheet/PCF8583.pdf
  75. ' http://ics.nxp.com/support/documents/interface/pdf/user.manual.real.time.clocks.pdf
  76.  
  77.  
  78. #if _build < 20000
  79.     Const _base = 1
  80. #endif
  81.  
  82.  
  83. '-------------------------------------------------------------------------------
  84. ' stałe
  85.  
  86. ' konfiguracja bufora -> jeżeli tylko bufor dla zegara to 0, jeżeli bufor dla zegara i alarmu to 1
  87. ' domyślnie 0 - bufor tylko dla zegara
  88.  
  89. Const _clock_alarm = 0
  90.  
  91. ' adresy układu PCF8583
  92. ' jeżeli noga A0 układ PCF8583 jest podłączony do GND to:
  93. ' adres do odczytu = &HA1
  94. ' adres do zapisu = &HA0
  95. ' jeżeli noga A0 układ PCF8583 jest podłączony do VCC to:
  96. ' adres do odczytu = &HA3
  97. ' adres do zapisu = = &HA2
  98.  
  99. Const Pcf8583r = &HA1
  100. Const Pcf8583w = &HA0
  101.  
  102. ' długość bufora
  103.  
  104. #if _clock_alarm = 0
  105.    Const Pcf8583_bufor_len = 8
  106. #else
  107.    Const Pcf8583_bufor_len = 16
  108. #endif
  109.  
  110. ' adresy rejestrów
  111.  
  112. ' mapa pamięci układu PCF8583 - opis na str. 8
  113. ' od adresu 16 (hex &H10) jest wolne 240 (hex &HF0) bajtów pamięci RAM
  114.  
  115. Const Pcf8583_control = 0
  116. Const Pcf8583_100th_of_a_second = 1
  117. Const Pcf8583_seconds = 2
  118. Const Pcf8583_minutes = 3
  119. Const Pcf8583_hours = 4
  120. Const Pcf8583_year_date = 5
  121. Const Pcf8583_weekdays_months = 6
  122. Const Pcf8583_timer = 7
  123.  
  124. #if _clock_alarm = 1
  125.  
  126.    Const Pcf8583_alarm_control = 8
  127.    Const Pcf8583_alarm_100th_of_a_second = 9
  128.    Const Pcf8583_alarm_seconds = 10
  129.    Const Pcf8583_alarm_minutes = 11
  130.    Const Pcf8583_alarm_hours = 12
  131.    Const Pcf8583_alarm_date = 13
  132.    Const Pcf8583_alarm_months = 14
  133.    Const Pcf8583_alarm_timer = 15
  134.  
  135. #endif
  136.  
  137. Const Pcf8583_free_ram = 16       ' od tego adresu jest 240 bajtów wolnego ramu
  138.  
  139. ' ID danych
  140.  
  141. Const Rok_id = &H55AA    ' przypadkowa wartość która wpadła mi do łba :)
  142.  
  143.  
  144. '-------------------------------------------------------------------------------
  145. ' zmienne globalne
  146.  
  147.    Dim Rtc_bufor(pcf8583_bufor_len) As Byte
  148.  
  149.    Dim Rtc_control As Byte At Rtc_bufor + Pcf8583_control Overlay       ' Control and status register - opis poszczególnych bitów na str. 6
  150.    Dim Rtc_100th_of_a_second As Byte At Rtc_bufor + Pcf8583_100th_of_a_second Overlay
  151.    Dim Rtc_seconds As Byte At Rtc_bufor + Pcf8583_seconds Overlay
  152.    Dim Rtc_minutes As Byte At Rtc_bufor + Pcf8583_minutes Overlay
  153.    Dim Rtc_hours As Byte At Rtc_bufor + Pcf8583_hours Overlay
  154.    Dim Rtc_year_date As Byte At Rtc_bufor + Pcf8583_year_date Overlay
  155.    Dim Rtc_weekdays_months As Byte At Rtc_bufor + Pcf8583_weekdays_months Overlay
  156.    Dim Rtc_timer As Byte At Rtc_bufor + Pcf8583_timer Overlay
  157.  
  158. #if _clock_alarm = 1
  159.  
  160.    Dim Rtc_alarm_control As Byte At Rtc_bufor + Pcf8583_alarm_control Overlay       ' Alarm control registers, clock mode - opis poszczególnych bitów na str. 10
  161.    Dim Rtc_alarm_100th_of_a_second As Byte At Rtc_bufor + Pcf8583_alarm_100th_of_a_second Overlay
  162.    Dim Rtc_alarm_seconds As Byte At Rtc_bufor + Pcf8583_alarm_seconds Overlay
  163.    Dim Rtc_alarm_minutes As Byte At Rtc_bufor + Pcf8583_alarm_minutes Overlay
  164.    Dim Rtc_alarm_hours As Byte At Rtc_bufor + Pcf8583_alarm_hours Overlay
  165.    Dim Rtc_alarm_date As Byte At Rtc_bufor + Pcf8583_alarm_date Overlay
  166.    Dim Rtc_alarm_months As Byte At Rtc_bufor + Pcf8583_alarm_months Overlay
  167.    Dim Rtc_alarm_timer As Byte At Rtc_bufor + Pcf8583_alarm_timer Overlay
  168.  
  169. #endif
  170.  
  171. ' układ PCF8583 posiada czteroletni kalendarz, od adresu 16 (hex &H10) w pamięci układu
  172. ' będą zapisywane dane potrzebne do obliczenia aktualnego roku
  173. ' aktualny rok = kalendarz baza + wartość z czteroletniego kalendarza
  174.  
  175.    Dim Pcf8583_dane_bufor(7) As Byte
  176.  
  177.    Dim Pcf8583_data_id As Word At Pcf8583_dane_bufor Overlay       ' id danych &H55AA (word)
  178.    Dim Pcf8583_kalendarz_baza As Word At Pcf8583_dane_bufor + 2 Overlay       ' baza 2000, 2004, 2008 ... wielokrotność 4 letniego kalendarza (word)
  179.    Dim Pcf8583_year_old As Byte At Pcf8583_dane_bufor + 4 Overlay       ' stara wartość od 0 do 3 (byte) kalendarza czteroletniego (obliczona wartość z Pcf8583_year_date)
  180.    Dim Pcf8583_crc16 As Word At Pcf8583_dane_bufor + 5 Overlay       ' suma kontrolna (word) danych: id, kalendarz_baza i year_old (Pcf8583_crc16 = Crc16(Pcf8583_dane_bufor(1) , 5))
  181.  
  182. '-------------------------------------------------------------------------------
  183. ' deklaracje funkcji
  184.  
  185. ' Funkcja odczytuje godzinę i datę z układ PCF8583 i zapisuje w zmiennych
  186. ' globalnych:  Hour (byte), Minute (byte),  Second (byte), Day (byte),
  187. ' Month (byte), Year (word), Weekday (byte).
  188. ' funkcja zwraca:
  189. ' 0 - ok
  190. ' 1 - bład magistrali I2C
  191. ' 2 - uszkodzone dane w pamięci RAM układu PCF8583 (dane potrzebne do obliczenia aktualnego roku)
  192.  
  193. Declare Function Pcf8583_gettime() As Byte
  194.  
  195.  
  196. ' Funkcja zapisuje godzinę i datę do układu PCF8583. Dzień tygodnia jest obliczany
  197. ' automatycznie na podstawie daty.
  198. ' wejście: sekundy, minuty, godziny, dzień, miesiąc i rok
  199. ' funkcja zwraca:
  200. ' 0 - ok
  201. ' 1 - błąd I2C
  202.  
  203. Declare Function Pcf8583_storetime(byval S As Byte , Byval M As Byte , Byval H As Byte , Byval D As Byte , Byval Mm As Byte , Byval Y As Word) As Byte
  204.  
  205.  
  206. ' Funkcja odczytuje określoną ilość danych z układu Pcf8583.
  207. ' wejście:
  208. ' bufor - tablica w której mają być zapisane dane.
  209. ' adres - adres ram układu Pcf8583 od którego zaczyna się odczyt
  210. ' ilosc_bajtow - ilość danych do odczytu
  211. ' funkcja zwraca:
  212. ' 0 = ok, 1 = błąd I2C
  213.  
  214. #if _build < 20760
  215.    Declare Function Pcf8583_read(byref Bufor As Byte , Byval Adres As Byte , Byval Ilosc_bajtow As Byte) As Byte
  216. #else
  217.    Declare Function Pcf8583_read(byref Bufor() As Byte , Byval Adres As Byte , Byval Ilosc_bajtow As Byte) As Byte
  218. #endif
  219.  
  220. ' Funkcja zapisuje określoną ilość danych do układu Pcf8583.
  221. ' wejście:
  222. ' bufor - tablica z której mają być pobierane dane do zapisu
  223. ' adres - adres ram układu Pcf8583 od którego zaczyna się zapis
  224. ' ilosc_bajtow - ilość danych do zapisu
  225. ' funkcja zwraca:
  226. ' 0 = ok, 1 = błąd I2C
  227.  
  228. #if _build < 20760
  229.    Declare Function Pcf8583_write(byref Bufor As Byte , Byval Adres As Byte , Byval Ilosc_bajtow As Byte) As Byte
  230. #else
  231.    Declare Function Pcf8583_write(byref Bufor() As Byte , Byval Adres As Byte , Byval Ilosc_bajtow As Byte) As Byte
  232. #endif
  233.  
  234. ' Funkcja zapisuje w PCF8583 dane potrzebne do obliczenia aktualnym roku
  235. ' (PCF8583 posiada tylko czteroletni kalendarz). Zapisywane są takie dane:
  236. ' ID (word), baza kalendarza (word), wartość kalendarza czteroletniego (byte)
  237. ' i suma kontrolna (word) - całość 7 bajtów
  238. ' wejście: - rok (word)
  239. ' funkcja zwraca:  0 - ok, 1 - błąd I2C
  240.  
  241. Declare Function Pcf8583_store_year(byval Year As Word) As Byte
  242.  
  243.  
  244. ' Funkcja sprawdza czy dane potrzebne do obliczenia aktualnego roku,
  245. ' zawarte w tablicy globalnej Pcf8583_dane_bufor() nie są uszkodzone.
  246. ' Sprawdzany jest id i suma kontrolna. Dane do bufora należy wcześniej
  247. ' odczytać funkcją Pcf8583_read().
  248. ' funkcja zwraca: 0 = ok, 1 = błąd
  249.  
  250. Declare Function Pcf8583_sprawdz_dane() As Byte
  251.  
  252.  
  253. ' Funkcja oblicza na podstawie daty jaki jest dzień tygodnia. Funkcje napisano
  254. ' na podstawie przykładu w Pascalu ze strony http://pl.wikipedia.org/wiki/Kalendarz_wieczny
  255. '
  256. ' Wejście:
  257. ' - dzien , miesiąc , rok
  258. '
  259. ' Wyjście:
  260. ' 0 - niedziela
  261. ' 1 - poniedziałek
  262. ' 2 - wtorek
  263. ' 3 - środa
  264. ' 4 - czwartek
  265. ' 5 - piątek
  266. ' 6 - sobota
  267.  
  268. Declare Function Oblicz_dzien_tygodnia(day As Byte , Month As Byte , Year As Word) As Byte
  269.  
  270. '---------------------------------------------
Jeśli wysyłam czas z terminala Putty, w formacie jaki mi zaleciłeś- TIM=09:05:01, DAT=14-03-17, to wszystko działa poprawnie. Data również.
Jeśli nie ma opcji takiej, żeby to zmienić we wsadzie do procka, to w ostateczności zrobię w aplikacji na smartfona wprowadzanie czasu i daty ręcznie z klawiatury i będzie działać :)
Awatar użytkownika
Michał6201
Posty: 165
Rejestracja: 03 paź 2015, 20:07

Re: Problem z zapisem do eeprom więcej niż 2 zmiennych

Post autor: Michał6201 » 15 mar 2017, 14:23

Przemyślałem sprawę, pewnie trzeba byłoby przerabiać znów cały program, a i tak mi dużo pomogłeś, to nie będę wydziwiał i zrobię aplikację z ręcznym wprowadzaniem czasu i daty. Przecież tego nie będę ustawiał przy każdej jeździe samochodem. PCF8583 ma podtrzymywanie zasilania baterią, więc będzie ok.
Dziś dokończę resztę tej aplikacji i przetestuję zapis odczyt dat :)
Awatar użytkownika
niveasoft
Posty: 1313
Rejestracja: 17 sie 2015, 12:13
Kontakt:

Re: Problem z zapisem do eeprom więcej niż 2 zmiennych

Post autor: niveasoft » 15 mar 2017, 14:54

To nie jest jakieś skomplikowane tylko takie rzeczy wychodzą w praniu i wystarczy je załatać :D
Jeśli dobrze rozumiem to Aplikacja Androida pozwala sobie na skrócenie tylko pierwszego członu czyli usuwa tak zwane zero wiodące?
Jeśli już Minuty i Sekundy pozostawia w formacie 00:00 to można po prostu mierzyć długość otrzymanej komendy.
Długość 8 znaków to format 23:00:00 a długość 7 znaków to format 1:00:00 i jedna rzecz z głowy.

Można też zmusić aplikację androidową by "kiedy godzina < 10 To Nadawany_string = "0" + Nadawany_string

Rozwiązań tyle ilu programistów.

Radziłbym popracować nad rozwiązaniem niż pójście na łatwiznę bo trochę się napracowałem przerabiając ten kod bo myślałem o tym że zawsze można go rozwinąć. Natomiast odpuszczenie jakiegoś tematu kończy się potem kulawa aplikacją bez możliwości dalszego jej rozwinięcia.

Rozwiąż problem odbioru/zapisu a będziesz mógł zapisywać więcej danych :D ..i to nie tylko w tym projekcie ..myśl o następnych.

Żebym nie pisał sam to coś napisz a jak nie zadziała to pokaż i się pomyśli :D

Można też nauczyć Procesor wykrywania dwukropków lub rozdzielających minusów - to proste!
Awatar użytkownika
Michał6201
Posty: 165
Rejestracja: 03 paź 2015, 20:07

Re: Problem z zapisem do eeprom więcej niż 2 zmiennych

Post autor: Michał6201 » 15 mar 2017, 16:34

Wiem, że napracowałeś się nad poprawa tego kodu i z pewnością zajęło Ci to mnóstwo czasu.

Właśnie aplikacja zaczytując czas i datę z androida obcina wszystkie zera, i nie tylko obetnie zero w godzinie ale i minutach i sekundach, więc jeśli mamy godzinę: 09:05:02, to android podstawi w aplikacji taki format czasu: 9:5:2, więc tu mamy obcięte w sumie trzy zera. To samo tyczy się daty.

Spróbuję z tymi stringami w aplikacji, pokombinuję też z wsadem do Bascoma i jak coś to będę pisał na forum :D


..a tak na samym końcu to myślę że to nie Android tylko nieładnie napisałeś aplikację na niego jeśli wysyłasz string a nie ma zer wiodących.
Zrozumiałbym binarnie 1:2:30 ale string tego typu? To nie jest human interface :D
ODPOWIEDZ