Kanał - ATNEL tech-forum
Wszystkie działy
Najnowsze wątki



Teraz jest 29 mar 2024, o 02:12


Strefa czasowa: UTC + 1





Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 56 ]  Przejdź na stronę Poprzednia strona  1, 2
Autor Wiadomość
PostNapisane: 9 maja 2018, o 20:10 
Offline
Użytkownik

Dołączył(a): 18 cze 2015
Posty: 352
Pomógł: 0

Cześć Daro69
Nawet nie wiesz, jak się cieszę, że masz taki upór maniaka, jeśli chodzi o moje posty. Już tyle razy mi pomogłeś w innych tematach i to bardzo ważnych
dla mnie.....Nie wiem, czy przeczytałeś dokładnie poprzedni post, ale już wszystko ładnie się wczytuje z flash do ram i działa tak, jak w tablicach utworzonych w ram. Można by rzec, ze ten kawałek tematu jest zamknięty, ale być może widzisz małego chochlika, którego ja nie dostrzegam (pomimo, że wyświetlanie jest
prawidłowe od pierwszego znaku w tablicy do ostatniego i od nowa...). W takim razie jutro napiszę, jak ja interpretuję pętlę for, którą napisałem i może znajdę
chochlika ???. Składnię pętli rozumiem i jak ona działa, ale może logicznie źle napisałem te zakresy. Zestaw mam w pracy i nieraz mam trochę czasu na C.
Pozdrawiam.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 10 maja 2018, o 06:53 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 01 lis 2015
Posty: 1448
Lokalizacja: okolice Warszawa
Pomógł: 149

No dobra, to ja mam chochliki w oczach. ;)
Zinkrementuje do max wartości i wyjdzie z pętli,
Obsługując ja następnym razem, znowu zostanie zainicjowana wartością 0.
for(uint8_t zmienna=0 ; ...

Wysłane z mojego Lenovo K33a42 przy użyciu Tapatalka



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 10 maja 2018, o 07:25 
Offline
Użytkownik

Dołączył(a): 18 cze 2015
Posty: 352
Pomógł: 0

Witaj.
No to ok, ale jak już napisałem, że opiszę moją interpretację, to dokończę ;)
W tablicy mam zmienne od 48 do 122. 48=0 w tablicy, a 122=62 w tablicy. I teraz kod:

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Jeśli pozycja_do_edycji < 62, to zwiększaj, ponieważ musi dojść do te 62 (122 w tab.)
Ale jeśli osiągnie 63, to wyzeruj i od nowa...Co prawda w tablicy nie ma 63, ale jeśli dałem ==62, to 62 nie zdążyło się wyświetlić
i przeskakiwało na 0 w tab.
Być może z punktu logiki popełniam tu błąd i przy zastosowaniu podobnego toku myślenia, ale w innej sytuacji, a nie tylko wyświetlanie sobie literek miałbym zonka. Tutaj musiałby się może jeszcze ktoś wypowiedzieć. W tej konkretnej sytuacji
program zachowuje się zgodnie z tym, co zamierzałem. Jeszcze raz pozdrowionka.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 10 maja 2018, o 07:32 
Offline
Użytkownik

Dołączył(a): 25 lip 2013
Posty: 2561
Pomógł: 126

Poczytaj o pętli for.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 10 maja 2018, o 08:16 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 26 sty 2016
Posty: 1146
Lokalizacja: Kraków
Pomógł: 93

Robert_1967 napisał(a):
Jeśli pozycja_do_edycji < 62, to zwiększaj, ponieważ musi dojść do te 62 (122 w tab.)
Ale jeśli osiągnie 63, to wyzeruj i od nowa...Co prawda w tablicy nie ma 63, ale jeśli dałem ==62, to 62 nie zdążyło się wyświetlić
i przeskakiwało na 0 w tab.
Nie musisz sprawdzać warunku
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
Pętla for sama zadba o to, żeby nie udało się takiej wartości osiągnąć (tak, wiem, są pewne możliwości, ale nie na tym poziomie skomplikowania programu).
Krótka instrukcja działania pętli for:
1) jeżeli program napotka pętle for, wykonuje najpierw to, co jest przed pierwszym średnikiem. W tym przypadku, ustawi wartość zmiennej pozycja_do_edycji na 0
2) program sprawdzi to, co jest pomiędzy pierwszym i drugim średnikiem. Czyli sprawdzi, czy przypadkiem zmienna pozycja_do_edycji nie przekroczyła wartości 62. A tak przy okazji, wyświetla się 63. znak?
3) program wykona to, co jest po drugim średniku. Zazwyczaj jest to inkrementacja/dekrementacja zmiennej sterującej pętlą.
4) wykonuje się to, co jest wewnątrz pętli. I tu uwaga: jeżeli po drugim przecinku zapiszesz zmienna++, to operacje wykonają się na starej wartości zmiennej, przed zwiększeniem. Ale jeśli napiszesz ++zmienna, to najpierw zwiększy się wartość zmiennej, a później zostanie ona wzięta do obliczeń.
5) po wykonaniu wszystkich instrukcji pętli program wraca do punktu 2)



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 10 maja 2018, o 10:09 
Offline
Użytkownik

Dołączył(a): 18 cze 2015
Posty: 352
Pomógł: 0

Dzięki Marhef za chęć wyjaśnienia.

