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



Teraz jest 17 lut 2025, o 01:26


Strefa czasowa: UTC + 1





Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 6 ] 
Autor Wiadomość
PostNapisane: 28 wrz 2016, o 20:03 
Offline
Użytkownik

Dołączył(a): 13 sie 2015
Posty: 44
Pomógł: 3

Witam Wszystkich

Jako że jestem w miarę nowy na forum i moja wiedza na temat konstrukcji argumentów funkcji z urzyciem wektorów jest wciąż za mała to postanowiłem starszym doświadczeniem osobą zadać pytanie:
Jak przekazać do funkcji Tablice z Progmemu poprzez wskaźniki ?
Przeszukałem dość sporo internet i możliwe ze coś przegapiłem natomiast wpadł mi w ręce taki oto dokument: Pana "M.Piasecki: PODSTAWY PROGRAMOWANIA "
(nawet z zbieżną nazwą pewnej książki którą mam)

Obrazek

Widać tam serie rycin jak to działa oraz fragmęt kodu obsługi "∗(∗(tabD+2) + 3) = 111 ; // tabD[ 2 ][ 3 ] = 111 ; " więc jeśli znaczy to że to jest to samo to dlaczego nie można tego przekazać do funkcji wbudowanej "pgm_read_byte()" ?

Jeśli ktoś będzie chciał pomoc będę dozgonnie wdzięczny bo siedzę już nad tym pytanie 3ci dzień przeszukując "na oślep" poczęci jak lunatyk internet z zerowym rezultatem

PS. Na prawdę dobrym tematem na Meeting (warsztaty) jest temat wetorów bo to jest temat moim zdaniem bardzo kluczowy ale również bardzo zawiły być może dlatego że jest chaos w przykładach z których przynajmniej ja sie najwięcej uczę. Do zobaczenia na warsztatach.

Kod niedziałający poniżej, po odebraniu ramki uarta są same "krzaczki"

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


Pozdrawiam i z góry dziękuje.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 28 wrz 2016, o 23:40 
Offline
Użytkownik

Dołączył(a): 29 lip 2014
Posty: 195
Pomógł: 44

Witam,

skoro mądrzy ludzie nie chcą niczego napisać, to może ja spróbuję ;-). Przede wszystkim, moim zdaniem, wskaźniki na tablice ( mam na myśli konstrukcje typu: (*ptr_to_tab)[TIMER_STATES] ) wyglądają słabo... ;-). Bo dla większej ilości wymiarów to już w ogóle masakra. Wystarczy zapamiętać fakt, że tablice wielowymiarowe zapamiętywane są w pamięci wierszami i tyle, wtedy to staje się proste dla tablicy o dowolnym rozmiarze. Jeśli na przykład, dla tablicy dwuwymiarowej potrzebujesz "dobrać się" do elementu (2,2) to jego adres będzie: 2+ 2*dlugosc_wiersza + adres poczatkowy. W Twoim przypadku to będzie tak:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


To w sumie wszystko, dla tablicy o dowolnym rozmiarze będzie tak samo. Ale uwaga: takie podejście jest potrzebne jedynie, jeśli chcesz przekazać adres tablicy jako parametr do funkcji, jeśli masz tablicę wewnątrz jakiejś tam funkcji, to możesz operować normalnie indeksami. To w sumie oczywiste, ale wolałem wspomnieć, by nie było nieporozumień. Jeśli czegoś nie rozumiesz to pisz.

Pozdrawiam, QuadMan.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 29 wrz 2016, o 01:51 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27359
Lokalizacja: Szczecin
Pomógł: 1042

HVM-a-C napisał(a):
Jak przekazać do funkcji Tablice z Progmemu poprzez wskaźniki ?


Przede wszystkim to źle definiujesz tablice stringów w pamięci flash, bo jak już to tak:

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


Po drugie tak jak kolega wyżej pisze - przekazywanie w takim przypadku całej tablicy do funkcji jako argument hmmm po co ? To tak jakbyś chciał się posługiwać nazwą zmiennej globalnej tej tablicy - więc po co tak przekazywać ? same komplikacje będą szczególnie właśnie przy tablicach wielowymiarowych - tak się nie robi. Na tym przykładzie wyżej widać jak na dłoni jak działa twoja tablica wskaźników do stringów w pamięci flash. Masz tablicę jednowymiarową wskaźników .... do stringów co tak na prawdę jest właśnie odpowiednikiem twojej tablicy

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


