Torkness Napisano Lipiec 31, 2015 Udostępnij Napisano Lipiec 31, 2015 Cześć,Podczas odczytywania string'a przez uart (wykorzystuje przerwania) mam spory problem z przepisaniem danych do zmiennej typu char[]. Tablica źródłowa i tablica docelowa są typu volitale. Przeszukałem kilka podobnych problemów na forum jednak nie znalazłem rozwiązania. Wolałbym nie rezygnować z oznaczenia volatile, ponieważ są to zmienne obsługiwane w przerwaniu UART. Otrzymuje 3 ostrzeżenia i 3 informacje: Warning 1 passing argument 1 of 'memcpy' discards 'volatile' qualifier from pointer target type [enabled by default] 70 3 Message 2 expected 'void *' but argument is of type 'volatile unsigned char *' 117 14 Warning 3 passing argument 2 of 'memcpy' discards 'volatile' qualifier from pointer target type [enabled by default] 70 3 Message 4 expected 'const void *' but argument is of type 'volatile unsigned char *' 117 14 Warning 5 passing argument 1 of 'memset' makes pointer from integer without a cast [enabled by default] 71 3 Message 6 expected 'void *' but argument is of type 'unsigned char' 121 14 (Wiersze których tyczą się ostrzeżenia/wiadomości nie pasują bo wyczyściłem z kodu poniżej nieużywane funkcje/obsługę ledów etc.) Kod: #include <avr/io.h> #include <stdio.h> #include <avr/interrupt.h> #include <util/atomic.h> #include <util/delay.h> #include <string.h> #define BAUD 9600 #define MYUBRR F_CPU/16/BAUD-1 volatile unsigned char data_in[44]; //ilość znaków jakie chcę maksymalnie przechowywać w tablicy volatile unsigned char command_in[44]; volatile unsigned char data_count; volatile unsigned char command_ready; void USART_INIT(unsigned int ubrr) { UBRR0H = (unsigned char)(ubrr>>8); UBRR0L = (unsigned char)(ubrr); UCSR0B = (1<<RXEN0)|(1<<RXCIE0); UCSR0C = (3<<UCSZ00); } void COPY_COMMAND() { ATOMIC_BLOCK(ATOMIC_FORCEON) { memcpy(command_in,data_in,44); memset(data_in[0],0,44); } } ISR (USART_RX_vect) { data_in[data_count]=UDR0; if(data_in[data_count]=='\n') { command_ready=1; data_count=0; }else { data_count++; } } int main(void) { USART_INIT(MYUBRR); DDRD = 0x00; sei(); while(1) { if(command_ready==1) { //w tym miejscu chce umiescic funckje rozpoznajaca rozkaz command_ready=0; } } } GeSHi Może ktoś ma pomysł co jest tu nie tak i mógłby mi wytłumaczyć? Ja szukam i szukam i nic nie znajduję 🙁 Pozdrawiam Link do komentarza Share on other sites More sharing options...
marek1707 Lipiec 31, 2015 Udostępnij Lipiec 31, 2015 Ostrzeżenia które dostałeś są dwojakiego rodzaju: "passing argument 1 of 'memcpy' discards 'volatile' qualifier from pointer target type" Te mówią o tym, że podczas analizy programu nastąpiła niezgodność typów argumentów formalnych z aktualnymi, dołączonymi do jej wywołania w Twoim kodzie. Funkcja memcpy oczekuje void * a dostała volatile unsigned char *. Jeżeli wiesz co robisz, możesz po prostu przerzutować odpowiednie wskaźniki na typ oczekiwany przez funkcję: memcpy((void *)command_in, (void *)data_in, 44); co powinno zadziałać bez narzekania kompilatora. Trzeba zauważyć, że nawet i bez tego zostanie wygenerowany poprawny kod Drugi typ ostrzeżenia jest dużo groźniejszy: "passing argument 1 of 'memset' makes pointer from integer without a cast" bo mówi o tym, że gdzieś użyłeś zwykłej liczby int w miejscu wskaźnika i nie wstawiłeś jawnego rzutowania. Na takie coś warto zwrócić uwagę, bo jeśli nie zrobiłeś tego celowo (i nie spodziewałeś się takiego komunikatu), to może to być poważnym problemem podczas działania programu i powodować makabryczne zniszczenia w pamięci danych. Rzeczywiście, w wywołaniu funkcji: memset(data_in[0], 0, 44); korzystasz z wartości komórki [0] tej tablicy a przecież pierwszym argumentem musi być wskaźnik na początek wypełnianego obszaru, czyli albo memset(&data_in[0], 0, 44); albo po prostu memset(data_in, 0, 44); plus poprzednie uwagi dot. rzutowania na typ wskaźnika wymagany przez funkcję memset(). Złym pomysłem są też nic nie mówiące liczby 44 umieszczone w przypadkowychmiejscach w kodzie. Skoro znasz i używasz instrukcji preprocesora, to jeszcze jeden #define nie zaszkodzi: #define DLUGOSC_BUFORA 44 Po co zerujesz bufor odbiornika po przepisaniu jego zawartości do command_in? Przecież nowe znaki napływające z UARTa mogą zastępować stare bez potrzeby "przygotowania" dla nich miejsca. Unikaj umieszczania długo wykonujących się funkcji (jak memcpy czy memset) w sekcjach krytycznych. Zawsze mnie rozczulają takie wyznania: "Ja szukam i szukam i nic nie znajduję". A dobry podręcznik do języka C miałeś kiedyś w ręku? To zwykła książka. Wystarczy odejść od komputera, usiąść w fotelu i po dwóch dniach czytania i zastanawiania się zaczynasz rozumieć o co chodzi 🙂 Warto, zostaje do końca życia. Link do komentarza Share on other sites More sharing options...
Pomocna odpowiedź
Bądź aktywny - zaloguj się lub utwórz konto!
Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony
Utwórz konto w ~20 sekund!
Zarejestruj nowe konto, to proste!
Zarejestruj się »Zaloguj się
Posiadasz własne konto? Użyj go!
Zaloguj się »