Ja czytałem oczywiście o pętli for i z książek Mirka i z netu. Niby rozumiałem, ale jak widzę, to w niektórych sytuacjach nie do
końca.

micky napisał(a):
A tak przy okazji, wyświetla się 63. znak?


O przy okazji wreszcie udało mi się wstawić cytat :) . Nie, nie wyświetla się, ponieważ w tablicy nie ma. Tu właśnie nie byłem
pewny, czy nie robię babola. Jednak okazuje się, że if jest zbędny, jak pisałeś.
Ja myślałem, że kiedy dojdzie do ostatniego znaku z tablicy, to ja muszę sam wyzerować zmienną i z tond ten if(pozycja_do_edycji ==63) pozycja_do_edycji = 0;. Nie wiedziałem, że się samo wyzeruje i zacznie od nowa...O ile słusznie prawię.

Teraz poprawiłem kod na taki i wyświetla mi się wszystko prawidłowo. Jedyne, z czym mam problem, to utworzenie własnej funkcji
lcd_char_P() z funkcji lcd_char(), jak sugerował kol. rskup, a żeby nie pisać za każdym razem pgm_read_byte...


Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Pozdrawiam. Robert.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 10 maja 2018, o 10:17 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 26 sty 2016
Posty: 1146
Lokalizacja: Kraków
Pomógł: 93

Robert_1967 napisał(a):
micky napisał(a):
A tak przy okazji, wyświetla się 63. znak?

O przy okazji wreszcie udało mi się wstawić cytat :)
Prawie ;) pomyliłeś nicki :P
Robert_1967 napisał(a):
Nie, nie wyświetla się, ponieważ w tablicy nie ma. Tu właśnie nie byłem pewny, czy nie robię babola.
Nie chce mi się liczyć, ile masz znaków w tablicy. To może inaczej: tych znaków jest 62 czy 63? Bo z taką pętlą, jaką masz, wyświetlą się 62 znaki, o indeksach od 0 do 61.
Pytam, bo nie wiem, czy dobrze zrozumiałem założenia



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 10 maja 2018, o 11:07 
Offline
Użytkownik

Dołączył(a): 18 cze 2015
Posty: 352
Pomógł: 0

Witaj Marhef
Mam dokładnie 62 naki, czyli wyświetla się od pozycji 0 do 61. Ale jeśli zrobiłbym w kodzie pozycja_do_edycji < 61; , to ostatni znak
(122) się nie wyświetla.

Marhef napisał(a):
Prawie ;) pomyliłeś nicki :P


A gdzie tam ???. Przecież to Ty pisałeś :lol: .

a tu nawiązywałem do kolegi rskup:

Robert_1967 napisał(a):
Jedyne, z czym mam problem, to utworzenie własnej funkcji
lcd_char_P() z funkcji lcd_char(), jak sugerował kol. rskup, a żeby nie pisać za każdym razem pgm_read_byte...


Pozdrawiam. Robert.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 10 maja 2018, o 11:37 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 26 sty 2016
Posty: 1146
Lokalizacja: Kraków
Pomógł: 93

Robert_1967 napisał(a):
Mam dokładnie 62 naki, czyli wyświetla się od pozycji 0 do 61. Ale jeśli zrobiłbym w kodzie pozycja_do_edycji < 61; , to ostatni znak (122) się nie wyświetla.
Właśnie tego nie mogłem załapać. Wydawało mi się, że piszesz o 63 znakach, stąd moje pytania



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 10 maja 2018, o 11:43 
Offline
Użytkownik

Dołączył(a): 18 cze 2015
Posty: 352
Pomógł: 0

Witaj Marhef
Już żeby do końca rozjaśnić, to we wcześniejszych postach w kodzie w pętli for była wartość 63, ale po przeczytaniu Twojego
posta wywaliłem z kodu ifa i pozbyłem się wartości 63. Pozdrawiam. Robert.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 10 maja 2018, o 18:09 
Offline
Użytkownik

Dołączył(a): 07 cze 2016
Posty: 563
Pomógł: 143

Zapewne niektórzy pomyślą, że czepiam się szczegółów, ale jednak czasami szczegóły są bardzo istotne.

Chciałbym nieco sprostować opis pętli for:
Marhef napisał(a):
Krótka instrukcja działania pętli for:
1) jeżeli program napotka pętle for, wykonuje najpierw to, co jest przed pierwszym średnikiem. W tym przypadku, ustawi wartość zmiennej pozycja_do_edycji na 0
2) program sprawdzi to, co jest pomiędzy pierwszym i drugim średnikiem. Czyli sprawdzi, czy przypadkiem zmienna pozycja_do_edycji nie przekroczyła wartości 62. A tak przy okazji, wyświetla się 63. znak?
3) program wykona to, co jest po drugim średniku. Zazwyczaj jest to inkrementacja/dekrementacja zmiennej sterującej pętlą.
4) wykonuje się to, co jest wewnątrz pętli. I tu uwaga: jeżeli po drugim przecinku zapiszesz zmienna++, to operacje wykonają się na starej wartości zmiennej, przed zwiększeniem. Ale jeśli napiszesz ++zmienna, to najpierw zwiększy się wartość zmiennej, a później zostanie ona wzięta do obliczeń.
5) po wykonaniu wszystkich instrukcji pętli program wraca do punktu 2)