tyle że w twoim wypadku źle zdefiniowanej i zdeklarowanej.

Gdybyś chciał tą tablicę mieć w pamięci to problem byłby nieco mniejszy bo nie trzeba tam makr typu pgm_read_xxx()

Mogłoby to wtedy wyglądać tak:

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


a funkcja tak:

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

(tylko twoją funkcję UART0_Sstring() zastąpiłem lcd_str() do testów u siebie ale robi to samo tyle że na LCD) ;)

Tylko po choinkę takie triki karkołomne ? Tym bardziej że wewnątrz swojej funkcji zrobiłeś wg mnie KUPĘ BŁĘDÓW i nie wiem czy zdajesz sobie z tego sprawę - oto one (zaznaczam na czerwono)

Cytuj:
void ChangeBAUD (char num, char len, const char **str)
{
char buffer[len];
for (char j=0 ; j<len ; j++)
{

buffer[j] = pgm_read_byte( (*(*(str+num) + j)) );

}
UART0_Sstring(buffer);
}


Radzę ci hmmm może lepiej powiedzieć POLECAM CI, postaraj się zastosować do porad odnośnie stosowania odpowiednich typów to będziesz miał po stokroć mniej problemów - ten twój kod albo ci się kompilował z tysiącem warningów albo może korzystasz z kociego Atmel Studio z wyłączonymi warningami i nawet ich nie widziałeś .... :(

krótkie przypomnienie

char - ten typ stosuj tam gdzie będziesz miał do czynienia ze znakami ASCII

uint8_t, uint16_t, uint32_t - te typy stosuj dla zmiennych w których będziesz przechowywał tylko liczby !

mówię ci zapamiętaj tę prostą zasadę .....

Po drugie - to co wyprawiasz wewnątrz tej funkcji to już jest potrójne salto mortale z poczwórnym obrotem przez lewe ramię, a jak do tego dodać chęć przekazania całej tablicy z progmem przez wskaźniki tą metodą o jakiej piszesz to już jest takie salto że ciężko nawet je opisać ;)

Powiedz mi - tzn ok - jeśli to próbujesz robić TYLKO PO TO ŻEBY "poczuć wskaźniki" to ok jeszcze rozumiem - uczysz się - chociaż w rozwiązaniach idziesz totalnie złą drogą .... Jeśli chcesz napisać kawałek kodu który ci potrzebny to

1. powiedz po jaki gwint wewnątrz tej funkcji kopiujesz znak po znaku z przekazanego stringu do bufora tworzonego wewnątrz funkcji (brrrr na stosie - fuuuj) ... ???? Zamiast wprost wyświetlić ten string z pamięci Flash a masz na to przecież KUPĘ przykładów w Bluebooku a widzę, że go masz przecież ;)

2. ok jak już się uparłeś i tworzysz ten bufor - to znowu - nie doczytałeś a OPISUJĘ to pięknie (że tak nieskromnie powiem) w Bluebooku - jak działają funkcje - co się gdzie tworzy i jak ....

twój buffer[] to zmienna lokalna/automatyczna - a więc? Co będą zawierały jej elementy po skreowaniu ? UWAGA! będą zawierały SIECZKARNIĘ - a na pewno nie same zera !!! Więc jeśli wkleisz znak po znaku nawet z tej nieszczęsnej tablicy przez salto mortale jakie próbujesz zrobić - to nie wkopiujesz ZERA przecież !!! a to co spowoduje ? Że nawet jeśli poprawnie uda ci się zapisać to salto mortale na wskaźnikach - to funkcja wysyłająca string będzie śmigała aż napotka zero w tej zmiennej buffer a że nie napotka ;) to będzie rąbała dalej po pamięci aż gdzieś tam napotka w końcu jakieś zero - zaś ty nawet nie zauważysz - nie zdążysz zauważyć że na początku miałeś napis ale później poleciały śmieci z pamięci i napis został przez nie zamieciony ... rozumiesz ?

