Skocz do zawartości

Elvis

Użytkownicy
  • Zawartość

    2603
  • Rejestracja

  • Ostatnio

  • Wygrane dni

    191

Wszystko napisane przez Elvis

  1. Zakłócenia możesz filtrować programowo. Po pierwsze dane polecenie lepiej wysyłać wielokrotnie. Po drugie wraz z poleceniem najlepiej wysłać sumę kontrolną - żeby "śmieci" nie były odbierane po stronie odbiornika. Wreszcie, jeśli to jakieś ważne dane, to możesz odsyłać potwierdzenie transmisji. Ogólnie odpowiedź jest: tak - można coś takiego zrobić. Ale żeby działało bezawaryjnie, to już nie jest tak bardzo prosto.
  2. Typ bool też nie jest standardowy w C. Najprościej uzyskać 0/1 tak: sensor[4] = (PINA & 0x08) ? 1 : 0;
  3. O ile wiem w C nie ma możliwości używania liczb binarnych (w czystym C). Można używać hexów, oczywiście dziesiętnych oraz ósemkowych. Jak chodzi o hex-y to kwestia wprawy. A mają niewątpliwą zaletę - spróbuj zapisać w kodzie binarnym np. maskę dla rejestru ARM-a, liczba jest 32-bitowa...
  4. Nie sprawdzałem przykładu na telefonie z ekranem dotykowym. Proponuję spróbować zamiast keyPressed, wykorzystać metodę: protected void pointerPressed(int x, int y) Dokumentacja jest tutaj: http://java.sun.com/javame/reference/apis/jsr118/javax/microedition/lcdui/Canvas.html#pointerPressed%28int,%20int%29
  5. Niestety C, ew. C++. Ale jeśli będzie zainteresowanie, to ja chętnie zmienię kurs LPC2114 na LPC1114
  6. A ja polecam LPC1114 - ma całkiem spore możliwości, niezłą cenę (polecam kamami, tme ma strasznie drogo). Poza tym programator nie jest potrzebny. Do programowania wystarczy konwerter RS232<->UART.
  7. ARM-y mają jedną przewagę nad AVR. Są produkowane przez wielu wytwórców. Więc jeśli np. NXP podwyższy ceny, to wszyscy zaczną używać STM, czy odwrotnie. W przypadku AVR producent ma pełną dowolność w dyktowaniu ceny.
  8. Spróbuj zamienić na: ISR(USART_RXC_vect)
  9. Lekcja 11 - Komunikacja przez COM0, Bootloader Progam testowy Na początek zaprogramujmy płytkę programem przykładowym dostępnym w archiwum Program16.zip. Program bardzo niewiele różni się od poznanego w poprzedniej części. Główna różnica to wykorzystanie UART0 zamiast UART1 (czyli COM0 zamiast COM1). Program wysyła testowe komunikaty przez port COM0. Aby zobaczyć rezultat działania musimy wykorzystać program do odczytu z COM0. Jak poprzednio polecam program putty, ale wystarczy nawet hyperterminal spod windows. Niestety jeśli uruchomimy terminal, nie zobaczymy spodziewanego rezultatu. Wygląda jakby nasz program nie działał. Żeby uruchomić program musimy wyjąć zworki: J5 - ISP J7 - RST Po ich wyjęciu resetujemy mikrokontroler przyciskiem RESET i widzimy, że program działa poprawnie. Niestety, gdy zamkniemy terminal i spróbujemy zaprogramować mikrokontroler, płytka nie będzie chciała się zaprogramować. Przed programowaniem musimy ponownie założyć zworki J5 i J7 oraz nacisnąć reset. Jak widać jest to dosyć męcząca procedura. Dlatego w poprzednich przykładach wykorzystywaliśmy COM1 do komunikacji, a COM0 do programowania. Bootloader Pozostaje wytłumaczyć magię zworek J5 i J7. Przy okazji znajdziemy nieco łatwiejszą metodę programowania i komunikacji przez port COM0. Najpierw musimy poznać nieco bliżej tzw. bootloader. Jest to program, który jest wgrywany do każdego procesora LPC2114 przez producenta. Gdy kupujemy nowy procesor bootloader jest już do niego wgrany. Co ciekawe, nawet po zaprogramowaniu procesora naszym programem bootloader nadal w nim pozostaje. Tak jak na PC możemy mieć wiele programów na raz, również w mikrokontrolerze może być wgranych wiele programów. Aby programy sobie nie przeszkadzały, znajdują się one pod innymi adresami. Bootloader jest uruchamiany podczas każdego startu, czy resetu procesora. Dopiero bootloader uruchamia nasz program. Do czego służy bootloader? Przede wszystkim do programowania procesora przez UART. Po resecie procesora najpierw uruchamiany jest bootloader, który sprawdza stan pinu P0.14. Jeśli na pinie tym będzie logiczne „1”, przekazuje sterowanie (uruchamia) do naszego programu. Jeśli na wejściu P0.14 po resecie pojawi się logiczne „0” bootloader przejmuje kontrolę i oczekuje na komunikację przez UART0. Do komunikacji z bootlaoderem (czyli programowania procesora) można wykorzystać darmowe programy takie jak: * LPC2000 Flash Utility - http://www.nxp.com/products/microcontrollers/support/software_download/lpc2000/ * FlashMagic - http://www.flashmagictool.com/ * lpc21isp - http://sourceforge.net/projects/lpc21isp/ Ostatni z tych programów jest przez nas wykorzystywany. W pliku makefile znajdziemy odwołanie do niego. Przyciskając Ctrl+F5 wywołujemy właśnie ten program. Teraz gdy wiemy, że po resecie uruchamiany jest nie nasz program, tylko właśnie bootloader, czas przyjrzeć się pinowi P0.14 oraz zworkom J5 i J7. Popatrzmy na schemat Linia A1 jest podłączona właśnie do portu P0.14. Natomiast RST do dopowiada za reset procesora. Jeśli zworka J7 jest założona to to układ pozwala na resetowanie procesora przez PC przy użyciu linii DTR złącza RS-232. Podobnie zworka J5 odpowiada za zerowanie wejścia P0.14 (uruchamiające programowanie przez bootloader) przez linię RTS złącza RS-232. Na schemacie widać jeszcze podłączenie przełącznika S2 z wejściem P0.14 przez zworkę INT1. Wykorzystamy tę możliwość nieco dalej. Gdy zworki J7 oraz J5 są założone, przy wykorzystaniu portu RS-232 można wykonać reset procesora oraz wymusić logiczne „0” na wejściu P0.14. Dzięki temu możliwe jest uruchomienie bootloadera z poziomu PC. Naciskamy ctrl+F5 i wszystko dzieje się automatycznie. Mikrokontroler jest resetowany, na P0.14 wymuszany jest stan „0” i rozpoczyna się programowanie. Niestety czasem taka „automatyzacja” działa nie najlepiej. Jeśli chcemy COM0 wykorzystać jako zwykły port komunikacyjny, linie DTR oraz RTS mogą wpływać na działanie mikrokontrolera. Widzieliśmy to po wgraniu przykładowego programu. Program nie działał, bo procesor był cały czas resetowany. Dużo zależy od programu sterującego portem RS-232, może on używać linii DTR i RTS lub nie. W przypadku putty niestety mikrokontroler nie może działać. Po wyjęciu zworek J5 oraz J7 mikrokontroler działa normalnie, ale nie można automatycznie go programować. Pozostaje zastanowić się, jak niejako „ręcznie” uruchomić bootloader w trybie programowania. Producent płytki dostarczył w tym celu 2 przełączniki: RESET oraz INT1. Jeśli przytrzymując INT1, naciśniemy RESET, procesor zostanie zresetowany, a bootloader odczyta na wejściu P0.14 stan „0” (o ile oczywiście zworka INT1 zostanie założona). Dzięki temu możemy zaprogramować procesor bez zworek J5 i J7. Procedura jest następująca: 1) przytrzymaj przycisk INT1 2) naciśnij i zwolnij RESET 3) zwolnij INT1 4) rozpocznij programowanie klikając przycisk Start w programie FlashMagic, albo odpowiednik w pozostałych Teraz mamy nową, znacznie łatwiejszą procedurę pozwalającą na wykorzystanie COM0 zarówno do programowania, jak i komunikacji. Przy okazji drobna uwaga. W projekt płytki ZL1ARM zakradł się mały błąd. Kondensator C9 o pojemności 100nF zapewnia filtrowanie drgań przycisku S2, ale jednocześnie może powodować zawieszanie (właściwie - uruchamianie bootloadera) podczas startowania płytki. Raz na kilka uruchomień program nie startuje. Jeśli taki efekt się pojawia należy zmienić kondensator na mniejszy. Program16.zip
  10. Dowcip matematyczny Def. Pochodną imprezy nazywamy ilość alkoholu jaką możemy kupić za butelki sprzedane po imprezie. Tw. Imprezę nazywamy nietrywialną wtedy i tylko wtedy gdy jej druga pochodna jest niezerowa.
  11. Nie, będzie jeszcze jedna część o RS232 oraz o przetworniku ADC.
  12. Jak już wymieniamy ciekawe mikrokontrolerki, to polecam zobaczyć Cortex-M0. Co prawda są słabsze od Cortex-M3, ale za to są bardzo tanie. Mogą być ciekawą alternatywą dla AVR. Do wgrywania można wykorzystać RS-232, albo kupić płytkę ewaluacyjną z przejściówką USB<->UART: http://www.kamami.pl/index.php?productID=137779 Najciekawsze są ceny samych procesorów. Najtaniej znalazłem w Kamami: http://www.kamami.pl/index.php?ukey=product&productID=136170 Procesor z 24KB Flash, 8KB RAM, zegarem 50MHz w cenie 6,65 zł (brutto przy 30szt)... Producent dostarcza gotowe środowisko do programowania (bazujące na eclipse): http://ics.nxp.com/lpcxpresso/ Na koniec jeszcze jeden plus dla osób nie przekonanych do SMD. LPC1114 jest (albo raczej będzie) dostępny w obudowie 44PLCC - można ją włożyć w przewlekaną podstawkę. http://pl.farnell.com/nxp/lpc1114fa44-301/mcu-32bit-32kflash-cortex-m0-44plcc/dp/1786288
  13. W ustawieniach projektu trzeba odszukać opcję generowania dodatkowo pliku .hex. Ja mam wersję 1.x CrossStudio, tam było to w zakładce Linker, opcja "Additional Output Format"
  14. Zawsze możesz wykorzystać BT do komunikacji z palmtopem. Dajesz moduł btm-222 i masz komunikację jak po RS-232.
  15. Te procesorki mają niestety trochę niespodzianek. Trzeba jeszcze uważać na P0.14 i czytać erraty. Jak chodzi o podciąg, to nie polecam dawać małego rezystora. Wtedy przy wyłączonej diodzie będzie płynąć całkiem spory prąd. Może lepiej odwrócić logikę - diodą podłączyć katodą z procesorem, anodą (przez rezystor) z zasilaniem. Wtedy zerem będzie można zapalać diodę. Podciąg może być całkiem spory - np. 47k. Najlepiej byłoby dać tranzystor, który sterowałby diodą - przy najmniej procesor nie byłby obciążany prądem diody.
  16. Jak chodzi o P0.2 to niestety trzeba dokładnie czytać dokumentację - wyjścia I2C są open-colector. Też się kiedyś na to naciełem. Ale z pullupem działają poprawnie. Natomiast P0.30 działa poprawnie. Tylko jest jeszcze jedna sprawa. Na stronie 106 dokumentacji (UM10114.pdf) podane są domyślne ustawienia portów. I jak na złość P0.30 domyślnie jest jako ADC (AIN3 dokłądniej). Czyli trzeba dodać: PINSEL1 &= ~(_BV(28)|_BV(29)) albo: PINSEL1 = 0
  17. Dziwne, że nie działa kod: GPIO0_IOSET =_BV(2)|_BV(30); Natomiast aktualna wersja: GPIO0_IOSET = 0xffff;//_BV(2)|_BV(30); Nie ma prawa działać na P0.30 - powinno być: GPIO0_IOSET = 0xffffffff;//_BV(2)|_BV(30); [ Dodano: 16 Paź 10 09:21 ] Już wiem, czemu nie działa P0.2 W dokumentacji jest mała zmyłka, jak odsyłacz [1]. A w nim: Więc wyjście P0.2 wymaga pull-upa. Inaczej nie będzie działać.
  18. Aby sprawdzić, gdzie są przechowywane zmienne funkcje itd. najlepiej otworzyć plik z rozszerzeniem .map (znajduje się w katalogu z plikiem wynikowym). Przykładowo w program14.map znajdziemy fragment: Memory Configuration Name Origin Length Attributes ROM 0x00000000 0x0001e000 xr RAM 0x40000000 0x00004000 rw *default* 0x00000000 0xffffffff Tutaj zdefiniowana jest mapa pamięci naszego mikrokontrolera. Od adresu 0 mamy Flash, od 0x40000000 pamięć RAM. Dalej odnajdujemy adresy zmiennych, czy funkcji. Przykładowo stała: const unsigned int SIN_TABLE[] = { 0, 15, 31, 46, 61, 76, 90, 104, 117, 129, 141, 152, 161, 170, 178, 184, 190, 194, 197, 199, 200 }; Daje wynikowo: *(.rodata) .rodata 0x00000418 0x74 program14.o 0x00000438 SIN_TABLE 0x00000418 LED_PIN Więc jak widać const działa zgodnie z oczekiwaniami, stała umieszczana jest w pamięci Flash.
  19. Ja bym radził oprócz oceny "na oko" podłączyć miliamperomierz i sprawdzić ile mA pobiera podświetlenie. Na diodę powinno być 10-20mA. Więc wystarczy sprawdzić ile diod ma wyświetlacz, i można chociaż z grubsza prąd oszacować. Poza tym jak pisze Nawyk zacząć o rezystora, sprawdzić jak świeci i ile prądu bierze.
  20. Strasznie drogo w AVT... Poczekaj chwile, może Treker coś z Kamami załatwi. Jeśli nie, to może lepiej inną płytkę wybrać. Bo prawie 180 zł to nieporozumienie...
  21. Ja również bardzo dziękuję za oddane głosy. Gratuluję wszystkim laureatom.
  22. Poprzednia lekcja RS-232, c.d. - biblioteka standardowa W przypadku Bascom-a używanie RS-232 jest bajecznie proste. Polecenie „print” wysyła tekst, właściwie nic nie trzeba robić. W tej części spróbujemy uzyskać podobny efekt w języku C. Funkcja sprintf Najpierw przyjrzymy się funkcji „sprintf”. Należy ona do biblioteki standardowej C, więc jest dostępna na właściwie każdej platformie i kompilatorze. Aby ją wykorzystać wystarczy zaimportować plik stdio.h: #include <stdio.h> Funkcja sprintf jest bardzo podobna do znanej funkcji printf. Każdy kurs C zaczyna się wyświetleniem „Hello World” za pomocą printf. Sprintf jako pierwszy parametr przyjmuje bufor (tablicę znaków) i zamiast na ekran, wypisuje wynik do bufora. Obejrzyjmy kod: char buf[32]; sprintf(buf, "Hello world!\n"); Program nie wypisze nic na ekran. W jego wyniku zmieni się zawartość tablicy buf, ale nic nie będzie widać. Po co więc nam funkcja sprintf? Za jej pomocą możemy właściwie dowolnie formatować napisy, wykorzystywać formatowania w rodzaju %d, %f, \n itd. Następnie bufor możemy za pomocą naszej funkcji uart_send_string() wysłać przez RS-232. Zmieńmy nieco poprzedni program. Tym razem, gdy otrzymamy nieznane polecenie (znak), wypiszemy kod tego znaku. Fragment: default: uart1_send("Nieznane polecenie\r\n"); break; Zastąpimy następującym: default: sprintf(buf, "#%d - Nieznane polecenie\r\n", c); uart1_send(buf); break; Kompilujemy program i... czeka nas przykra niespodzianka. Dostajemy całe mnóstwo błędów: c:/winarm/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\libc.a(freer.o): In function `_malloc_trim_r': mallocr.c:(.text+0x48): undefined reference to `_sbrk_r' mallocr.c:(.text+0x64): undefined reference to `_sbrk_r' mallocr.c:(.text+0x84): undefined reference to `_sbrk_r' c:/winarm/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\libc.a(makebuf.o): In function `__smakebuf': makebuf.c:(.text+0x3c): undefined reference to `_fstat_r' makebuf.c:(.text+0x110): undefined reference to `isatty' c:/winarm/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\libc.a(mallocr.o): In function `_malloc_r': mallocr.c:(.text+0x424): undefined reference to `_sbrk_r' mallocr.c:(.text+0x4cc): undefined reference to `_sbrk_r' c:/winarm/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\libc.a(stdio.o): In function Okazuje się, że musimy sami zdefiniować brakujące funkcje. Najprościej będzie skopiować gotowy plik z funkcjami z przykładu w katalogu: C:\WinARM\examples\lpc2129_adc_stdio\syscalls.c Kopiujemy plik do naszego projektu, dodajemy go w oknie edytora. Niestety błędy podczas kompilacji pozostają bez zmian. Musimy dodać nowy plik do kompilacji, czyli poleceń w pliku Makefile. Odnajdujemy fragment: # List C source files here. (C dependencies are automatically generated.) # use file-extension c for "c-only"-files SRC = $(TARGET).c I do zmiennej SRC dodajmy nowy plik: SRC = $(TARGET).c syscalls.c Jest to bardzo ważny moment. Od tej chwili nasz program będzie się składał z dwóch plików źródłowych. Część kodu jest w program19.c, część w syscalls.c. Jest to bardzo częsty i użyteczny mechanizm. Nie musimy trzymać wszystkich funkcji w jednym, z czasem bardzo dużym pliku. Zamiast tego dzielimy projekt na mniejsze części, funkcje umieszczamy w różnych plikach. Bardzo ułatwia to orientowanie się w projekcie oraz pozwala na wykorzystywanie plików z innych projektów w nowych programach. Niestety problemy nadal występują. syscalls.c:15:18: error: uart.h: No such file or directory syscalls.c: In function '_read_r': syscalls.c:31: warning: implicit declaration of function 'uart0GetchW' syscalls.c:31: warning: nested extern declaration of 'uart0GetchW' syscalls.c:37: warning: implicit declaration of function 'uart0Putch' syscalls.c:37: warning: nested extern declaration of 'uart0Putch' Na początek po prostu pozbędziemy się problemów - zakomentujemy wszystkie linie, które sprawiają problemy. W języku C wystarczy na początku linii napisać // aby kompilator resztę traktował jako komentarz. Dzięki temu linie te zostaną pominięte podczas kompilacji, ale gdy będziemy chcieli do nich wrócić, wystarczy usunąć napis //. Kompilujemy program i wgrywamy do procesora. Poniżej wynik działania: W archiwum program19.zip znajdziemy kompletny kod przykładu. Wgrywanie zajmuje teraz dużo więcej czasu niż w poprzedniej wersji. Niestety dołączenie funkcji sprintf znacznie zwiększyło objętość programu. Zajmuje teraz aż 45KB! Czyli o ponad 40KB więcej niż poprzednio... Moduł obsługi UART-a Zanim przejdziemy dalej warto nieco uporządkować program. W pliku głównym poza samym programem napisaliśmy kod odpowiedzialny za komunikację przez UART1. Kod ten na pewno przyda się w kolejnych programach, jest dość długi i utrudnia analizę programu głównego. Przygotujemy własny moduł, czyli utworzymy dwa pliki: uart.h, uart.c Do pliku uart.c przeniesiemy funkcje związane z komunikacją, czyli: uart1_init, uart1_recv, uart1_send_byte, uart1_send. Plik nagłówkowy jest potrzebny kompilatorowi, aby w programie głównym rozpoznawane były nazwy naszych funkcji. Wpisujemy do niego nagłówki funkcji poprzedzone słowem kluczowym extern, które informuje kompilator, że treść funkcji zdefiniowana jest gdzie indziej (w pliku uart.c). Następnie w programie głównym dodajemy instrukcję włączającą nasz nowy moduł: #include "uart.h" Musimy jeszcze w pliku Makefile dodać informację o nowym pliku z programem: uart.c. Wykonujemy to podobnie jak poprzednio dla pliku syscalls.c. Kompilujemy nowy projekt i sprawdzamy działanie. Wielkość kodu, ani działanie programu nie ulega zmianie. Natomiast program jest nieco "czytelniejszy", a nasz nowy moduł uart będziemy mogli wykorzystywać w kolejnych programach. Archiwum Program20.zip zawiera omawiany przykład. Funkcja printf i scanf Teraz możemy przystąpić do prawdziwego ułatwienia pracy. W standardowych programach pisanych na PC do komunikacji z użytkownikiem można wykorzystać standardowe funkcje printf oraz scanf. Ich użycie jest bardzo proste i każdy kurs C szczegółowo je omawia. Nauczymy się wykorzystywać je na mikrokontrolerze. Otwieramy plik syscalls.c i sprawdzamy, które linie musieliśmy zakomentować, aby program się kompilował. Na początek: #include "uart.h" Tutaj jest łatwo - wystarczy usunąć komentarz, mamy moduł uart.h, więc wszystko powinno być dobrze. Następnie zobaczmy zakomentowane odwołania do funkcji uart0Putch. Jak można się domyślić, ta funkcja ma wysyłać znaki. Nasza wersja nazywa się uart1_send_byte. Wystarczy więc zmienić nazwę wywoływanej funkcji i oczywiście usunąć komentarze. Zobaczmy jeszcze funkcję uart0GetchW. Odpowiada ona za odczyt znaku. Nasza wersja nazywa się uart1_recv i niestety działa nieco inaczej - zamiast czekać na znak, zwraca 0 jeśli nic nie zostało odebrane. Musimy więc dodać pętlę, w której będziemy czekać, aż coś odbierzemy. do { c = uart1_recv(); } while (c==0); Czas teraz wrócić do programu głównego i wykorzystać nowo przygotowane funkcje. Nowy program ma na celu jedynie prezentację, jak łatwo teraz programować komunikację przez RS-232: while (1) { printf("Podaj prędkość robota: "); scanf("%d", &speed); printf("\n"); if (speed>150) speed = 0; if (speed<0) printf("Za mala wartosc\n"); else if (speed>100) printf("Za duza wartosc\n"); else printf("Predkosc wynosi %d%%\n", speed); } Okazało się, że kod w pliku syscalls.c wymagał nieco poprawek - wersja z przykładu nie działała w 100% poprawnie. W załączniku znajdziemy plik program21.zip z poprawioną i przetestowaną wersją. Wnioski Wykorzystanie funkcji printf do komunikacji jest bardzo wygodnym rozwiązaniem. Niestety w przypadku kompilatora gcc oraz biblioteki standardowej, cena jaką trzeba zapłacić za wygodę jest wysoka. Dla dużych programów 40kB nie stanowi problemu, natomiast jeśli nasz program jest mały, lepiej poszukać innego rozwiązania. Program21.zip Program20.zip Program19.zip
  23. Może warto zobaczyć ten dokument: http://www.atmel.com/dyn/resources/prod_documents/doc2553.pdf Atmel opisuje w nim różnice między atmega88 i atmega8. Na mój gust różnice są spore - inne adresy rejestrów, część ma pozmieniane nazwy. Poza tym inne jest napięcie referencyjne dla ADC. Trzeba więc pewnie program trochę pozmieniać.
  24. Timer + rs232 powinien wystarczyć. Przed wywołaniem funkcji uruchamiasz timer, po zakończeniu zatrzymujesz i wartość wysyłasz przez rs232.
  25. Ja czasy mierze w ten sposób, że na wolnym pinie zmieniam stan przed wywołaniem określonej procedury i po powrocie. Następnie na oscyloskopie oglądam przebieg.
×
×
  • Utwórz nowe...