Punkty 3 i 4 powinny być w odwrotnej kolejności, czyli najpierw jest wykonanie bloku instrukcji, a dopiero później wykonywana jest inkrementacja zmiennej.

Odnośnie uwagi w punkcie 4 - nie ma znaczenia czy użyta będzie pre-inkrementacja (++i) czy też post-inkrementacja (i++), pętla wykona się tak samo:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

Powyższe dwie pętle wykonają się dokładnie tak samo, czyli pięć obiegów oraz zakres wartości zmiennej i od 0 do 4.

To, o czym pisałeś mogłoby mieć zastosowanie np. w sytuacji, kiedy inkrementacja następuje w momencie sprawdzania warunku:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

W pierwszym przypadku najpierw wykonywana jest inkrementacja, a dopiero później porównanie wartości. W efekcie pętla będzie miała 4 obiegi oraz zakres wartości zmiennej i od 1 do 4.
W drugim przypadku najpierw wykonywane jest porównanie wartości, a dopiero później inkrementacja. W efekcie pętla będzie miała 5 obiegów oraz zakres wartości zmiennej i od 1 do 5.

Mam nadzieję, że kolega Marhef nie potraktuje mojego sprostowania jako złośliwości ;)

Teraz na temat danych we FLASH.
Robert_1967 napisał(a):
żeby nie pisać za każdym razem pgm_read_byte...

Rozpatrzmy Twój przykład. Możesz przetestować coś takiego:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

Przy założeniu, że obydwie tablice mają tyle samo elementów i elementy mają te same wartości, obydwie linie wyświetlacza powinny być takie same.

Jeśli zda egzamin i ktoś będzie zainteresowany, to mogę spróbować podpowiedzieć, jak nie pisać osobnej funkcji lcd_str_P(), tylko przerobić funkcję lcd_str() tak, by akceptowała zarówno dane z FLASH, jak i z RAM :)



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 10 maja 2018, o 19:14 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 26 sty 2016
Posty: 1146
Lokalizacja: Kraków
Pomógł: 93

andrews napisał(a):
Mam nadzieję, że kolega Marhef nie potraktuje mojego sprostowania jako złośliwości ;)
A skąd :) jak to mówią, człowiek całe życie się uczy... a i tak umiera głupi. Opisałem, tak jak ja to rozumiem. Ale faktycznie, moje rozumowanie nie było najlepsze.
A jeśli ktoś naprostuje... no to przecież po to jest forum, żeby poprawiać swoje głupoty :)



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 10 maja 2018, o 19:39 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 01 lis 2015
Posty: 1448
Lokalizacja: okolice Warszawa
Pomógł: 149

kurka,
@andrews, jak zawsze sypiesz wiedzą i siejesz zainteresowanie. :)
andrews napisał(a):
to mogę spróbować podpowiedzieć, jak nie pisać osobnej funkcji lcd_str_P(), tylko przerobić funkcję lcd_str() tak, by akceptowała zarówno dane z FLASH, jak i z RAM

Skoro teraz można użyć lcd_char(), zarówno do flash jak i ram, hmm...
Spróbuję zgadnąć.
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

Tak sobie teraz na biegu wymyśliłem kierunek w jakim chyba bym kombinował,
ale oczywiście jeśli możesz to poproszę poprawną wersję, lub nakierowanie. :)
sorka że w wątku kolegi Robert_1967, zakładam że się nie obrazi. ;)



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 10 maja 2018, o 20:07 
Offline
Użytkownik

Dołączył(a): 18 cze 2015
Posty: 352
Pomógł: 0

Dzięki andrews.
Niby taka "prosta" instrukcja for, a wzbudziła trochę dyskusji (oczywiście prosta dla kogoś, kto ją zrozumiał i opanował). No ale to chyba dobrze. Przecież jest
wiele osób, które się uczą i na pewno skorzystają z tej pomocy. Co do pre-inkrementacji i post-inkrementacji, to czytałem oczywiście, aczkolwiek póki co
nie do końca ją rozumiem, ale nauczę się. W każdym bądź razie dzisiaj natrafiłem na stwierdzenie (w internecie), że pomijając sam fakt, czy jest to pre, czy
post-inkrementacja, to pisanie w stylu I++ jest złe i bardziej "kosztowne" od na przykład ++I. Oczywiście nie podpisuję się pod tym, a tylko podzieliłem się
informacją z jakiegoś bloga. Może autorowi tego stwierdzenia chodziło o zajętość programu, czy prędkość wykonywania . Nie wiem. Natomiast w moim konkretnym
przypadku napisałem i tak i tak i w obu przypadkach wielkość pliku była identyczna, a sposób działania programu również.