po to w tej mojej funkcji pokazałem ci jak się taki bufor jak już się na niego upierasz wyzerować np funkcją memset()


i teraz na koniec uważaj ;) bo ci się to może przyda ... jeśli twoim celem było wysyłanie dowolnego stringa z tej twojej tablicy stringów, to jeśli ją zorganizujesz tak jak ci pokazałem wyżej jako tablicę wskaźników to możesz W OGÓLE pozbyć się tej twojej funkcji i zamiast niej w pętli głównej zrobić tak ;)

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


i co ? ;) jak ci się to widzi ? ;) ... po co to przekazywanie w oddzielnych argumentach indeksu, albo już w ogóle niepotrzebnie długości stringa ?
Tylko zauważ że dodałem postfix _P do twojej funkcji czyli powinna ona być przerobiona na wysyłanie znaków ale z pamięci flash

czyli coś w tym stylu:

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


ale właśnie TO masz w bluebooku - czemu nie korzystasz z tego co masz pod ręką - tylko jak piszesz śmigasz po całym internecie szukając karkołomnych rozwiązań - mając je pod ręką i to jeszcze opisane , z przykładami itp itd

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 29 wrz 2016, o 18:55 
Offline
Użytkownik

Dołączył(a): 13 sie 2015
Posty: 44
Pomógł: 3

Z początku się wystraszyłem tyle dostałem od Was długich podpowiedzi ze przez chwile skojarzyło mi sie to z wynikami badań w trakcie choroby. im bardziej chory pacjent tym więcej ma w karcie napisane :D dobrze że chociaż w tym języku co potrzeba a nie po łacinie bo to by oznaczało że zaraz wyzionie ducha. :)


QuadMan napisał(a):
Witam,

skoro mądrzy ludzie nie chcą niczego napisać, to może ja spróbuję ;-). Przede wszystkim, moim zdaniem, wskaźniki na tablice ( mam na myśli konstrukcje typu: (*ptr_to_tab)[TIMER_STATES] ) wyglądają słabo... ;-). Bo dla większej ilości wymiarów to już w ogóle masakra. Wystarczy zapamiętać fakt, że tablice wielowymiarowe zapamiętywane są w pamięci wierszami i tyle, wtedy to staje się proste dla tablicy o dowolnym rozmiarze. Jeśli na przykład, dla tablicy dwuwymiarowej potrzebujesz "dobrać się" do elementu (2,2) to jego adres będzie: 2+ 2*dlugosc_wiersza + adres poczatkowy. W Twoim przypadku to będzie tak:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


To w sumie wszystko, dla tablicy o dowolnym rozmiarze będzie tak samo. Ale uwaga: takie podejście jest potrzebne jedynie, jeśli chcesz przekazać adres tablicy jako parametr do funkcji, jeśli masz tablicę wewnątrz jakiejś tam funkcji, to możesz operować normalnie indeksami. To w sumie oczywiste, ale wolałem wspomnieć, by nie było nieporozumień. Jeśli czegoś nie rozumiesz to pisz.

Pozdrawiam, QuadMan.


O Kurza twarz ! niech mnie dzwi ścisną jak Ty mądry nie jesteś !! coś nad czym siedziałem 3 dni (zliczyłem ilość przejrzanych stron: 543) z rezultatem zerowym a Tobie to zajęło może z 3hodziny bo tyle minęło czasu od wystawienia pytania na forum. Bardzo Ci dziękuje. Zadam pytanie skąd wiedziałeś że tak ma to wyglądać ? Gdzie o tym mogę poczytać ?


mirekk36 napisał(a):
Przede wszystkim to źle definiujesz tablice stringów w pamięci flash, bo jak już to tak:

Składnia: [ Pobierz ] [ Ukryj ]
język c

const char tb1[] PROGMEM = "ZBRODNIA.XXw";
const char tb2[] PROGMEM = "PAN.TADEUSZ";
const char tb3[] PROGMEM = "AVR.STUFF";
const char tb4[] PROGMEM = "PRZYKŁAD";
const char tb5[] PROGMEM = "MK.PASJA";

const char * const Book1 [] PROGMEM = {
tb1,
tb2,
tb3,
tb4,
tb5,
};

GeSHi



Rozumiem że mój sposób kategorycznie nie może być ? Widzę że mamy zaletę taką że ilość miejsca w flash jest dostosowywana za każdym razem do długości łańcucha + 0. Może w tym miejscu opisze jaki jest zamierzony cel całego programu w takich tablicach jak widzisz Mirku mieści się zbiór nazw książek program ma w łatwy sposób poprzez wpisanie komendy po RS (np nazwy książki) odnaleźć ją w tablicy i podać jej miejsce na regale.
to oczywiście program w wydaniu "abstrakcja 2016" jak sam podkreśliłeś , póki co mogę powiedzieć że znalazłem 1000 dróg którymi nie da się pójść.
Na pewno są inne drogi na konstrukcje tego programu pozostaje pytanie która droga jest dobra ?

mirekk36 napisał(a):
Radzę ci hmmm może lepiej powiedzieć POLECAM CI, postaraj się zastosować do porad odnośnie stosowania odpowiednich typów to będziesz miał po stokroć mniej problemów - ten twój kod albo ci się kompilował z tysiącem warningów albo może korzystasz z kociego Atmel Studio z wyłączonymi warningami i nawet ich nie widziałeś .... :(

heh tak to był , a nawet jest Atmel Studio i owszem masz racje był jeden alert tyczący się właśnie przekazywania tego przedziwnego wskaźnika do tablicy.
Co do typów tak oświeciło mnie w momencie gdy o tym przypomniałeś. Mój błąd.

mirekk36 napisał(a):
Powiedz mi - tzn ok - jeśli to próbujesz robić TYLKO PO TO ŻEBY "poczuć wskaźniki" to ok jeszcze rozumiem - uczysz się - chociaż w rozwiązaniach idziesz totalnie złą drogą .... Jeśli chcesz napisać kawałek kodu który ci potrzebny to

hmm no wiesz generalnie jak "próbujesz" coś robić to znaczy że z reguły nie czujesz gruntu pod nogami, Logika podpowiada -> Move forward ale też jak widać jeden wcale nie umyślny błąd na początku i później rodzi sie cała seria reperkusji z nim związana.


mirekk36 napisał(a):
1. powiedz po jaki gwint wewnątrz tej funkcji kopiujesz znak po znaku z przekazanego stringu do bufora tworzonego wewnątrz funkcji (brrrr na stosie - fuuuj) ... ???? Zamiast wprost wyświetlić ten string z pamięci Flash a masz na to przecież KUPĘ przykładów w Bluebooku a widzę, że go masz przecież ;)

A to efekt szukania rozwiązania w pewnym momencie (chyba akt desperacji) zacząłem szukać problemu w przekazywaniu wartości z "pgm_read_byte" :(

mirekk36 napisał(a):
2. ok jak już się uparłeś i tworzysz ten bufor - to znowu - nie doczytałeś a OPISUJĘ to pięknie (że tak nieskromnie powiem) w Bluebooku - jak działają funkcje - co się gdzie tworzy i jak ....

twój buffer[] to zmienna lokalna/automatyczna - a więc? Co będą zawierały jej elementy po skreowaniu ? UWAGA! będą zawierały SIECZKARNIĘ - a na pewno nie same zera !!! Więc jeśli wkleisz znak po znaku nawet z tej nieszczęsnej tablicy przez salto mortale jakie próbujesz zrobić - to nie wkopiujesz ZERA przecież !!! a to co spowoduje ? Że nawet jeśli poprawnie uda ci się zapisać to salto mortale na wskaźnikach - to funkcja wysyłająca string będzie śmigała aż napotka zero w tej zmiennej buffer a że nie napotka ;) to będzie rąbała dalej po pamięci aż gdzieś tam napotka w końcu jakieś zero - zaś ty nawet nie zauważysz - nie zdążysz zauważyć że na początku miałeś napis ale później poleciały śmieci z pamięci i napis został przez nie zamieciony ... rozumiesz ?