Andrews. Jutro rano przetestuję, co napisałeś. Jeśli chodzi o funkcję lcd_str_P(), to nie ukrywam, że przydała by się w bibliotece. Może akurat nie dzisiaj i nie
jutro, ale kiedyś przyda się. Fakt, może za niedługo będę w stanie sam napisać, no ale puki co jeszcze nie potrafię. Do tej pory korzystałem bardziej z gotowych
rozwiązań i teraz widzę, że trzeba się uczyć. Nie mówię, że kompletnie nic nie umiem, ale zmieniłem podejście. Mój problem leży głównie w tym, że robię wszystko
na raz. Trochę zrozumiałem, ale nie do końca i biorę się za następny temat. No ale pewnie nie ja jeden :lol: .
Nawet, jak zaczynałem dowolnego main.c , to zazwyczaj inkludy były na zasadzie copy and past, no bo szybciej. Ale potem łapałem się, że nie potrafię z pamięci
napisać np. #include <util/delay>.h. W poradniku Mirek zwrócił uwagę, że często wpisuje wszystko z palca i ja tak zacząłem. Okazało się, że teraz piszę coraz
więcej z pamięci. Niby takie proste, a ile daje :lol: .
Co do funkcji lcd_char_P, czy lcd_str_P() , to myślę, że lepiej je rozgraniczyć (P), ponieważ moim skromnym zdaniem będziemy wiedzieć, co kiedy użyć
(nie zwalnia od myślenia). Jeśli funkcja jest uniwersalna, to nie zastanawiamy się, której aktualnie potrzebujemy, bo i tak zadziała. Dla zaawansowanych to
może bez znaczenia, bo i tak wiedza co robią. Nawet, jak nie wiedzą, co robią :lol: :lol: :lol: . Pozdrawiam. Robert.

------------------------ [ Dodano po: 2 minutach ]

Daro69
To nie jest wątek "na wyłączność :lol: . Każdy może pisać, a jeśli podzieli się z Tobą, to przy okazji przecież i ja skorzystam ;) . Pozdrawiam.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 10 maja 2018, o 21:59 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 11 mar 2014
Posty: 1475
Pomógł: 167

Robert_1967 napisał(a):
Co do funkcji lcd_char_P, czy lcd_str_P() , to myślę, że lepiej je rozgraniczyć (P)
Tutaj andrews trochę Ci namieszał ;), bo namawia Cię do tego co od pewnego czasu avr gcc udostępnia, czyli nowy sposób na definiowanie zmiennych / stałych w pamięciach EEPROM/Flash zwany Named Address Spaces. W skrócie działa to tak, że przez odpowiednie zdefiniowanie zmiennej zrzuca się z programisty konieczność późniejszego odpowiedniego odczytywania jej (czyli korzystania z np. pgm_read_byte()).
Więcej masz w opisie zrobionym w wątku topic19149.html (oczywiście także napisanym przez andrews :)).

Jednak proponuję Ci, na Twoim obecnym etapie, zostać na razie przy dwóch różnych funkcjach z _P i bez _P a proponowaną nowoczesną metodę potraktować jako ciekawostkę.

--
Pozdrawiam,
Robert



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 11 maja 2018, o 06:22 
Offline
Użytkownik

Dołączył(a): 18 cze 2015
Posty: 352
Pomógł: 0

Dzięki rskup
Ostatnio natrafiłem na innym znanym forum zaczynającym się na e... na temat, o którym piszesz. Na razie staram trzymać się "starych" zasad, ponieważ primo, trochę się do nich przyzwyczaiłem. Po drugie, korzystam w 99% tego super forum. Po trzecie bazuję przede
wszystkim na wiedzy przekazywanej z książek Mirka, poradników, ect...No i tak, jak piszesz, na moim etapie...
Co nie oznacza, że wielkie dzięki dla kolegi andrews za pokazanie pomysłu i jak pociągnie dalej temat, to będzie z pożytkiem dla innych. Jeszcze nie testowałem kodu kol. andrews, ale zaraz w wolnej chwili to uczynię. To zn. co tu testować. Na pewno będzie
działać :) , ale żeby to jeszcze zrozumieć ;) . Pozdrawiam. Robert.

------------------------ [ Dodano po: 49 minutach ]

Niestety, nie kompiluje się prawidłowo w moim przypadku.
Mam warninga w postaci:

07:51:43 **** Incremental Build of configuration Debug for project ASCII_flash_andrews ****
make all
'Building file: ../main.c'
'Invoking: AVR Compiler'
avr-gcc -Wall -g2 -gstabs -O0 -fpack-struct -fshort-enums -ffunction-sections -fdata-sections -std=gnu99 -funsigned-char -funsigned-bitfields -mmcu=atmega16 -DF_CPU=16000000UL -MMD -MP -MF"main.d" -MT"main.o" -c -o "main.o" "../main.c"
In file included from ../main.c:8:0:
c:\program files\atmel\avr tools\avr toolchain\avr\include\util\delay.h:95:3: warning: #warning "Compiler optimizations disabled; functions from <util/delay.h> won't work as designed" [-Wcpp]
# warning "Compiler optimizations disabled; functions from <util/delay.h> won't work as designed"
^
'Finished building: ../main.c'
' '
'Building target: ASCII_flash_andrews.elf'
'Invoking: AVR C Linker'
avr-gcc -Wl,-Map,ASCII_flash_andrews.map -mmcu=atmega16 -o "ASCII_flash_andrews.elf" ./LCD/lcd44780.o ./main.o
'Finished building target: ASCII_flash_andrews.elf'
' '
'Invoking: AVR Create Extended Listing'
avr-objdump -h -S ASCII_flash_andrews.elf >"ASCII_flash_andrews.lss"
'Finished building: ASCII_flash_andrews.lss'
' '
'Invoking: Print Size'
avr-size --format=avr --mcu=atmega16 ASCII_flash_andrews.elf
AVR Memory Usage
----------------
Device: atmega16

Program: 6668 bytes (40.7% Full)
(.text + .data + .bootloader)

Data: 65 bytes (6.3% Full)
(.data + .bss + .noinit)


Obrazek

Nie za bardzo wiem, co w takiej sytuacji. Robert.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 11 maja 2018, o 07:36 
Offline
Użytkownik

Dołączył(a): 07 cze 2016
Posty: 563
Pomógł: 143

Robert_1967 napisał(a):
# warning "Compiler optimizations disabled; functions from <util/delay.h> won't work as designed"

Ten błąd wynika z tego, że najprawdopodobniej wyłączyłeś optymalizację kompilatora, przez co funkcje z delay.h nie będą działały prawidłowo. Ten błąd nie ma związku z moim kodem. Włączenie optymalizacji jest wymogiem kodu z biblioteki standardowej delay.h. Po włączeniu optymalizacji powinno być OK. Kod, który przedstawiłem był przeze mnie skompilowany (bez żadnych warning-ów) i sprawdzony.

Jeśli chodzi o to podkreślenie __flash w kodzie na załączonym obrazku, to rozwiązanie jest tutaj



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 11 maja 2018, o 08:16 
Offline
Użytkownik

Dołączył(a): 18 cze 2015
Posty: 352
Pomógł: 0

Dzięki andrews

Utworzyłem projekt od nowa, ponieważ myślałem, ze na szybko coś poknociłem. Projekt się kompiluje i nie zgłasza błędów.
Wyświetlanie prawidłowe. Mimo wszystko dalej podkreśla na żółto __flash const uint8_t tab_flash[]. po najechaniu myszką
wyświetla się napis ?syntax error. Niemniej jednak wszystko gra. Nie wiem czemu taka reakcja programu.

Nie pamiętam, co mam wyłączone, a co nie (na pewno wyłączony debuger), ale cała instalacja eclipse dokładnie w/g poradnika
Mirka ponad pół roku temu. Prawie codziennie tworzę jakiś mały projekt dla potrzeb nauki i zawsze tak samo. Mam pierwszy
taki komunikat odnośnie util_delay. Mój program z posta o ASCII nie zgłasza problemu z tą biblioteką.
Oczywiście nie zrozum mnie źle, Ja tylko opisuję aktualny stan rzeczy i trochę mnie to dziwi, że mam coś takiego. Mam wyłączone
sprawdzanie pisowni w/g instrukcji Mirka. To tak w skrócie. Zaciekawiła mnie jeszcze objętość pliku za pierwszym razem. Teraz jest ok.

08:54:35 **** Incremental Build of configuration Release for project ASCII_flash_andrews ****
make all
'Building file: ../main.c'
'Invoking: AVR Compiler'
avr-gcc -Wall -Os -fpack-struct -fshort-enums -ffunction-sections -fdata-sections -std=gnu99 -funsigned-char -funsigned-bitfields -mmcu=atmega16 -DF_CPU=16000000UL -MMD -MP -MF"main.d" -MT"main.o" -c -o "main.o" "../main.c"
'Finished building: ../main.c'
' '
'Building target: ASCII_flash_andrews.elf'
'Invoking: AVR C Linker'
avr-gcc -Wl,-Map,ASCII_flash_andrews.map -mmcu=atmega16 -o "ASCII_flash_andrews.elf" ./LCD/lcd44780.o ./main.o
'Finished building target: ASCII_flash_andrews.elf'
' '
'Invoking: AVR Create Extended Listing'
avr-objdump -h -S ASCII_flash_andrews.elf >"ASCII_flash_andrews.lss"
'Finished building: ASCII_flash_andrews.lss'
' '
'Create Flash image (ihex format)'
avr-objcopy -R .eeprom -R .fuse -R .lock -R .signature -O ihex ASCII_flash_andrews.elf "ASCII_flash_andrews.hex"
'Finished building: ASCII_flash_andrews.hex'
' '
'Create eeprom image (ihex format)'
avr-objcopy -j .eeprom --no-change-warnings --change-section-lma .eeprom=0 -O ihex ASCII_flash_andrews.elf "ASCII_flash_andrews.eep"
'Finished building: ASCII_flash_andrews.eep'
' '
'Invoking: Print Size'
avr-size --format=avr --mcu=atmega16 ASCII_flash_andrews.elf
AVR Memory Usage
----------------
Device: atmega16

Program: 1588 bytes (9.7% Full)
(.text + .data + .bootloader)

Data: 65 bytes (6.3% Full)

Pozdrawiam. Robert.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 11 maja 2018, o 08:29 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 11 mar 2014
Posty: 1475
Pomógł: 167

Robert_1967 napisał(a):
Mimo wszystko dalej podkreśla na żółto __flash const uint8_t tab_flash[]. po najechaniu myszką
wyświetla się napis ?syntax error. Niemniej jednak wszystko gra. Nie wiem czemu taka reakcja programu.
W poprzednim poście andrews podał Ci linka do postu z opisem jak to usunąć :).
Cytuj:
Jeśli chodzi o to podkreślenie __flash w kodzie na załączonym obrazku, to rozwiązanie jest tutaj topic15543.html#p162317


--
Pozdrawiam,
Robert



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 11 maja 2018, o 08:55 
Offline
Użytkownik

Dołączył(a): 07 cze 2016
Posty: 563
Pomógł: 143

rskup napisał(a):
W poprzednim poście andrews podał Ci linka do postu z opisem jak to usunąć