Mirku możesz sie zaśmiać ale uwierz że o tym pamiętałem wiesz gdzie powstał dygres ? w momencie gdy stwierdziłem że jeśli wiem że mam odczytać np 10 bajtów to wypełniam je 10 odczytanymi bajtami. Zero śmieci po prostu czyste dane :D czasem wolał bym dostać od kompilatora taki tekst który pamiętam z jednego z poradników video: "FIGA Z MAKIEM POWIEDZIAŁ KOMPILATOR , NIE SKOMPILUJE CI TEGO ..." :D


mirekk36 napisał(a):
i teraz na koniec uważaj ;) bo ci się to może przyda ... jeśli twoim celem było wysyłanie dowolnego stringa z tej twojej tablicy stringów, to jeśli ją zorganizujesz tak jak ci pokazałem wyżej jako tablicę wskaźników to możesz W OGÓLE pozbyć się tej twojej funkcji i zamiast niej w pętli głównej zrobić tak ;)

Składnia: [ Pobierz ] [ Ukryj ]
język c

for(;;) /* FORever :D */
{
UART0_Sstring_P( Book1[2] );
_delay_ms(1000);
}

GeSHi


i co ? ;) jak ci się to widzi ? ;) ... po co to przekazywanie w oddzielnych argumentach indeksu, albo już w ogóle niepotrzebnie długości stringa ?
Tylko zauważ że dodałem postfix _P do twojej funkcji czyli powinna ona być przerobiona na wysyłanie znaków ale z pamięci flash


Pięknie :D muszę cześć programu przerobić bo nie wiedziałem że da się to zrobić jednowymiarowo to co ja robiłem 2wymiarowo.

PS. Skoro mi było ciężko znaleźć coś o tym problemie może to właśnie jest dobry temat na kolejny video poradnik na temat wskaźników ?

Pozdrawiam i Bardzo WAM dziękuje.



Ostatnio edytowano 29 wrz 2016, o 19:39 przez HVM-a-C, łącznie edytowano 1 raz

Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 29 wrz 2016, o 19:19 
Offline
Użytkownik

Dołączył(a): 29 lip 2014
Posty: 195
Pomógł: 44

Witam ponownie.

Kolego HVM-a-C miałem cytować fragmenty Twojego posta, ale za dużo by się tego zebrało, a zaraz muszę uciekać. Pytasz gdzie to można przeczytać ? W każdej książce, opisującej standard języka C, ot choćby: "biblii" B.W. Kernnghan, D.M. Ritchie - "Język ANSI C programowanie". Moja odpowiedź była trochę natury ogólnej, zakładałem że potrzebujesz dostępu d dowolnego elementu tablicy wielowymiarowej z jakiejś tam funkcji, stąd takie a nie inne podejście. W aplikacji, którą obecnie kończę mam tablice 4 wymiarowe ;-). Dla tego konkretnego przypadku podejście Mirka ( tablica wskaźników na poszczególne elementy tablicy stringów ) jest oczywiście lepsze. Nie pisałem nic o typach - ot po prostu zrobiłem rzutowanie gdzie trzeba, aby "uciszyć" kompilator.
Zakładałem, że jako programista wiesz, co robisz ( podobnie jak twórcy "C" ;-) ). Dlatego też niczego nie pisałem o końcu stringa, niepotrzebnym kopiowaniu, itd. Myślałem po prostu, że to jest jakiś tam fragment testowy i tyle.
Jeśli to mają być faktycznie stringi w pamięci, gorąco polecam metodę Mirka i dokładne zapoznanie się z Jego postem.

Pozdrawiam, QuadMan.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 29 wrz 2016, o 19:46 
Offline
Użytkownik

Dołączył(a): 13 sie 2015
Posty: 44
Pomógł: 3

"Zakładałem, że jako programista wiesz, co robisz ( podobnie jak twórcy "C" ;-) )." no to teraz dopiero dostałem motywator umieć tyle co twórcy C :D wszystkim tego życzę ale zobaczymy co z tego wyjdzie , tak czy śmak dziękuje.



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: 6 ] 

Strefa czasowa: UTC + 1


Kto przegląda forum

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


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