Przyznam się bez bicia, że dopisałem to troszkę później, więc kolega Robert_1967 mógł nie zauważyć.

Robert_1967 napisał(a):
Zaciekawiła mnie jeszcze objętość pliku za pierwszym razem. Teraz jest ok.

Ewidentnie za pierwszym razem miałeś wyłączoną optymalizację. Widać to zarówno w warning-u, jak i w wywołaniu kompilatora (-O0).
Dlaczego? Nie wiem, bo mnie przy tym nie było ;)
Drugim razem kompilowałeś z opcją -Os, czyli z optymalizacją z naciskiem na ograniczenie rozmiaru kodu, więc zauważona przez Ciebie różnica do dość normalne zjawisko ;)



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 11 maja 2018, o 10:02 
Offline
Użytkownik

Dołączył(a): 18 cze 2015
Posty: 352
Pomógł: 0

Wielkie dzięki kolegom za szybką odpowiedź.
Zajrzę do wskazanego wątku i zgłębię temat. Pozdrawiam. Robert.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 11 maja 2018, o 18:44 
Offline
Użytkownik

Dołączył(a): 07 cze 2016
Posty: 563
Pomógł: 143

Teraz mam nieco czasu, więc pozwolę sobie na szerszą odpowiedź.
rskup napisał(a):
Tutaj andrews trochę Ci namieszał ;), bo namawia Cię do tego co od pewnego czasu avr gcc udostępnia, czyli nowy sposób na definiowanie zmiennych / stałych w pamięciach EEPROM/Flash zwany Named Address Spaces.

"Namawianie" nie było skierowane do konkretnej osoby, tylko do ogółu czytających ten wątek. Named Address Spaces funkcjonują już od prawie 6 lat i nie jest to wcale taka nowość. Mimo tego cały czas odnoszę wrażenie, że wielu programistów odczuwa niechęć do czegoś, co naprawdę upraszcza kod i eliminuje kilka poważnych problemów.
Szczególnie mam tutaj na myśli właśnie początkujących. Jeśli bowiem ktoś opanuje już pewne podstawowe zagadnienia, wie co to są zmienne, tablice, struktury, potrafi je zdefiniować w RAM i prawidłowo odczytać, a później chce pewne stałe dane przenieść do FLASH, by zaoszczędzić nieco pamięci RAM, to (jak pokazałem w swoim przykładowym kodzie) wystarczy do zmiennej globalnej dopisać kwalifikator __flash i kod będzie działał prawidłowo bez modyfikacji. Nie trzeba pamiętać o konieczności użycia makr, nie trzeba się uczyć tych wszystkich makr z rodziny pgm_read_xxx() i godzinami modyfikować kodu (który dla danych w RAM działał przecież prawidłowo), zastanawiając się, które makro użyć, aby odczytać odpowiednią ilość bajtów dla typu odczytywanej zmiennej, jak pobrać prawidłowy adres odczytywanej zmiennej, aby odczytać dokładnie to co chcemy itp.

rskup napisał(a):
W skrócie działa to tak, że przez odpowiednie zdefiniowanie zmiennej zrzuca się z programisty konieczność późniejszego odpowiedniego odczytywania jej (czyli korzystania z np. pgm_read_byte()).

Nie bardzo rozumiem, co miałeś na myśli używając określenia "odpowiedniego odczytywania", ale zapewniam Cię, że odczytywanie danych zdefiniowanych z kwalifikatorem __flash jest na pewno dużo bardziej odpowiednie, niż używanie makr pgm_read_xxx(). Stosowanie tych makr to nie tylko kwestia niewygody i gorszej czytelności kodu. Jeśli programista ich używa, kompilator traci możliwość kontroli typów, która jest ważnym elementem analizy poprawności kodu. Użycie __flash (lub __memx) eliminuje ten problem.

Reasumując, poza siłą przyzwyczajenia i strachem przed nieznanym, osobiście nie widzę argumentów przemawiających za stosowaniem makr pgm_read_xxx(), za to na pewno widzę kilka przeciw ;)

Robert_1967 napisał(a):
Co do funkcji lcd_char_P, czy lcd_str_P() , to myślę, że lepiej je rozgraniczyć (P), ponieważ moim skromnym zdaniem będziemy wiedzieć, co kiedy użyć
(nie zwalnia od myślenia). Jeśli funkcja jest uniwersalna, to nie zastanawiamy się, której aktualnie potrzebujemy, bo i tak zadziała.

Nie obraź się, ale moje skromne zdanie jest akurat dokładnie odwrotne. I wcale nie chodzi o to, że myślenie mnie boli ;) Generalnie języki wyższego poziomu po to zostały stworzone, aby ułatwiać życie programiście, co nie oznacza, że przez to "zwalniają od myślenia". Po prostu dzięki nim programista może myśleć bardziej globalnie, a oprócz tego, jakiej funkcji użyć w zależności od miejsca zapisania danych, jest na prawdę wiele innych rzeczy, które musi przemyśleć.

Nie traktuj tego co powiedziałem jako złośliwość. Nikomu nie chcę odbierać prawa do własnego zdania oraz własnych wyborów i szanuję je nawet, jeśli się z nimi nie zgadzam.

Wprawdzie tylko kolega Daro69 zainteresował się tematem funkcji uniwersalnej, ale mimo wszystko podpowiem co obiecałem ;)

Nie znam kodu funkcji lcd_str(), której używa kolega Robert_1967, ale powiedzmy, że to coś w stylu:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


"Przerobienie" funkcji polegałoby w takim przypadku na dodaniu kwalifikatora __memx do parametru funkcji (oczywiście tak samo w deklaracji jak i w definicji):
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Dane definiujemy globalnie:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Funkcję wywołujemy:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


I to by było na tyle...

Pozdrawiam
   Andrzej


Autor postu otrzymał pochwałę


Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 11 maja 2018, o 20:21 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 01 lis 2015
Posty: 1448
Lokalizacja: okolice Warszawa
Pomógł: 149

andrews napisał(a):
Wprawdzie tylko kolega Daro69 zainteresował się tematem funkcji uniwersalnej,

Myślę że nie tylko ja. Po prostu jako pierwszy "wychyliłem" się, a inni nie zdublowali mojej prośby. :)
Przyznaję że kwalifikatorów __flash nie używałem.
Czytając tu na forum wzmianki o nowym/starym sposobie, miałem zamiar oswoić się z tematem, ale ciągle zabieram się do niego ja przysłowiowy pies do jeża. :roll:
Możliwe że niebawem, po przeanalizowaniu informacji z Twojej stronki - sporo tego, :?
przestawię się na sposób z kwalifikatorem __flash . 8-)
Dzięki za kod, ( skopiowane i zarchiwizowane w lochach ). :D
Pozdrawiam.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 11 maja 2018, o 20:29 
Offline
Użytkownik

Dołączył(a): 18 cze 2015
Posty: 352
Pomógł: 0

Witaj andrews.
Bardzo dziękuję za tak konkretne wyjaśnienie, wyłożenie tematu. Żeby było jasne na początku. Ja się nigdy nie obrażam jeśli chodzi o dyskusje na forum, a tym
bardziej, jeżeli coś pozytywnego z tego wyniosę. Jestem po prosu już za stary, a żeby się przejmować takimi drobiazgami. To, co napisałeś, to wszystko prawda.
Początkujący zawsze maja obawy przed czymś nowym i wolą pozostać przy "starym", póki co. Ja osobiście podziwiam ludzi i jestem im wdzięczny, że znajdują
czas i chęci na pomoc innym i dzielenie się wiedzą. Tak się złożyło, że nigdy nie miałem styczności z programowaniem jakimkolwiek i teraz na stare lata, a żeby
trochę nadążyć w moim hobby elektronicznym, postanowiłem się w miarę możliwości trochę nauczyć. Cała ta terminologia informatyczna trochę mnie przeraża,
ale dzięki książkom Mirka, netu i pomocy innych idzie coraz lepiej, ale wolno. Ja się trzymam stereotypów, bo od nich zacząłem, a jak będę już trochę bogatszy
w wiedzę (mam taką cichą nadzieję), to pewnie inaczej będę myślał. Twoje rozwiązanie ciekawe i fajne. Widzisz andrews, ja kolekcjonuję wiele poradników Mirka,
które są po prostu bezcenne, czytam itd, ale może źle się uczę. W szkole było inaczej, program ułożony, wszystko po kolei itd...Tutaj cały materiał do wzięcia
od zaraz, no i jak tu nie przeskoczyć kilka tematów dalej, jak już się udało diodą pomigać :lol: :lol: :lol: . Gotowe sekwencje kodów z książek, z netu. Działa
po skompilowaniu, ale dlaczego działa, to już tylko autor wie :lol: . Myślę, że tu tkwi sedno sprawy. Ale to nic. To ma być zabawa i przyjemność. Ja z tego nie
żyję. Cieszę się że znajduję jeszcze czas na taką zabawę i że jest jakiś pozytywny efekt. To nie jest tak, że ja tylko piszę na forum i proszę mi tu dać rozwiązanie.
Pracuję, pracuję, ale może nieraz zbyt długo i potem tylko w głowie się kręci i pomroczność ciemna następuje :lol: . Ale dobra, dosyć marudzenia. Widzę jeszcze jeden pozytyw. Jakiś czas temu szukałem literek jednym palcem na klawiaturze, a teraz już dwoma palcami jadę i coraz lepiej dzięki forum ATNEL.
I tym pozytywnym akcentem kończę i jeszcze raz dzięki kolegom za udział w dyskusji i nauce C ;) .



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 11 maja 2018, o 21:44 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 11 mar 2014
Posty: 1475
Pomógł: 167

andrews napisał(a):
rskup napisał(a):
W skrócie działa to tak, że przez odpowiednie zdefiniowanie zmiennej zrzuca się z programisty konieczność późniejszego odpowiedniego odczytywania jej (czyli korzystania z np. pgm_read_byte()).

Nie bardzo rozumiem, co miałeś na myśli używając określenia "odpowiedniego odczytywania", ale zapewniam Cię, że odczytywanie danych zdefiniowanych z kwalifikatorem __flash jest na pewno dużo bardziej odpowiednie, niż używanie makr pgm_read_xxx().

No właśnie o tym pisałem. Przy "starej" metodzie musisz odpowiednio je odczytywać w zależności od miejsca umieszczenia danych (czyli używać makr typu pgm_read_byte()). Przy "nowej" __flash-owej nie ma tego problemu.

Dzięki andrews za namawianie do pójścia z duchem czasu. W końcu trzeba pójść do przodu i poprzerabiać swoje biblioteki na __flash-owe i zacząć już tylko tak używać :)

--
Pozdrawiam,
Robert



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 16 maja 2018, o 17:41 
Offline
Użytkownik

Dołączył(a): 07 cze 2016
Posty: 563
Pomógł: 143

Przepraszam, że z takim opóźnieniem kontynuuję wątek. Uznałem, że należałoby jeszcze coś wyjaśnić, ale wcześniej nie miałem czasu.
Robert_1967 napisał(a):
Co do funkcji lcd_char_P, czy lcd_str_P() , to myślę, że lepiej je rozgraniczyć (P)

Wcześniej podałem rozwiązanie z użyciem uniwersalnej funkcji akceptującej zarówno dane we FLASH jak i w RAM. Jeżeli jednak ktoś woli używać osobnych funkcji, nic nie stoi na przeszkodzie. Wystarczy (nawiązując do wcześniejszego przykładu) zastąpić kwalifikator __memx na __flash:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
i już mamy osobną funkcję z przyrostkiem _P, która akceptuje tylko wskaźniki do pamięci FLASH. Nadal jednak wewnątrz funkcji można uniknąć konieczności używania wiadomych makr do odczytu danych stosując normalny zapis, jak w przypadku danych w RAM.

Ważne jest to, że jeśli zdefiniujemy dane we FLASH za pomocą kwalifikatora __flash, nadal musimy używać odpowiednich funkcji z przyrostkiem _P z bibliotek standardowych (takich jak np. memcpy_P() czy też strcmp_P() ), tak jak to robimy w przypadku użycia PROGMEM. To, że autorzy bibliotek standardowych nie użyli funkcji uniwersalnych, tak jak to pokazałem wcześniej, wynika z faktu, że funkcje biblioteczne są zawsze bardzo dokładnie optymalizowane m.in. pod kątem szybkości wykonania. Funkcja uniwersalna używa wskaźników 24-bitowych i potrzebuje kilku dodatkowych taktów do rozróżnienia umiejscowienia danych, przez co jest minimalnie wolniejsza. W wielu przypadkach jednak, takich jak np. opisywane tutaj wyświetlanie danych na LCD lub przykładowo transmisja UART, to spowolnienie jest praktycznie bez znaczenia, więc bez obaw o szybkość kodu można takich funkcji jak najbardziej używać. No i oczywiście to, że funkcja ma przyrostek _P nie musi wcale oznaczać, że była napisana z użyciem makr pgm_read_xxx(), jak pokazałem nieco wyżej ;)

rskup napisał(a):
W końcu trzeba pójść do przodu i poprzerabiać swoje biblioteki na __flash-owe i zacząć już tylko tak używać

Przerabianie bibliotek wcale nie jest konieczne.
Powiedzmy, że mamy gotowy moduł do obsługi UARTa z funkcją zawierającą w nazwie przyrostek _P, np. uart_send_str_P(), przeznaczoną do transmisji danych odczytywanych z pamięci FLASH napisaną z użyciem makr z rodziny pgm_read_xxx(). Możemy normalnie dołączyć ten moduł do naszego projektu bez dokonywania w nim zmian.
Jeżeli teraz w pliku main.c zdefiniujemy sobie ciąg znaków we FLASH:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
to możemy przekazać go do naszej "starej" funkcji:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
i będzie ona działać prawidłowo, tak samo jakbyśmy zdefiniowali mystring przy użyciu PROGMEM.

Oczywiście dobrze jest zachować pewną systematykę i stosować albo jeden sposób, albo drugi, ale nie musimy przerabiać tych funkcji od razu wszystkich.

Daro69 napisał(a):
Możliwe że niebawem, po przeanalizowaniu informacji z Twojej stronki - sporo tego,
przestawię się na sposób z kwalifikatorem __flash .

Myślę, że warto się przekwalifikować ;)
Co do ilości materiałów, moim zdaniem nie trzeba się zrażać. Starałem się przedstawić sprawę jak najbardziej kompleksowo, pokazać jak najwięcej aspektów sprawy. W rzeczywistości nie jest to jakoś szczególnie skomplikowane, to tylko tak wygląda na pierwszy rzut oka ;) Na początek można pominąć rozdziały o danych w obszarach pamięci powyżej 64KiB lub w zdefiniowanych sekcjach, bo to jest raczej rzadko potrzebne, tym bardziej jeśli do tej pory nie musiałeś korzystać z makr pgm_get_far_address(), pgm_read_word_far() itp.

W razie czego można pytać. Postaram się odpowiedzieć na wszelkie wątpliwości (w miarę wolnego czasu oczywiście ;) ).



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
Wyświetl posty nie starsze niż:  Sortuj wg  
Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 56 ]  Przejdź na stronę Poprzednia strona  1, 2

Strefa czasowa: UTC + 1


Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zidentyfikowanych użytkowników i 1 gość


Nie możesz rozpoczynać nowych wątków
Nie możesz odpowiadać w wątkach
Nie możesz edytować swoich postów
Nie możesz usuwać swoich postów
Nie możesz dodawać załączników

Szukaj:
Skocz do:  
cron
Sitemap
Technologię dostarcza phpBB® Forum Software © phpBB Group phpBB3.PL
phpBB SEO