background image

http://www.easy-soft.tsnet.pl 

Urządzenia alarmowe bardzo często wyposażane  
są w różnego rodzaju sygnalizacje włamania. 
Najprostszym jest uruchomienie sygnału dźwiękowego 
czy optycznego, te bardziej zaawansowane potrafią 
podawać swój status przez Internet czy telefon. 
Prezentowane w tym artykule urządzenie to amatorski 
alarm, który potrafi przesłać informację o załączeniu 
przez krótką informację tekstową, tak zwany SMS. Dla 
potrzeb modelu wykorzystałem modem GSM firmy 
WAVECOM, jednak można użyć dowolnego telefonu 

komórkowego. Być może jego wykorzystanie będzie wymagało rozwiązania problemu zasilania oraz sposobu 
kodowania SMS, jednak jest możliwe i wykonalne w warunkach warsztatu elektronika – amatora. 
 
 

Opis konstrukcji. 

 

Prezentowana centralka alarmowa jest jednym z tego rodzaju urządzeń elektronicznych, których podstawowa 
wartość skupia się na wykonaniu odpowiedniego oprogramowania. Układ elektryczny jest prosty i nieco 
przypomina płytkę prototypową przeznaczoną do projektowania układów z mikrokontrolerami. Jednostkę 
sterującą stanowi układ mikrokontrolera firmy ATMEL AT90S2313 taktowany wewnętrznym generatorem o 
częstotliwości stabilizowanej kwarcem 7,3728MHz. Mikrokontroler posiada 15 linii wejścia – wyjścia. Dwie z nich 
wykorzystywane są przez UART (RXD – 2, TXD – 3), pozostałe trzynaście steruje pracą układów peryferyjnych 
lub służy do komunikacji mikrokontrolera z otoczeniem.  Port B ustawiany jest przez program jako wyjściowy z 
załączonymi rezystorami pull-up (DDRB=0xFF). Tryb ten nie ulega zmianie w czasie pracy programu mimo, iż 
czasami port ten wyprowadza dane a czasami służy do ich odczytu. Jest to pewna szczególna cecha 
mikrokontrolera AVR, wrócimy jeszcze do niej w dalszej części artykułu. Podobnie jest w przypadku portu D, 
chociaż tutaj część linii jest liniami wyjściowymi (TXD, DIR) a część wejściowymi (RXD i bity 2 do 5). Nie mniej 
jednak raz ustawiony tryb pracy nie jest zmieniany podczas funkcjonowania urządzenia. 
Jak wspomniałem wcześniej, mikrokontroler AT90S2313 posiada 15 linii portów wejścia – wyjścia. Potrzeby 
układu alarmu są jednak znacznie większe. Posiada on 8 wejść przeznaczonych dla czujników a dodatkowo 
wyświetlacz i klawiatura wymagają użycia odpowiednio co najmniej 6 i 7 wyprowadzeń portów. To tylko 
podstawowe układy otoczenia. Dodajmy do tego jeszcze co najmniej 1 linię dla sterowania układem sygnalizacji 
alarmu i otrzymamy liczbę 22 wyprowadzeń portów koniecznych do poprawnego funkcjonowania układu 
alarmu. Konieczna więc była albo zmiana mikrokontrolera na taki posiadający większą liczbę portów albo też 
zastosowania dodatkowych układów scalonych. Zdecydowałem się na to drugie rozwiązanie. 
Sygnał z czujników alarmowych podawany jest na doprowadzenia diody transoptora. Transoptor zapewnia 
izolację galwaniczną oraz eliminuje część niskonapięciowych zakłóceń, które mogą pojawić się na linii 
doprowadzającej sygnał z czujnika. Użyłem 2 elementów firmy SHARP o symbolu PC849 (odpowiednik 
funkcjonalny produkowany jest przez firmę LITEON pod oznaczeniem LTV849). Każda z obudów zawiera 4 
transoptory składające się z fototranzystora i diody. Szeregowo połączone z diodami rezystory R1..R8 należy 
dobrać do parametrów posiadanych czujników. Te stosowane przez mnie o wartości 1k dobrane zostały dla 
napięcia sterującego 9..12V.  
Osiem wejść czujników podłączone jest do układu multipleksera, który w zależności od poziomu logicznego 
sygnału przyłożonego na wejście A/B (wyprowadzenie 1) podaje na wyjścia 1Y..1Y odpowiednio stany logiczne z 
wejść 1A..4A lub 1B..4B. Umożliwia to 4-bitowemu portowi mikrokontrolera odczyt 8-bitowych danych w dwóch 
„porcjach” po 4 bity. Wyborem 4 wejść, z których odczytywany jest stan steruje wyprowadzenie 6 portu D 
mikrokontrolera. 
Niektóre z portów mikrokontrolera pełnią podwójną rolę. Oprócz tego, że są wyjściowymi np. dla modułu 
wyświetlacza LCD, to są również wejściowymi dla wierszy klawiatury. Zacznijmy może opis od wyświetlacza. W 
swojej konstrukcji użyłem modułu LCD 2 linie po 20 znaków w każdej. Wyświetlacz pracuje w trybie interfejsu 
4-bitowego wykorzystując linie portu PB0..PB4 jako linie danych, PB4 jako linię wyboru rejestru RS i PB7 jako 
ENABLE. Wszystkie linie portów oprócz ENABLE są wykorzystywane w dwójnasób: jako sterujące wyświetlaczem 
oraz pracą klawiatury. Wykorzystywany jest fakt, że w czasie trwania stanu niskiego na linii ENABLE nie są do 
rejestrów wyświetlacza zapisywane żadne dane. Umożliwia to zmiany stanów pozostałych linii bez zakłócania 
pracy modułu.  
Typowo, na wyprowadzenie 3 złącza wyświetlacza podane jest napięcie z suwaka potencjometru służące do 
regulacji kontrastu a pomiędzy 15 i 16 doprowadzone jest napięcie dla podświetlenia tła (około 4,3V). Układ 
można uprościć zwierając napięcie regulacji kontrastu do masy. Dla większości wyświetlaczy LCD jest to 
wystarczające. 
Klawiatura została zbudowana jako matryca 3 kolumn i 4 wierszy. Trzy bity portu B (4, 5 i 6) pracują jako 
wyjściowe, cztery jako wejściowe. Wszystkie linie mają załączone wewnętrznie rezystory pull-up. Wyjątkiem są 
tutaj bity 0 i 1, które wymagają zewnętrznych rezystorów podciągających. Kierunek pracy portu nie jest 
zmieniany przez program sterujący. Linie pracują zawsze jako wyjściowe a w razie potrzeby ich stan 
sprawdzany jest przez odczyt rejestru PIN. W architekturze mikrokontrolera AVR rejestr PIN to adres, przy 
odczycie którego, wyprowadzenie portu załączane jest przez specjalny bufor trójstanowy do wewnętrznej 
magistrali danych mikrokontrolera.  
Rolę układu dopasowującego poziomy napięć interfejsu UART mikrokontrolera do RS232 pełni układ MAX232. 
Wykorzystane są tylko 2 układy driverów znajdujące się w strukturze. Sygnał interfejsu doprowadzony jest na 
złącze męskie, 9-wyprowadzeniowe. Układu MAX można nie wlutowywać lub nie wykorzystywać. Zworki JP1 i 
JP2 znajdujące się na płytce umożliwiają odłączenie sygnałów RXD i TXD mikrokontrolera od układu MAX, i 
doprowadzenie go do inwertorów 74HCT14. W zamiarze miał być to układ dopasowujący do telefonu GSM 
(SIEMENS C35). Rezystory R20 i R21 to dzielnik napięcia, który jest tak dobrany, aby napięcie wyjściowe nie 

 

- Strona 1 z 14 - 

background image

http://www.easy-soft.tsnet.pl 

przekraczało 3,3V w stanie wysokim. W drugą stronę, bramka 74HCT14 pracująca jako odbiornik, posiada w 
strukturze przerzutnik Schmitta, który powoduje, że napięcie powyżej 2,4V uważane jest za stan wysoki. 
Zaznaczam jednak, że alarm testowany był wyłącznie z modemami firmy SIEMENS (M20T) oraz WAVECOM 
(WMOD2)  a interfejs dla telefonu GSM nie był wykorzystywany. Złącze dla „zwykłego” telefonu GSM oznaczone 
jest jako X14 a dla modemu GSM - X12. Bramki układu inwertora pracują również jako układy wyjściowe 
sterujące pracą przekaźnika oraz diody LED. Całość układu zasilana jest napięciem 5V z umieszczonego na 
płytce układu stabilizatora 7805 (U3). Do poprawnej pracy wymaga on podania co najmniej 7V na zaciski złącza 
X10. Uwaga na polaryzację! Kondensatory C9..C12 pełnią rolę filtrowania napięcia zasilającego. C10 i C11 
powinny być umieszczone jak najbliżej wyprowadzeń stabilizatora.  Rezystor R11 i kondensator C4 to prosty 
układ RC (rezystor ładowany przez kondensator) wytwarzający sygnał „reset” dla mikrokontrolera. Elementem 
wykonawczym alarmu jest przekaźnik RL1. Na doprowadzeniach jego cewki znajduje się dioda D3 mająca za 
zadania eliminowanie przepięć powstających w czasie załączania i wyłączania cewki. Jak wspomniałem 
wcześniej, rolę układu dopasowującego pełnią bramki inwertora połączone równolegle w celu zapewnienia 
większej wydajności prądowej. Przekaźnik sterowany jest wspólnie z diodą LED. Załączeniu przekaźnika 
odpowiada stan zaświecenia diody.  
W pewnych momentach pracy układu, dioda wykorzystywana jest również do sygnalizacji. Wówczas jednak jej 
błyski są na tyle krótkie, że nie powodują załączenia przekaźnika. Również w czasie przeglądania wierszy 
klawiatury starałem się dobrać czasy na tyle krótkie aby nie powodować załączania urządzeń zewnętrznych.  

 

Wyprowadzenie mikrokontrolera 

Nazwa 

Numer 

(obudowa 

DIL20) 

Oznaczenie 

sygnału na 

schemacie 

Opis 

funkcji 

PB0/AIN0 
PB1/AIN1 

PB2 

PB3/OC1 

PB4 

PB5/MOSI 
PB6/MISO 

PB7/SCK 

12 
13 
14 
15 
16 
17 
18 
19 

DB4 
DB5 
DB6 
DB7 

RS 

COL 

LED 

EN 

Linia danych DB4 modułu LCD, wiersz 2 klawiatury 
Linia danych DB5 modułu LCD, wiersz 3 klawiatury 
Linia danych DB6 modułu LCD, wiersz 4 klawiatury 
Linia danych DB7 modułu LCD, wiersz 1 klawiatury 
Linia RS (Register Select) modułu LCD, kolumna 1 klawiatury 
Kolumna 2 klawiatury 
Linia załączająca przekaźnik i diodę LED, kolumna 3 klawiatury 
Linia ENABLE modułu LCD (sterująca wprowadzaniem danych) 

PD0/RXD 

PD1/TXD 

PD2/INT0 
PD3/INT1 

PD4/T0 
PD5/T1 

PD6/ICP 






11 

RXD 

TXD 




DIR 

Linia odbiornika interfejsu UART mikrokontrolera 
Linia nadajnika interfejsu UART mikrokontrolera 
Wejście sygnału z czujki zewnętrznej (X1 i X5) 
Wejście sygnału z czujki zewnętrznej (X2 i X6) 
Wejście sygnału z czujki zewnętrznej (X3 i X7) 
Wejście sygnału z czujki zewnętrznej (X4 i X8) 
Sterowanie wyborem wejść multipleksera (U2) 

Tabela 1. Opis wyprowadzeń mikrokontrolera AT90S2313 
 
 

Opis programu sterującego. 

 

Początkowo zamierzałem wykonać całość programu sterującego pracą alarmu w językach Bascom lub GCC. 
Okazało się jednak, że mikrokontroler AT90S2313 ze swoimi 2kB pamięci FLASH jest zbyt skromny jak na 
wymagania kompilatora języka wysokiego poziomu. Zupełnie zaskoczył mnie kompilator GCC. Przeniosłem do 
niego bibliotekę funkcji, napisaną co prawda dla 8051, lecz po drobnych modyfikacjach kompilator GCC 
przetworzył źródło na kod wynikowy bez większego problemu. Jednak rozmiar tego kodu był dla mnie zupełnym 
zaskoczeniem! Wykonałem wyłącznie procedury obsługi LCD w języku C i te po kompilacji zajęły 3kB! Dla 
porównania analogiczny funkcjonalnie program wykonany w Bascom AVR zajął jedynie ok.500 bajtów. Podobnie 
zresztą jak w RC-51. Być może nie umiałem włączyć jakiejś opcji optymalizacji ale... Tak czy inaczej – 2kB to 
za mało pamięci aby była wystarczającą do wykonania tego typu aplikacji w jakimś języku wysokiego poziomu. 
Chcąc nie chcąc, zgodnie z zasadą „coś za coś”, musiałem wykonać całość programu sterującego w języku AVR 
Asembler. W tym przypadku był to rozmiar kodu wynikowego kosztem czasu spędzonego przy jego 
implementacji. Przy uruchamianiu i testowaniu programu sterującego posługiwałem się AVR Studio 4 firmy 
ATMEL.  
Aby omówić sposób funkcjonowania programu, muszę wyjaśnić kilka podstawowych reguł, którymi kieruję się 
przy pisaniu tego rodzaju aplikacji. Dotyczą one głównie stałych i zmiennych oraz sposobu ich interpretacji 
przez funkcje. Zacznijmy od liczb. Zgodnie z notacją przyjętą przez firmę Atmel, każdą liczbę rozpoczyna bajt 
mniej znaczący a kończy bardziej znaczący. I tak – jeśli liczba jest 4-bajtową zmienną umieszczoną w 
rejestrach R0 - R01 - R02 - R03, to najmniej znaczący bajt zawiera R0 a najbardziej znaczący R03. Każdy 
łańcuch tekstowy wysyłany na wyświetlacz zawiera tylko kody znaków większych od 0x20 (32 dziesiętnie, kod 
znaku odstępu) a kończy się znakiem o kodzie 0x00. Podobnie jest z ciągami znaków wysyłanych do modemu 
ale podlegających przetwarzaniu przed ich wysłaniem. Na przykład polecenie zapisując kod PIN zawiera część 
stałą „AT+CPIN=” oraz zmienny – zależny od karty SIM – poufny kod PIN. Inaczej jest z poleceniami 
przesyłanymi wprost do modemu. Te kończy sekwencja kodów CR (powrót kursora do początku linii, 0x0A) oraz 
LF (nowa linia, 0x0C). Reasumując – każdy tekst wyświetlany lub przetwarzany kończy kod 0x00 a każdy tekst 
przesyłany jako stały do modemu, kończą kody CR-LF. Ten sposób zapamiętywania danych stosowany jest 
konsekwentnie w całym programie. Wyjątkiem jest sposób w jaki przechowywane są kody załączenia i 
wyłączenia alarmu oraz kod PIN. 

 

- Strona 2 z 14 - 

background image

http://www.easy-soft.tsnet.pl 

Program główny jest bardzo krótki. Na początku ustawiane są tryby pracy portów B i D. Do rejestru DDRB 
wpisywana jest wartość 0xFF, co oznacza, że wszystkie wyjścia mają załączone rezystory pull-up i pracują jako 
wyjściowe. Do rejestru DDRD wpisywana jest wartość 0xC0, która ustawia bity 6 i 7 portu D jako wyjściowe a 
pozostałe jako wejściowe. Tu jedna uwaga. Linia TXD portu C (bit 1) pracuje jako wyjściowa, jednak wpisanie 
do rejestru DDRD „1” na pozycję odpowiednią dla tego bitu powoduje, że pracuje ona jako zwykły port 
wyjściowy i traci swoją funkcję jako TXD. Aby linia ta pracowała poprawnie jako wyjście interfejsu UART, należy 
do DDRD na pozycji 1 wpisać „0” lub pozostawić stan taki, jaki jest po załączeniu zasilania. 
Następne linie programu ustalają częstotliwość z jaką wywoływane będą przerwania Timer’a 0 i 1. Ten pierwszy 
to licznik 8-bitowy generujący przerwanie po zliczeniu 255 impulsów. 256 impuls zegarowy ustawia flagę 
przepełnienia OVF0 i powoduje przejście do obsługi przerwania. Przy częstotliwości rezonatora kwarcowego 
7,3728MHz, preskalerze ustawionym na wartość 1024 oraz początkowej wartości licznika 0 (licznik Timer’a 0 
liczy w górę), przerwania będą wywoływane z częstotliwością 7372800 : 1024 : 256 = 28,125 Hz. Timer 1 
również ma preskaler ustawiony na wartość 1024, jednak do rejestrów wpisywana jest wartość inicjująca, od 
której Timer zlicza impulsy zegarowe w górę, aż do przepełnienia. Timer 1, w odróżnieniu od Timer’a 0, jest 16-
bitowy, toteż liczy do wartości 65535. Impuls numer 65536 powoduje przepełnienie, ustawienie flagi OVF1 i 
przejście do procedury obsługi przerwania. Tu przerwanie wywoływane jest z częstotliwością 7372800 : 1024 : 
(65535 – 58335) = 1 Hz. Przerwania są zablokowane po uruchomieniu mikrokontrolera, jednak pozostawiony 
„na wszelki wypadek” rozkaz CLI wyłącza je i blokuje aż do momentu, gdy konieczne będzie ich użycie. 
Zostawmy na razie procedury obsługi przerwań – będzie jeszcze okazja do nich wrócić. 
Od etykiety „STATUS_CHECK” rozpoczyna się część programu mająca za zadanie rozpoznanie trybu, w którym 
znajdował się mikrokontroler przed wyłączeniem napięcia zasilania. Wywoływana zostaje funkcja odczytująca 
bajt spod adresu 0x00 w pamięci EEPROM. Wartość tego bajtu odpowiada statusowi urządzenia. Jeśli komórka 
ta zawiera wartość różną od 0xF0 lub 0x0F, to program uznaje, że jest to pierwsze załączenie alarmu i zażąda 
wykonania wszystkich niezbędnych nastaw, to jest: podania kodu załączenia i wyłączenia, podania kodu PIN dla 
używanej karty SIM, wprowadzenia numeru telefonu oraz opisów dla lokalizacji alarmu i wejść czujników. 
Wybrana metoda sprawdzenia statusu urządzenia jest o tyle pewna, że każdy zapis programu do pamięci 
FLASH mikrokontrolera AT90S2313 powoduje usunięcie zawartości EEPROM (cały EEPROM zostaje zapisany 
wartością 0xFF). Po wprowadzeniu nastaw do komórki „STATUS” zostaje zapisana wartość odpowiednia dla 
stanu wyłączenia alarmu. 
Poświęćmy teraz kilka chwil wysyłanym do modemu rozkazom i ich znaczeniu. Interfejs UART pracuje z 
szybkością 9600 bitów na sekundę. Identyczną prędkość powinniśmy ustawić w posiadanym telefonie, czy 
modemie. Aby dokonać niezbędnych nastaw należy przy pomocy dowolnego programu terminala nawiązać 
połączenie z modemem i wydać polecenie „AT+IPR=9600;&W”. Ustawi ono i zapisze w pamięci konfiguracji 
modemu parametr prędkości transmisji. W przypadku użycia telefonu GSM może się okazać, że nie zaakceptuje 
on wyżej wymienionej komendy. Wówczas prawdopodobnie łatwiej będzie nam zmienić prędkość z jaką pracuje 
UART mikrokontrolera, aniżeli telefonu. Można to zrobić poprawiając funkcję „uart_init” a konkretnie wartość 
wpisywaną do rejestru UBRR. Należy dobrać ją w zależności od używanego rezonatora i wymaganej prędkości 
transmisji. Gotowe przykłady można znaleźć w notach aplikacyjnych na stronie producenta 
http://www.atmel.com lub wyliczyć samodzielnie na podstawie wzorów znajdujących się w kartach 
katalogowych mikrokontrolerów AVR. Gdy sprawdzimy, że modem (telefon) gotowy jest do pracy i komunikuje 
się poprawnie używając prędkości 9600 bps, możemy podłączyć go do naszego układu. 
Jako pierwszą program sterujący wysyła komendę „ATZ”. Powoduje ona ustawienie domyślnego trybu pracy – 
przywrócone zostają również wszystkie te parametry, które nie zostały zapamiętane na stałe jako domyślne. 
Następny rozkaz wprowadza numer PIN właściwy dla karty na przykład: „AT+CPIN=9889”. Kod PIN to hasło, 
którego rola polega na zabezpieczeniu telefonu GSM przed niepowołanym dostępem. Tutaj szczerze 
powiedziawszy trochę przeszkadza ale niestety – jest wymagany w celu uruchomienia modemu. Jako kolejne 
wysyłane są polecenia „ATE0” wyłączające tzw. echo komendy oraz „AT+CPMS=SM” ustawiające miejsce 
przechowywania wiadomości SMS na kartę SIM. Jednocześnie z przyjmowaniem tych poleceń modem włącza się 
do sieci. W przypadku modemu WAVECOM gotowość do pracy sygnalizowana jest przez migoczącą z 
częstotliwością około 1 Hz diodę LED, w przypadku SIEMENS MT20 jest odwrotnie – dioda LED zaświeca się na 
stałe. 
Po każdym poleceniu wysłanym do modemu wywoływana jest funkcja „gets” odbierająca ciąg znaków z UART. 
Oczekiwane jest, że modem odpowie co najmniej wysyłając kody CR i LF. W przypadku braku odpowiedzi od 
modemu, program przestanie pracować już w fazie inicjacji. Można w ten sposób łatwo stwierdzić, że brak jest 
poprawnej łączności z modemem. Niestety, nie wykonałem w programie detekcji odłączenia modemu. W 
przypadku, gdy modem zostanie odłączony tuż przed wysłaniem SMS z powiadomieniem o załączeniu alarmu, 
alarm zostanie włączony a następnie program będzie oczekiwał na połączenie z modemem i odpowiedź na 
przesłane polecenia. Jeśli jej nie otrzyma – zawiesi się sprawdzając w nieskończoność stan flagi gotowości do 
odbioru znaku (bajtu) z UART. 
Od etykiety „main” rozpoczyna się główna pętla programu. Na jej początku ponownie odczytywany jest bajt 
statusu i w zależności od jego wartości podejmowana jest odpowiednia akcja. Polega ona bądź to na wywołaniu 
procedury obsługi alarmu w stanie czuwania, bądź to obsługi alarmu w stanie wyłączenia. 
 

Stan wyłączenia.

 Za jego obsługę odpowiedzialna jest funkcja „alarm_off”. Po jej wywołaniu czyszczony jest 

ekran wyświetlacza LCD a następnie wyświetlona zostaje informacja z pamięci ROM umieszczona w niej pod 
nazwami symbolicznymi „whenoff” oraz „set_1”. Ta pierwsza umieszczona zostaje w 1 linii ekranu – ja 
zadeklarowałem ją jako „ALARM WYŁĄCZONY”. Ta druga umieszczona w 2 linii LCD, to pytanie o kod 
wyłączenia. Zadeklarowałem ją jako „Kod wyłączenia?”. Później zmiennej „visible” nadana zostaje wartość 
„UCANTSEE” a zmiennej „sensors” wartość „SENSOROFF”. Po wyżej wymienionych operacji, wywoływana jest 
funkcja odczytu kodu wprowadzanego przy pomocy klawiatury. Kod jest zawsze 4 cyfrowy. Rezultat pracy 
funkcji zwracany jest w rejestrach o nazwach symbolicznych „cchar1” do „cchar4”. Uwaga: kod załączenia musi 
być inny niż „0000”. Jest on zarezerwowany do wprowadzenia urządzenia w tryb serwisowy! 

 

- Strona 3 z 14 - 

background image

http://www.easy-soft.tsnet.pl 

Funkcja „compare_codes” porównuje 4 bajty pobrane z pamięci EEPROM spod adresu podanego w rejestrze 
„eeaddr” z tymi odczytanymi z klawiatury. Jeśli kod wprowadzony jest identyczny z zapamiętanym, do komórki 
zawierającej bajt statusu w EEPROM, zapisana zostaje wartość informująca program o tym, że alarm jest 
załączony i następuje powrót do programu głównego. Teraz na podstawie zawartości komórki „status” pamięci 
EEPROM, wywołana zostaje funkcja obsługująca stan załączenia alarmu. 
 

Stan załączenia.

 Całość funkcji związanych ze stanem czuwania alarmu umieszczona jest w podprogramie pod 

etykietą „alarm_on”. Po wejściu do podprogramu załączane jest przerwanie Timer’a 1. Fragment programu 
zawierający kod jego obsługi, umieściłem na listingu 1. Procedura ta ma do wykonania dwa podstawowe 
zadania. Ma zwiększyć wartość zmiennej - licznika „goon” oraz odświeżyć zawartość rejestrów licznika Timer’a 
1. Do tych dwóch zadań dodałem jeszcze trzecie – krótki, trwający około 1 milisekundy, błysk diody LED. 
Sygnalizuje ona w ten sposób, że odmierzany jest czas do załączenia. Pętla rozpoczynająca się od etykiety 
„al_on_wait” trwa dokładnie tyle czasu odmierzanego w sekundach, ile podano w stałej „DELAYTIME”. Jako 
typową wartość zadeklarowałem 30 sekund. Jest to czas, przed upływem którego osoba załączająca alarm musi 
się oddalić z obszaru zadziałania czujników. 
 
 
;----------------------------------------------------------------------------- 
;obsługa przerwania timera 1 
;odmierzanie czasu opóźnienia do zadziałania alarmu 
;----------------------------------------------------------------------------- 
tim1_irq: 
 sbi 

portb,ALARMOUT 

 ;załączenie diody LED (migotanie w czasie "ALARMDELAY") 

 push 

temp 

  ;przechowanie 

zawartości "temp" na stosie 

 ldi 

temp,TIM1RLDH 

 out 

TCNT1H,temp 

 ldi 

temp,TIM1RLDL 

 out 

TCNT1L,temp 

 ;odświeżenie zawartości Timer'a 1 

 inc 

goon 

  ;zwiększenie licznika "goon" 

 ldi 

temp,0xFF 

tim1_loop: 
 rcall 

delay1ms  ;opóźnienie czasowe aby migotanie LED było widoczne 

 pop 

temp 

 cbi 

portb,ALARMOUT 

 ;wyłączenie diody LED 

 reti 
 
Listing 1. Procedura obsługi przerwania Timer’a 1. 
 
Po upływie tego czasu, rozkaz CLI wyłącza obsługę przerwań a przerwanie pochodzące od Timer’a 1 jest 
blokowane. Teraz wyświetlony zostaje komunikat o załączeniu alarmu („whenon” i „set_2”) a następnie do 
rejestru kontrolnego przerwań (TIMSK) wprowadzana jest nastawa załączająca przerwanie na skutek 
przepełnienia Timer’a 0. Jest ono odpowiedzialne za odpytywanie stanu czujników (sensorów) alarmu. Rozkazy 
składające się na procedurę obsługi umieściłem na listingu 2. Ze względu na pozorną złożoność poświećmy jej 
troszeczkę uwagi. 
 
 
;----------------------------------------------------------------------------- 
;obsługa przerwania timera 0 
;odpytywanie wejść alarmu 
;----------------------------------------------------------------------------- 
tim0_irq: 
 push 

temp 

  ;zapamiętanie "temp" na stosie 

 cbi 

portd,HIGHNIBBLE 

;odczyt 

młodszej połówki bajtu wejść czujników 

 nop 

   ;przerwa 

na 

czasy 

propagacji 

układów 

 nop 
 in 

temp,pind 

 ;odczyt 

młodszej połówki bajtu 

 asr 

temp 

  ;"dopasowanie" 

bitów 

 asr 

temp 

 mov 

sensors,temp 

 sbi 

portd,HIGHNIBBLE 

 nop 

   ;przerwa 

na 

czasy 

propagacji 

układów 

 nop 
 in 

temp,pind 

 ;odczyt 

starszej 

połówki bajtu 

 asr 

temp 

  ;"dopasowanie" 

bitów 

 asr 

temp 

 andi 

temp,0x0F 

 swap 

temp 

 or 

sensors,temp 

 pop 

temp 

 reti 
 
Listing 2. Procedura obsługi przerwania Timer’a 0. 
 

 

- Strona 4 z 14 - 

background image

http://www.easy-soft.tsnet.pl 

Rozkaz „push temp” przechowuje wartość rejestru „temp” na stosie. Następnie zerowany jest bit 6 portu D 
oznaczony na schemacie jako DIR. Wartość „0” tego bitu oznacza, że odczytane zostaną czujniki podłączone do 
wejść 1A, 2A, 3A i 4A mikrokontrolera. Tworzą one młodszą połówkę bajtu stanu czujników. Jest ona 
odczytywana z rejestru PIND, przesunięta dwukrotnie w prawo (dwa polecenia „asr temp”) i zostaje 
zapamiętana w zmiennej „sensors”. Następnie, po ustawieniu stanu wysokiego na wyprowadzeniu PORTD.6, 
pobrany zostaje starsza połowa bajtu stanu czujników, przesunięta dwukrotnie w prawo i zsumowana z 
młodszą. Wynik sumowania zostaje zapamiętany w zmiennej „sensors”. Po odtworzeniu wartości „temp” rola 
procedury kończy się. Inne funkcje sprawdzają odczytany stan czujników i podejmują odpowiednią akcję. W 
przypadku stwierdzenia na jednym z wejść informacyjnych mikrokontrolera (PD2..PD5) stanu niskiego, rola 
przerwania Timer’a 0 kończy się – zostaje ono zablokowane. Dalsze przeglądanie czujników nie jest potrzebne. 
Ponownie zerowany jest licznik czasu „goon” i załączone zostaje przerwanie Timer’a 0 tym razem odmierzając 
czas upływający od momentu zadziałania czujnika do momentu załączenia alarmu. Ponownie jest to czas 
podany w sekundach o wartości „DELAYTIME”. Opóźnienie zostało wprowadzone po to, aby użytkownik miał 
możliwość wprowadzenia kodu wyłączającego alarm. 
Procedura „alarm_on”, sprawdza kod wyłączenia wprowadzany przez użytkownika podobnie jak poprzedniczka. 
W ten sam sposób kończy pracę ustawiając bajt statusu urządzenia w EEPROM i powracając do głównej pętli 
programu w przypadku zgodności wprowadzonego kodu z tym zapisanym w EEPROM. Ponownie jak poprzednio 
– decyzję o podejmowanej przez urządzenie akcji podejmuje główna pętla programu na podstawie zawartości 
komórki pamięci zawierającej bajt statusu urządzenia. W związku z tym, że jest to pamięć, która nie traci 
zawartości po wyłączeniu napięcia zasilania, urządzenie po odłączeniu i ponownym podłączeniu napięcia 
zasilania zostanie wprowadzone w ten sam stan, w którym znajdowało się przed wyłączeniem.  
 

Odczyt kodu.

 Ramy tego artykułu są trochę zbyt szczupłe aby omówić blisko 1,5 tysiąca linii programu 

napisanego w języku asemblera. Niestety w związku z tym pewne aspekty będą pominięte i dociekliwy Czytelnik 
musi sam przeanalizować kod źródłowy programu tak, aby dotrzeć do pewnych szczegółów. Jedną z takich 
dwóch „trudnych” procedur jest funkcja odczytu kodu wprowadzanego z klawiatury. Zwłaszcza kilka 
początkowych linii wymaga dokładniejszego omówienia. Umieściłem je na listingu 3. 
 


read_code_loop: 
 brid 

read_code_next 

 ;jeśli przerwania są wyłączone, przejdź do odczytu 

 

 

    ;klawiatury 

     ;i 

nie 

sprawdzaj 

stanu 

sensorów 

 

mov 

temp,sensors   

;sprawdzenie stanu czujników!!! konieczne tutaj,  

   

 

 

 

 

;bo funkcja nie przerywa pracy do momentu odczytu  

 

 

 

    ;pełnego, 4-cyfrowego kodu 

 cpi 

temp,SENSORSOFF 

 breq 

read_code_next 

 ;jeśli żaden sensor nie jest aktywny omiń  

 

 

 

    ;poniższe rozkazy 

 brts 

read_code_act 

 ;jeśli flaga T jest ustawiona, to nie wykonuj  

 

 

    ;nastaw 

przerwania 

Timera 

 cli 

   ;wyłączenie przerwań 

 clr 

goon 

  ;kasowanie 

licznika 

czasu 

opóźnionego załączenia  

   

 

 

 

 

;(pracuje w przerw.Timer'a 1) 

 ldi 

temp,0x80 

 out 

TIMSK,temp 

 ;załączenie przerwań Timer'a 1 (co 1 sek.) 

 sei 

   ;załączenie przerwań 

read_code_act: 
 set 

   ;ustawienie 

flagi 

"T" 

 push 

zl 

  ;przechowanie 

wskaźnika do bufora w RAM 

 rcall 

alarm_active 

 pop 

zl 

read_code_next: 
 

rcall  kbd_read 

 

;odczyt klawiatury, znak zwracany w zmiennej “char” 



Listing 3. Fragment funkcji odczytu kodu „read_code”. 
 
Od etykiety „read_code_next” rozpoczyna się właściwa procedura rozpoznawania wciśniętych klawiszy i 
nadawania wartości komórkom „cchar1”... „cchar4”. Pamiętajmy o tym, że funkcja jest uniwersalna i 
wykorzystywana zarówno w trybie wyłączenia alarmu jak i w trybie załączenia. Tryby te różnią się pomiędzy 
sobą przede wszystkim tym, że w stanie załączenia aktywne jest przerwanie Timer’a 0 przeglądające stan 
czujników. W związku z tym rozkaz „brid read_code_next” powoduje natychmiastowe przejście do funkcji 
interpretacji klawiszy wówczas, gdy nie jest załączona obsługa przerwania. Zrobiłem tak po to, aby wartość 
zmiennej „sensors” nie wpływała na stan alarmu. Dlaczego? Prześledźmy dalsze linie programu. 
Sekwencja rozkazów  
 mov 

temp,sensors 

 cpi 

temp,SENSORSOFF 

sprawdza, czy któryś z czujników alarmu jest aktywny. Obojętnie czy w stanie wyłączenia, czy załączenia 
podejmowana jest akcja na podstawie stanu zmiennej „sensors”! W związku z tym możliwe jest uaktywnienie 
sygnalizacji dźwiękowej i powiadomienia SMS w stanie wyłączenia alarmu. Omawiane wcześniej polecenie „brid” 
ma urządzenie przed tym uchronić.  

 

- Strona 5 z 14 - 

background image

http://www.easy-soft.tsnet.pl 

Również w tej funkcji konieczne jest jednokrotne zainicjowanie wartości „goon” i załączenie przerwań Timer’a 1 
w celu odmierzania czasu opóźnionego załączenia. Inicjacja przeprowadzana jest w zależności od stanu flagi T. 
Rozkaz „brts read_code_act” omija polecenia nadające wartości zmiennym w przypadku, gdy flaga jest 
ustawiona. Polecenia „set” ustawia flagę T po przeprowadzeniu inicjalizacji. 
 

Załączenie alarmu.

 Na listingu 4 umieściłem fragment kodu źródłowego programu odpowiedzialny za obsługę 

uaktywnienia alarmu. Rozpoczyna się ona od etykiety „alarm_active” zestawem rozkazów testujących stan 
zmiennej „goon” odmierzającej czas do załączenia alarmu. Jeśli wartość „goon” jest mniejsza lub równa 
„DELAYTIME”, to nie jest podejmowana żadna akcja. Jeśli wartość „goon” jest większa od „DELAYTIME”, rozkaz 
„sbi portb,ALARMOUT” załącza sygnalizację dźwiękową a polecenie „rcall send_SMS” wywołuje podprogram 
wysyłający SMS pod zaprogramowany i zapamiętany w EEPROM numer telefonu. SMS będzie wysłany, o ile bit 
0 zmiennej „sms_sent” nie jest ustawiony. Dodatkowo blokowane są przerwania, co powoduje zaniechanie 
sprawdzania stanu czujników oraz odmierzania czasu. Alarm pozostaje załączony do momentu wprowadzenia 
kodu wyłączenia lub odłączenia napięcia zasilania.  
 
 
;----------------------------------------------------------------------------- 
;alarm aktywny - sygnalizacja dźwiękowa, powiadomienie za pomocą SMS, 
;oczekiwanie na kod wyłączenia 
;----------------------------------------------------------------------------- 
alarm_active: 
 mov 

temp,goon 

 subi 

temp,DELAYTIME 

 ;sprawdzenie,czy 

upłynął już czas opóźnienia 

 brsh 

active_and_on 

 rjmp 

active_exit 

active_and_on: 
 cli 

   ;wyłączenie przerwań - już nie są potrzebne 

 sbi 

portb,ALARMOUT 

 ;załączenie wyjścia alarmu 

 tst 

smssent 

  ;jeśli wysyłano już SMS,to nie wysyłaj powtórnie 

 brne 

active_exit 

 rcall 

send_SMS  ;wysłanie sms z powiadomieniem 

active_exit: 
 ret 
 
Listing 4. Procedura obsługi załączenia alarmu. 
 
 

Wysyłanie SMS. 

 
Wysyłanie wiadomości SMS przez mikrokontroler to pytanie bardzo często pojawiające się w listach 
kierowanych do Redakcji oraz na grupach dyskusyjnych w Internecie, dlatego też poświęcę mu nieco czasu. 
Oba z posiadanych przez mnie modemów GSM obsługują dwa tryby przesyłania wiadomości SMS. Tryby te 
oznaczone są numerami 0 i 1. Odpowiedź Twojego telefonu lub modemu na rozkaz „AT+CMGF?” lub 
„AT+CMGF=?” będzie zawierać listę obsługiwanych trybów pracy. Ja dla swojej aplikacji wybrałem tryb 1, 
wygodniejszy i wolę nie wyrażać swojej opinii na temat kodowania wiadomości w trybie 0, zwanym również 
„PDU mode”. 
Podane poniżej informacje opracowane zostały na podstawie dokumentacji firmy SIEMENS dla modemu GSM 
M20. Zainteresowanym poszerzeniem swojej wiedzy na ten temat odsyłam szczególnie do czterech źródeł: 

1.  Dokumentacji modemu M20 SIEMENS dostępnej na stronie producenta pod nazwą 

„sms_guid_v1_0.doc”. Autorem jest T.Schuh 

2.  Noty aplikacyjnej umieszczonej pod adresem „http://www.mcselec.com/an_31.htm” . Autorem jest 

Vilko Sustić. 

3.  Noty aplikacyjnej umieszczonej pod adresem „http://www.mcselec.com/an_117.htm”. Autorem jest 

Warren Read. 

4.  Informacji zawartych na stronie internetowej http://www.dreamfabric.com/sms/ 

 
Mode 0 (PDU).  
W tym trybie na twórcę aplikacji spada obowiązek zakodowania całej informacji dotyczącej wysyłanej 
wiadomości. Spójrzmy na przykład zaczerpnięty z materiałów firmy SIEMENS przesyłający wiadomość o treści 
„THE BIG BROWN FOX” pod numer telefonu +991234567. 

 

- Strona 6 z 14 - 

background image

http://www.easy-soft.tsnet.pl 

 
 

03 

91 

0100 

11 

00 

09 

91 

99214365F7 

00 

00 

FF  11 

546411244C1E4142E9F3EA94199F58 

D

ługo

ść

 pola SCA 

Typ SCA 

Pole numeru S

C

Pi

erwszy okte

 

D

ługo

ść

 nu

me

ru

 

odbiorcy 

Typ num

eru 

Numer odbiorcy 

wiadomo

ści

 S

M

Iden

ty

fi

ka

to

prot

oko

łu 

Sche

ma

t kodowania 

danych 

Okres wa

żno

ści SMS 

D

ługo

ść

 te

kst

u

 

Tekst 

D

ługo

ść

 p

o

la

 nu

m

eru

 ce

n

trum

 u

ug w bajt

ach  

(mo

żna poda

ć 00)

 

91 – numeracj

a z num

ere

m

 k

ierunkowym 

kraju, 81 – bez num

eru kieru

n

kowego 

0100 = 1

000 (

zam

ie

niona po

zyc

ja c

yfr)

 

Pi

erwszy

 o

kte

sta

tus

u wi

ado

m

ci SMS (11

H

 to 

warto

ść

 typow

a dla wi

ększo

ści

 wi

adomo

ści

Numer odniesienia dla wiadomo

ści SMS. Na

le

ży 

wprowadzi

ć warto

ść

 0 

D

ługo

ść

 n

u

mer

u

 odbiorcy w bajtach  

Podobnie jak w przypadku typ

u

 SCA – 91 lub 81 

Numer odbiorcy SMS: cyfry s

ą zamienian

miejscami a w 

przypadku gdy zawiera on 

nieparzyst

ą liczb

ę cyfr, na ko

ń

cu dodawa

ne 

jest 

F.

 (

123 

Æ

 123

Æ

 21F

3)

 

0x00 – dos

tarc

z jako norm

alny SMS 

0x00 – a

lfabe

t dom

lny, 7

-bitowe znaki AS

CII 

0xF

F = 255 – 192 t

ygodnie

 = 63 t

ygodnie

 

Szesn

astkowo podana liczba bajtów oktetó

tek

stu 

THE BIG BROWN FOX 

 
Wyjaśnijmy znaczenie poszczególnych pól wiadomości SMS. 
1. Długość pola SCA jest opcjonalną dla niektórych telefonów. Jest to podana szesnastkowo liczba oktetów 

numeru Centrum Usług. Większość telefonów umożliwia wprowadzenie w tym miejscu wartości 0x00, więc 
nie trzeba podawać i tym samym znać tego parametru. 

2.  Typ numeru Centrum Usług podanie wartości 91 oznacza numerację międzynarodową (np. z prefix +48 dla 

Polski), 81 to numeracja lokalna, obowiązująca na terenie danego kraju  

3.  Numer Centrum Usług to numer podany przez operatora, dzięki któremu możliwe jest przesyłanie 

wiadomości SMS. Np. dla sieci Plus GSM jest to numer +48601000100, Zwróćmy uwagę na sposób 
kodowania tego numeru. Na przykład numer „601 000100” zakodowany będzie w sposób następujący: 

Numeracja krajowa, bez numeru kierunkowego: 81 

 Nieparzysta liczba znaków – na końcu dodawana jest litera F, więc numer 
przyjmie postać „601000100F” 

Numer po kodowaniu będzie wyglądał następująco: „06010010F0”. 

 
4.  Pierwszy oktet komunikatu SMS  

 
TP-RP – ścieżka (numer) nadawcy; ustawienie bitu oznacza, że ścieżka dla odpowiedzi na wysłany SMS 
jest ustawiona 
TP-UDHI – ustawienie bitu oznacza, że przesyłane dane użytkownika rozpoczynają się od nagłówka 
identyfikującego 
TP-SRR – ustawienie tego bitu oznacza, że nadawca żąda raportu na temat odbioru wiadomości SMS przez 
odbiorcę 
TP-VPF – bity określające format okresu ważności wiadomości SMS: 
  

0 0 : TP-VPP nieobecne 

  

1 0 : TP-VPP obecne, format relacyjny (0..143 = (wartość parametru + 1) x 5 minut, 144..167 =  

  

12 godzin + (wartość parametru - 143) x 30 minut, 168..196 = (wartość parametru – 166) x 1 dzień, 

  

197..255 = (wartość parametru – 192) x 7 dni) 

  

0 1 : format rozszerzony, 7 oktetów 

  

1 1 : format absolutny, 7 oktetów 

TP-RD – ustawienie bitu powoduje, że duplikaty wiadomości są odrzucane 
TP-MTI – typ komunikatu: wartość bitów 0 1 powoduje, że wiadomość przesyłana jest w trybie  
SMS-SUBMIT 

Numer bitu 

Nazwa bitu 

TP-RP 

TP-UDHI 

TP-SRR 

TP-VPF 

TP-VPF 

TP-RD 

TP-MTI 

TP-MTI 

 

- Strona 7 z 14 - 

background image

http://www.easy-soft.tsnet.pl 

5. Pole 

statusu 

określające numer odniesienia dla wysyłanego komunikatu; wpisanie wartości 0x00 powoduje, 

że numer telefonu, z którego wysyłamy SMS jest równocześnie numerem odniesienia. 

6. Długość numeru odbiorcy SMS, podana w ilości bajtów numeru. 
7.  Typ numeru odbiorcy SMS (81 lub 91). 
8.  Numer odbiorcy wiadomości SMS (kodowany w ten sam sposób, co numer Centrum Usług). 
9. Identyfikator 

protokołu komunikacyjnego. Wartością typową, używaną przez większość sieci telefonów 

komórkowych jest 0x00. 

10.  Schemat kodowania danych. Wprowadzona wartość 0x00 oznacza, że znaki kodowane są w postaci 7-

bitowych znaków ASCII. 

11. Okres ważności wiadomości SMS. Liczba podana i interpretowana zgodnie z kodem reguły podanym przez 

bity TP-VPF. 

12.  Liczba oktetów bajtów tekstu. 
13. Tekst wiadomości 

 

Wiadomość SMS zgodnie ze specyfikacją organizacji ETSI (

http://www.etsi.org

) może mieć do 160 znaków 

długości, gdzie każdy znak zakodowany jest w postaci kodu 7-bitowego. Znaki o kodach długości 8-bitów 
zazwyczaj nie są przez telefony wyświetlana, natomiast czasami używane są jako sterujące (przesyłanie 
obrazów, dzwonków itp.). Komunikaty zakodowane w postaci liczb 16-bitowych (maksymalnie 70 znaków) 
używane są do przesyłania komunikatów zakodowanych według standardu UNICODE (UCS2) i mogą być 
wyświetlane przez większość aparatów GSM. Niektóre z telefonów wyświetlają te komunikaty jako FLASH SMS. 
My zajmiemy się kodowaniem standardowym, gdy kody znaków mają długość 7 bitów. Prześledźmy sposób 
kodowania tekstu na przykładzie: zakodujmy wiadomość „ELEKTRONIKA”. 
Tekst „ELEKTRONIKA” zawiera 11 znakÓW nazywane septetami ze względu na swą długość – 7 bitów. My 
musimy zmienić sposób kodowania z septetów na oktety – znaki o długości 8 bitów. 
 

0x45 

0x4C 

0x45 

0x4B 

0x54 

0x52 

0x4F 

0x4E 

0x49 

0x4B 

0x41 

1000101  1001100  1000101  1001011  1010100  1010010  1001111  1001110  1001001  1001011  1000001 
1000101  1001100  1000101  1001011  1010100  1010010  1001111  1001110  1001001  1001011  1000001 
 
Pierwszy septet (E) zamieniany jest na oktet poprzez „zabranie“ najmniej znaczącego bitu następnego w 
kolejności znaku i wprowadzenie go na pozycję bitu 7 (0 + 1000101 = 01000101 Æ 0x45). Po tej operacji bit 
jest usuwany, więc następne przekształcenie (L) zabierze dwa bity z kolejnego znaku, kolejne trzy i tak dalej. W 
konsekwencji znak ósmy zostanie całkowicie usunięty. Dla znaku numer dziewięć proces rozpocznie się od 
początku. 
 
01000101  01100110  01110001  01001001  10010101  00111110  10011101    11001001  01100101  00010000 

0x45 

0x66 

0x71 

0x49 

0x95 

0x3E 

0x9D 

 

0xC9 

0x65 

0x10 

 
Jako przykład zakodowaną wiadomość „ELEKTRONIKA” i wyślijmy na numer sieci PLUS. Centrum wiadomości 
(SCA) ma tutaj numer +48601000310. Prześlijmy wiadomość na numer +48605010203. 

1. Długość pola SCA (w tym przypadku 7 bajtów, z polem typu SCA): 07 
2.  Typ SCA - numeracja międzynarodowa: 91 
3.  Numer SCA: 8406010013F0 
4. Pierwszy 

oktet 

wiadomości SMS: 11 

5. Pole 

statusu: 

00 

6. Długość numeru odbiorcy SMS (liczba bajtów): 07 
7.  Typ numeru odbiorcy – numeracja międzynarodowa: 91 
8.  Numer odbiorcy: 8496959192F3 
9. Identyfikator 

protokołu: 00 

10.  Schemat kodowania: 00 
11. Okres ważności (1 tydzień): BF 
12. Długość tekstu: 0x0A 
13. Tekst: 45667149953E9DC96510 

Uff... Zbierzmy to w całość: 07918406010013F0110007918496959192F30000BF0A45667149953E9DC96510 
Niestety – oprócz znajomości długości niektórych ze składników wiadomości, aby ją wysłać musimy jeszcze 
znać jej całkowitą długość. W naszym przykładzie wynosi ona 32 bajty. Zestaw poleceń, które musimy wydać 
modemowi aby wysłać wiadomość, będzie następujący: 

1. AT+CMGF=0 

<CR> 

2. AT+CMGS=32 

<CR> 

3. >07918406010013F0110007918496959192F30000BF0A45667149953E9DC96510 

<CTRL+Z> 

Uwaga: wyżej wymienione znaki są reprezentacją bajtów o wartości zakodowanej szesnastkowo. Cyfra „32” jest 
długością przesyłanej informacji podaną w bajtach. Podany przykład kodowania jest właściwy dla informacji 
wprowadzanej przez interfejs komunikacyjny. Inaczej wysyła się wiadomość, gdy numer Centrum Usług 
znajduje się na karcie czy też gdy wysyłana jest wiadomość zapamiętana w pamięci telefonu lub karty SIM. 
 

 

- Strona 8 z 14 - 

background image

http://www.easy-soft.tsnet.pl 

Mode 1 (TEXT MODE). 
W przeciwieństwie do swojego poprzednika , tryb 1 zwany również TEXT MODE jest bardzo łatwy w użyciu. 
Poniższa sekwencja poleceń wysyła identyczną wiadomość jak wyżej w trybie tekstowym: 

1. AT+CMGF=1 

<CR> 

2. AT+CMGS=”+48605010203” 

<CR> 

3. >ELEKTRONIKA<CTRL+Z><CR> 

Trybem tym posłużyłem się tworząc funkcję „send_SMS”. Niestety, nie wszystkie telefony GSM będą ten tryb 
obsługiwać. 
 
Funkcja wysyłająca wiadomość SMS: „send_sms”. 
Na listingu 4 umieściłem kod źródłowy funkcji wysyłającej wiadomość SMS. Część wiadomości docierającej do 
adresata jest stała, zdefiniowana w programie. Część wiadomości taka, jak lokalizacja obiektu i opis czujnika 
jest zmienna i może być zdefiniowana przez użytkownika. Definicja zostaje zapamiętana w pamięci EEPROM i 
jest używana przy kompozycji wiadomości. Przeanalizujmy listing 4. 
 

send_SMS:  
 ldi 

zl,LOW(send_sms_1<<1) 

 ;Z 

= adres nastawy-polecenia w ROM 

 ldi 

zh,HIGH(send_sms_1<<1) 

 

rcall 

putf 

 

 

 

;wysłanie polecenia 

 rcall 

gets 

   ;pobranie 

odpowiedzi 

modemu 

 ldi 

zl,LOW(send_sms_2<<1) 

 

;Z = adres napisu w ROM 

 ldi 

zh,HIGH(send_sms_2<<1) 

 

ldi 

yl,LOW(buffer)   

 

;Y = adres bufora w RAM 

 clr 

yh 

   ;tu 

adresy 

RAM 

mogą być tylko 1-bajtowe 

 

rcall 

move_rom2ram   

 

;przepisanie danych z ROM do RAM,  

  

 

 

 

 

 

;adresy ROM w Z,RAM w Y 

 ldi 

eeaddr,SMSNUMBER_EEADDR 

;teraz 

pobranie numeru telefonu z eeprom do "buffer", 

 

 

 

     ;na 

który 

wskazuje 

 

rcall 

ee_read2buf 

 

 

;uwaga: zmieniany jest rejestr Y 

 
 ldi 

temp,0x22 

  ;cudzysłów zamykający 

 st 

y,temp 

 rcall 

st_EOL 

   ;zapisanie znaków CR+LF do bufora 

 rcall 

puts_buffer 

  ;wysłanie zawartości "buffer" przez UART 

 

 

 

 

 

 

;teraz kompozycja SMS do wysłania 

 ldi 

zl,LOW(send_sms_3<<1) 

 ;odczyt 

części "stałej" z ROM i EEPROM 

 ldi 

zh,HIGH(send_sms_3<<1) 

 ldi 

yl,LOW(buffer) 

 clr 

yh 

 rcall 

move_rom2ram 

 

 

ldi 

eeaddr,SMSTEXT_EEADDR 

;teraz odczyt opisu obiektu (30 znaków wprowadzone 

   

 

 

 

 

 

‘przez użytkownika) 

 rcall 

ee_read2buf 

 ldi 

temp,',' 

   ;do 

temp 

kod 

przecinka 

 st 

y,temp 

   ;zapisanie 

go 

buforze 

 clr 

temp 

   ;wyliczenia 

adresu 

etykiety 

jej 

odczyt 

(jeśli czujnik  

 

 

 

     ;jest 

aktywny,to 

bit 

send_SMS_sen: 
 inc 

temp 

   ;przyjmuje 

wartość "0") 

 

clc 

 

 

 

 

;kasowanie flagi "carry" 

 ror 

sensors 

   ;przeniesienie 

najmłodszego bitu do C 

 brcs 

send_SMS_sen 

  ;jeśli C jest "1",to wejście nie jest aktywne 

 mov 

eeaddr,temp 

 rcall 

sen_ee_addr 

  ;wyznaczenie 

adresu 

eeprom 

 

inc 

yl 

 

 

 

;odczyt etykiety wejścia do bufora w RAM 

 rcall 

ee_read2buf 

 ldi 

temp,0x1A 

  ;zapamiętanie znaku "Ctrl+Z" 

 st 

y,temp 

 rcall 

st_EOL 

   ;zapisanie 

kodów 

CR+LF 

 rcall 

puts_buffer 

  ;wysłanie zawartości "buffer" przez UART 

 inc 

smssent 

   ;ustawienie 

znacznika 

wysłania SMS 

 

 

 

 

 ret 
 
Listing 5. Procedura wysyłania wiadomości tekstowej SMS. 
 
Jako pierwsze wysyłane jest do modemu polecenie zapisane w pamięci ROM zdefiniowane pod etykietą 
„send_sms_1”. Jest to polecenie załączenia trybu tekstowego „AT+CMGF=1”. Uwaga! Zarówno polecenie 
wyświetlające listę dostępnych trybów jak i załączające konkretny tryb pracy działa dopiero po włączeniu się 
telefonu do sieci. Każde polecenie musi być zakończone znakiem CR (0x0D). Za przesłanie polecenia z ROM 
odpowiedzialna jest funkcja o nazwie „putf”. Różni się ona od „puts” tym, że dane wysyłane przez UART pobiera 

 

- Strona 9 z 14 - 

background image

http://www.easy-soft.tsnet.pl 

z ROM a nie bufora w pamięci RAM. W następnej kolejności przesyłany jest do modemu numer telefonu, 
którego stała część zdefiniowana jest pod etykietą „send_sms_2” a zmienna, wprowadzana przez użytkownika, 
pobierana jest z EEPROM. Polecenie zawierające numer telefonu adresata wiadomości komponowane jest w 
pamięci RAM i przesyłane do modemu przez funkcję „puts”. Podobnie tworzona jest wiadomość tekstowa: 
komponowana w RAM z części stałej „send_sms_3”, tekstu – lokalizacji obiektu wprowadzonej przez 
użytkownika oraz etykiety czujnika wyliczanej na podstawie zawartości zmiennej „sensors” (zmienna ta 
przesuwana jest w prawo z użyciem flagi przeniesienia C do momentu aż flaga ta zostanie wyzerowana; 
logiczne „0” oznacza stan aktywny czujnika – liczba przesunięć liczona wskazuje na numer wejścia). Tekst musi 
być zakończony znakiem CTRL+Z. Jest to dobrze znany nam znak końca zbioru tekstowego o kodzie 26 (0x1A). 
 
 

Montaż. 

 

Całość zmontowana została na dwóch płytkach jednostronnych: po jednej dla klawiatury i układu sterującego. 
Konstrukcja alarmu jest bardzo prosta a jej montaż nie powinien sprawiać trudności nawet początkującemu 
elektronikowi. Montaż rozpoczynamy od wlutowania łączówek – ja wykonywałem je przy pomocy drutu 
„srebrzanki”. Później elementy bierne – rezystory i kondensatory, półprzewodniki a na końcu układ 
mikrokontrolera. Mikrokontroler nie musi być zaprogramowany. Dolutowując do jego wyprowadzeń złącze 
można zaprogramować go już w układzie. Tak właśnie uruchamiałem swój układ. 
Rezystory R1 do R8 należy dobrać w zależności od posiadanych czujników. Wartość 1k jest właściwą dla 
napięcia wejściowego od 9 do 12V i transoptorów LTV849. Dla PC849 firmy SHARP można użyć rezystorów o 
większej wartości. Wartość rezystancji można oszacować na podstawie wzoru: 

(Napięcie czujnika – 1,5) : 0,01 = Rezystancja w Ohm 

Program napisany został w taki sposób, że za aktywny uważany jest stan, gdy na wejściu pojawi się napięcie. W 
przypadku odwrotnym wymagane jest zanegowanie wartości zmiennej „sensors” po odczycie czujników. W 
takiej sytuacji wystarczy w procedurze obsługi przerwania Timer’a 0 na końcu dodać polecenie „neg sensors”. 
Zarówno klawiatura jak i wyświetlacz podłączone zostały z użyciem złącz zaciskanych o nazwie IDC. 
Wyświetlacz wymaga złącza o 16 wyprowadzeniach, klawiatura o 10. Oczywiście złącza można zastąpić 
przewodami. Stabilizator 7805 dobrze jest umieścić na niewielkim radiatorze. Jego temperatura będzie zależeć 
bardzo mocno od modelu użytego wyświetlacza oraz doprowadzonego napięcia wejściowego. Ja użyłem 
zgodnego z LCD wyświetlacza VFD, który charakteryzuje się dosyć dużym poborem prądu i przez to stabilizator 
bardzo mocno nagrzewał się w czasie pracy (wyświetlacz pobiera około 0,3A co przy napięciu zasilającym 12V 
daje moc traconą przeszło 2W). Układ powinien być zasilany napięciem stałym o wartości co najmniej 8V i nie 
więcej niż 15V. 
Jeśli chcemy wykorzystać modem GSM (na przykład WAVECOM), na płytce montujemy złącze DSUB-9 męskie 
(szpilki). Jest ono właściwe dla urządzenia sterującego transmisją. Do złącza tego wprost dołączamy kabel 
modemu. 
Elementem wykonawczym jest przekaźnik z cewką na napięcie 5V. W modelu używałem przekaźnika firmy ITT 
o oznaczeniu RZ2H-5. Styki przekaźnika, podobnie jak wejścia czujników alarmu, wyprowadzone są przez 
złącza terminatory o rastrze 3,5mm („pod śrubkę”) umożliwiające wygodne podłączenie i rozłączenie układu. 
Karta SIM musi być przygotowana do pracy. To znaczy musi zawierać poprawny numer centrum serwisowego 
oraz być aktywna. Programowanie parametrów karty można wykonać bądź to z użyciem programu terminala, 
bądź to umieszczając kartę w zwykłym telefonie GSM. 
 
 

Użytkowanie alarmu. 

 

Po pierwszym załączeniu użytkownik musi przeprowadzić procedurę nastaw. Proszę pamiętać o tym, że interfejs 
użytkownika jest bardzo skromny, ponieważ ilość pamięci programu, którą dysponuje mikrokontroler również 
jest bardzo mała. 
Jako pierwszy należy wprowadzić kod wyłączenia alarmu. Może i powinien on być inny od kodu załączenia. 
Wprowadzamy 4 cyfry – w tym momencie zmienna „visible” ma wartość „UCANSEE” i można odczytać 
wprowadzane znaki. Kod zawiera 4 cyfry, po których wprowadzeniu użytkownik zostanie poproszony o 
akceptację przez naciśnięcie klawisza ENTER (w prawym, dolnym rogu klawiatury) lub możliwe jest powtórne 
wprowadzenie innego (?) kodu po naciśnięciu klawisza CLR (środek dolnego rzędu klawiatury). Później w 
identyczny sposób wprowadzamy kod wyłączenia i numer PIN dla karty telefonu GSM. Teraz następuje pytanie 
o numer telefonu, na który wysyłane będą SMS. Należy wprowadzić go łącznie z numerem kierunkowym kraju, 
na przykład „48605010203”. Procedura wprowadzania numeru telefonu jest wspólna z tą przeznaczoną do 
wprowadzania tekstu: dłuższe przytrzymanie klawisza powoduje wprowadzenie litery. Proszę zwrócić uwagę na 
to, aby wprowadzić wyłącznie cyfry. W przypadku pomyłki, kasowanie jest możliwe przez naciśnięcie klawisza 
CLR. Numer zostaje zapamiętany po naciśnięciu ENTER. 
Następnie użytkownik pytany jest o część opisową dla SMS. Przeznaczona jest ona dla krótkiego opisu 
lokalizacji, na przykład „JAGIELLOŃSKA 2/3”. Można wprowadzić do 28 znaków. Dodatkowo należy podać opisy 
dla wejść poszczególnych sensorów, na przykład 1 – „OKNO”, 2 – „DRZWI” itp. Zalecam aby wprowadzić 
cokolwiek, co pozwoli zidentyfikować wejście czujnika – chociażby numer 1, 2, 3 itp. Na etykietę – opis wejścia 
czujnika, przeznaczone jest 8 znaków. Jeśli nie zostaną wprowadzone żadne dane tekstowe, program zapisze 
pod adresem łańcucha znaków w EEPROM znak jego końca. Mogą się wówczas pojawić błędy przy kompozycji i 
wysyłaniu wiadomości SMS. Wprowadzanie tekstu kończy krótkie przyciśnięcie klawisza ENTER.  Proszę nie 
przytrzymywać go przez czas dłuższy niż 1 sekunda. 
Na rysunku 1 umieściłem opis klawiatury. Tekst wprowadzany jest podobnie jak przy pisaniu wiadomości SMS w 
telefonie komórkowym. Dłuższe przytrzymanie klawisza, powoduje wyprowadzenie kolejnych znaków. I tak dla 

 

- Strona 10 z 14 - 

background image

http://www.easy-soft.tsnet.pl 

przykładu pod klawiszem „1” ukryte są litery A, B i C oraz oczywiście cyfra 1. Zwolnienie klawisza powoduje 
przesunięcie kursora na następną pozycję po upływie czasu około 1 sekundy. 
Po wprowadzeniu nastaw alarm przejdzie do pracy w trybie wyłączonym. Podanie kodu załączenia spowoduje, 
że odmierzony zostanie czas 30 sekund a następnie alarm przejdzie do trybu czuwania. W tym czasie widać 
migotanie diody LED co 1 sekundę i pojawia się komunikat „czekaj...”, chociaż bardziej na miejscu byłby napis 
„uciekaj!”. Jest to jednak napis wspólny dla różnych funkcji, nie było miejsca w pamięci ROM na bardziej 
sugestywne komunikaty. 
Pojawienie się napięcia na wejściu czujnika powoduje, że na kolektorze tranzystora pojawi się stan niski. Jest 
on interpretowany przez mikrokontroler jako uaktywnienie alarmu. Od momentu pojawienia się stanu niskiego 
CPU zaczyna odmierzać czas 30 sekund i jeśli w tym czasie nie zostanie wprowadzony kod wyłączenia, 
załączany jest przekaźnik oraz wysyłane powiadomienia SMS. Alarm jest załączony aż do momentu odłączenia 
napięcia zasilania lub wprowadzenia kodu wyłączenia. Podobnie jak poprzednio, odmierzanie czasu 
sygnalizowane jest przez migotanie diody LED. 
Gdy alarm znajduje się w trybie wyłączenia, możliwe jest ponowne wprowadzenie nastaw. Nastawy wykonane 
poprzednio i zapisane w EEPROM są zamazywane a na ich miejsce zapisywane są nowe, wprowadzane przez 
użytkownika. Nie istnieje więc możliwość modyfikacji nastaw – należy podać je wszystkie na nowo. Aby wejść 
do trybu nastaw, w trybie wyłączenia należy wpisać kod „0000” a następnie kod wyłączenia alarmu. Po 
poprawnym jego podaniu, możliwe jest wprowadzenie nastaw. 
 
 

Uwagi. 

Wykaz elementów: 

 

półprzewodniki: 

U1 AT90S2313 

U2 74LS157 

U3 7805 

U4 74HCT14 

U5 MAX232 

ISO1,ISO2 - PC849 SHARP (LTV849 

LITEON) 

D1 

dioda LED czerwona 

D2 dioda 

krzemowa 

średniej  mocy, 

   

np. 1N4007 

D3..D6 dioda 

krzemowa 

małej  mocy, 

  

np. 1N4148 

 

elementy bierne: 

Q1 kwarc 

7,3728MHz 

R1..R8 1k 

R9..R11 10k 

R14, 

R16..R18 33R 

R19 560R 

R20 270R 

R21 750R 

PR1 10..22k 

C1,C2 22p 

C3 10u/16V 

C4..C8 1u/50V 

C9 100u/16V 

C10,C11 100n/63V 

C12 470u/25V 

Z1,Z2,X1..X8 

X10 terminatory 

„pod 

śrubkę” o  

rastrze 3,5mm 

X9 

komplet wtyk wlutowywany 

  

w płytkę, IDC prosty, 16 wypr. +  

gniazdo zaciskane na przewodach 

X11 

komplet wtyk wlutowywany 

  

w płytkę, IDC prosty, 10 wypr. +  

gniazdo zaciskane na przewodach 

X12 złącze DSUB-9/M (męskie) 

X14 złącze dla telefonu komórkowego 

 

inne: 

SW1..SW12 - przyciski zwierne 

RL1 przekaźnik z cewką 5V, np.  

  

ITT RZ2H-5 

LCD1 

wyświetlacz LCD 2x20 

 
Urządzenie alarmowe jest urządzeniem amatorskim i jako takie 
nosi jego znamiona. Jest przykładem aplikacji wykorzystującej 
modem lub telefon GSM do sygnalizacji. Wraz z urządzeniem 
udostępniam również źródło programu i zachęcam do 
samodzielnych jego modyfikacji. Można na przykład usunąć z 
programu możliwość wysyłania w wiadomości SMS etykiet opisów 
czujników a zaoszczędzone w ten sposób miejsce w pamięci 
programu wykorzystać na implementację lepszego interfejsu 
użytkownika lub innego sposobu kodowania wiadomości niż TEXT 
MODE. Można wreszcie pozbyć się procedur komunikacji z 
telefonem GSM i wykorzystywać urządzenie jak zwykłą centralkę 
alarmową. 
Całość programu została wykonana i skompilowana przy pomocy 
AVR STUDIO 4. Jest to kompletne środowisko do pisania i 
uruchamiania aplikacji dla mikrokontrolerów AVR. Do linii RESET, 
MISO, MOSI i SCK mikrokontrolera przylutowałem złącze i przy 
wykorzystaniu programatora ISP programowałem i testowałem 
układ. Jest to bardzo wygodna, nie tylko dla elektronika amatora, 
metoda. Pozwala na uruchamianie aplikacji w rzeczywistym 
środowisku jej pracy. 
Program zajmuje 128 bajtów pamięci EEPROM na zmienne 
definiowane przez użytkownika. Ich wykaz Można znaleźć w tabeli 
2. Kod wynikowy po kompilacji zajmuje 1019 słów dwubajtowych, 
to jest 2038 z 2048 bajtów pamięci programu AT90S2313. 
Niestety, nie ma już zbyt wiele miejsca na implementację nowych 
funkcji lub dłuższych komunikatów. Można je wykonać jedynie 
kosztem usunięcia lub optymalizacji już istniejących. 
 
 
Jacek Bogusz 
jacek.bogusz@easy-soft.tsnet.pl 
 
 
 
 

 

- Strona 11 z 14 - 

background image

http://www.easy-soft.tsnet.pl 

 

Etykieta adresu 

Adres zmiennej 

w EEPROM 

Opis 

STATUS_EEADDR 
 
ONCODE_EEADDR 
OFFCODE_EEADDR 
PINNUMBER_EEADDR 
SMSNUMBER_EEADDR 
 
SENSOR1_EEADDR 
 
SENSOR2_EEADDR 
SENSOR3_EEADDR 
SENSOR4_EEADDR 
SENSOR5_EEADDR 
SENSOR6_EEADDR 
SENSOR7_EEADDR 
SENSOR8_EEADDR 
SMSTEXT_EEADDR 

0x00 

 

0x01 
0x05 
0x09 

0x0D 

 

0x1B 

 

0x23 
0x2C 
0x35 
0x3E 
0x47 
0x50 
0x59 
0x62 

Komórka, w której zapamiętany jest status alarmu (załączony = 
0xF0, wyłączony = 0x0F) 
Kod załączenia alarmu w postaci 4 kodów znaków ASCII 
Kod wyłączenia alarmu w postaci 4 kodów znaków ASCII 
Numer PIN telefonu, również 4 znaki ASCII 
Numer telefonu, na który przesyłane będą powiadomienia SMS; 
zmienna ma długość 12 bajtów – 11 na numer telefonu + 0x00 
Etykieta wejścia czujnika 1; zmienna ma długość 9 bajtów – 8 na 
opis + 0x00 
Etykieta wejścia czujnika 2, jak wyżej 
- / / -      3 
- / / -      4 
- / / -      5 
- / / -      6 
- / / -      7 
- / / -      8 
Tekst komunikatu SMS przeznaczony do zidentyfikowania obiektu, 
na przykład ulica + numer domu; długość 28 bajtów – 27 na tekst + 
0x00 

Tabela 2. Wykaz adresów zmiennych umieszczonych w pamięci EEPROM 
 
 
;stałe związane z wyświetlaczem 
.equ ENABLE 

 

 

= 7 

 

;numer bitu portu b dla linii ENABLE wyświetlacza LCD 

.equ REGSEL 

 

 

= 4 

 

;numer bitu portu b dla linii R/S wyświetlacza LCD 

 
;stałe związane z UART i tablicami danych 
.equ 

CR  

 

= 0x0A   

;kod znaku powrotu kursora 

.equ 

LF  

 

= 0x0D   

;kod znaku nowej linii  

.equ 

EOF  

 

= 0x1A   

;kod znaku końca zbioru tekstowego 

.equ 

EOD  

 

= 0x00   

;koniec danych (tabeli, tekstu itp) 

 
;stałe związane z klawiaturą 
.equ 

COLUMN1  

= 4 

 

;numer bitu portu b 1 kolumny klawiatury 

.equ 

COLUMN2  

= 5 

 

;numer bitu portu b 2 kolumny klawiatury 

.equ 

COLUMN3  

= 6 

 

;numer bitu portu b 3 kolumny klawiatury 

.equ 

NOKEY    

= 0xFF   

;jeśli "char" zwracany przez funkcję odczytu klawiatury 

 

 

    ;przyjmuje 

wartość NOKEY, oznacza to, że nie jest 

 

 

    ;wciśnięty żaden klawisz 

.equ 

CLRKEY   

= 10 

 

;umowny kod klawisza "CLR" 

.equ 

ENTERKEY 

= 11 

 

;umowny kod klawisza "ENTER" 

.equ 

UCANSEE  

= 0xFF   

;stała dla "visible" oznacza, że wprowadzane znaki  

  

 

 

 

 

;można czytać 

.equ 

UCANTSEE  

= 0x00   

;stała dla "visible" oznacza, że wprowadzanych znaków nie  

  

 

 

 

 

;można czytać (wyświetlany jest znak zastępczy *) 

;stałe stanu alarmu 
.equ 

ALARMON  

= 0x0F   

;status alarmu - załączony 

.equ 

ALARMOFF  

= 0xF0   

;status alarmu - wyłączony 

.equ 

ALARMACTIVE = 0x55 

 

;status alarmu – sygnalizacja (nie używany) 

.equ 

ALARMOUT  

= 6 

 

;bit wyjścia portu b sterujący załączeniem alarmu 

.equ 

HIGHNIBBLE 

= 6 

 

;bit wyjścia portu D sterujący wyborem połówki bajtu 

czujników 
.equ SENSORSOFF  = 

0xFF 

 

;wartość zmiennej „sensors” oznaczająca, że żaden  

  

 

 

 

 

;z czujników nie jest aktywny (wyzwolony przez warunek 

 

 

    ;alarmu) 

.equ DELAYTIME 

30  

;czas 

opóźnienia do zadziałania alarmu (w sekundach) 

.equ TIM1RLDH 

0xE3 

.equ TIM1RLDL 

0xDF 

 

;stałe do odświeżania zawartości Timer'a 1 (częstotliwość  

 

 

 

    ;wywoływania przerwania to 1 Hz) 

;++++++++++++++++++++++++++++ 
;teksty do wyświetlenia 
;++++++++++++++++++++++++++++ 
;tekst powitania 
welcome1: .db 

  "ALARM+SMS",EOD 

 
;teksty statusu 
whenoff: .db 

  "ALARM 

WYLACZONY",EOD 

whenon:  .db 

 "ALARM 

AKTYWNY",EOD 

 
;teksty menu nastaw 
set_1: 

 .db 

 "Kod 

zalaczenia?",EOD 

 

 

- Strona 12 z 14 - 

background image

http://www.easy-soft.tsnet.pl 

 
set_2: 

 .db 

 "Kod 

wylaczenia?",EOD 

set_3: 

 .db 

 "Kod 

PIN 

modemu?",EOD 

set_4: 

 .db 

 "Telefon 

dla 

SMS?",EOD 

set_5:   

.db 

 

"Tekst SMS (30 zn.)?",EOD 

set_6:   

.db 

 

"Tekst wej. (8 zn.)?",EOD 

set_ok:  

.db 

 

"ENTER=OK,C=popraw   ",EOD 

set_wait: .db 

  "Czekaj...",EOD 

 
;nastawy modemu GSM 
init_modem_1:  .db 

 

"ATZ",CR,LF   ;ten tekst wysyłany będzie przez UART, dlatego 

  

 

 

 

 

 

;kończy się CR+LF 

init_modem_2:  .db 

 

"AT+CPIN=",EOD ;ten tekst będzie przetwarzany przed wysyłką, 

 

 

     ;dlatego 

kończy się EOD 

init_modem_3: .db 

 

"ATE0",CR,LF 

init_modem_5: .db 

 

"AT+CPMS=",0x22,"SM",0x22,CR,LF 

send_sms_1: .db   

"AT+CMGF=1",CR,LF 

send_sms_2: .db   

"AT+CMGS=",0x22,"+",EOD 

send_sms_3: 

.db 

 

"ALARM ZALACZONY W OBIEKCIE ",EOD 

 
;tablica znaków do wprowadzania tekstu, naciśnięciu klawisza odpowiada znak z tablicy 
;kolumna 1 zawiera znaki dla pojedynczego naciśnięcia, 2 dla podwójnego itd. 
chartable: 

.db 

 

'0', 

' ', 

'/', 

'-' 

;kody dla klawisza "0" 

  .db 

 '1', 

'A', 

'B', 

'C' 

;kody 

dla 

klawisza 

"1" 

  .db 

 '2', 

'D', 

'E', 

'F' 

;kody 

dla 

klawisza 

"2" 

  .db 

 '3', 

'G', 

'H', 

'I' 

;kody 

dla 

klawisza 

"3" 

  .db 

 '4', 

'J', 

'K', 

'L' 

;kody 

dla 

klawisza 

"4" 

  .db 

 '5', 

'M', 

'N', 

'O' 

;kody 

dla 

klawisza 

"5" 

  .db 

 '6', 

'P', 

'Q', 

'R' 

;kody 

dla 

klawisza 

"6" 

  .db 

 '7', 

'S', 

'T', 

'U' 

;kody 

dla 

klawisza 

"7" 

  .db 

 '8', 

'V', 

'W', 

'Z' 

;kody 

dla 

klawisza 

"8" 

  .db 

 '9', 

'Y', 

'Z', 

'.' 

;kody 

dla 

klawisza 

"9" 

 
Listing 6. Wykaz stałych używanych w programie 
 
 
 
;definicje zmiennych pomocniczych 
.dseg 
.def 

cchar1  = r02   

 

;kod BCD znaku zwracanego przez funkcję "read_code" /1 

.def 

cchar2  = r03   

 

; j.w. /2 

.def 

cchar3  = r04   

 

; j.w. /3 

.def 

cchar4  = r05   

 

; j.w. /4 

.def visible 

= r06   

 

;zmienna ma wartość 1,gdy wprowadzany kod można odczytać 

.def 

length 

r07 

  ;długość wprowadzanego tekstu dla read_text 

.def sensors 

= r08   

 

;stan sensorów (czujników) alarmu 

.def goon = 

r09 

 

 

;zmienna 

zwiększana o 1 co 1 sekundę przez funkcja 

odmierzająca  
 

 

 

 

    ;czas 

opóźnienia podczas obsługi przerwania Timer’a 1 

.def 

copypb 

r10 

  ;przechowuje 

kopię portu b 

.def 

copypd 

r11 

  ;przechowuje 

kopię portu d 

.def smssent 

r12 

  ;wartość różna od 0 oznacza, że SMS został wysłany 

.def 

temp   = r16   

 

;zmienna pomocnicza 

.def delay1 

 

= r17   

 

;dla procedury delay 

.def delay2 

 

= r18   

 

; - / / - 

.def 

delay3  = r19   

 

;w niej podawany jest argument dla funkcji „delaysec”  

 

 

 

    ;(w 

sekundach) 

.def 

delay   = r20   

 

;główna zmienna dla delay - w niej podawany jest argument  

    

 

 

 

 

;dla funkcji „delayms” (w milisekundach) 

.def 

i = r21    ;zmienna 

pomocnicza 

pętle i iteracje 

.def 

char   = r22   

 

;bufor znaków dla lcd 

.def 

eedata  = r23   

 

;bajt do zapisu w eeprom 

.def eeaddr 

 

= r24   

 

;adres zapisu bajtu w eeprom 

.def 

sbuf 

= r25   

 

;bufor dla pojedynczego znaku odbieranego / wysyłanego 

przez uart 
 
;xp zawiera odciętą, yp rzędną (definicja pokrywa się z "delay") 
.def 

xp  

= R17 

.def 

yp  

= R18 

 
Listing 7. Wykaz definicji rejestrów używanych w programie (zmiennych) 

 

- Strona 13 z 14 - 

background image

http://www.easy-soft.tsnet.pl 

 

1  A  B  C 

 

(0x67) 

 

2  D  E  F 

 

(0x57) 

 

3  G  H  I 

 

(0x37) 

 

 

 

 

 

4  J  K  L 

 

(0x6E) 

 

5  M  N  O 

 

(0x5E) 

 

6  P  Q  R 

 

(0x3E) 

 

 

 

 

 

7  S  T  U  

 

(0x6D) 

 

8  V  W  X 

 

(0x5D) 

 

9, Y, Z, . 

 

(0x3D) 

 

 

 

 

 

0  ,  /  - 

 

(0x6B) 

 

CLR 

 

 

(0x5B) 

 

ENTER 

 

 

(0x3B) 

 
Rysunek 1. Klawiatura (na zielono oznaczono kody zwracane przez funkcję „kbd_read”. 
 

 

- Strona 14 z 14 - 

background image

R1 IN

13

R2 IN

8

T1 IN

11

T2 IN

10

V+

2

V-

6

R1 OUT

12

R2 OUT

9

T1 OUT

14

T2 OUT

7

C1+

1

C1 -

3

C2+

4

C2 -

5

U5
MAX232

C8
1u

C7
1u

C6

1u

C5

1u

VCC

1
3
5
7
9

11
13
15

2
4
6
8
10
12
14
16

X9

C3

10u

VCC

PR1
10k

VCC

D2
1N4007

VCC

1
3
5
7
9

2
4
6
8
10

X11

ZLACZE 2-10

DB4
DB5
DB6
DB7
RS

EN

LED

RXD
TXD

RS
EN

DB5
DB7

DB4
DB6

R17

33

R16

33

R18

33

R14

33

DB4

COL

RS

LED

DB5

DB6

DB7

RXD

TXD

1
6
2
7
3
8
4
9
5

X12
DB9/M

KLAWIATURA

(1,2,3 - WIERSZE; 4,5,7,9 - KOLUMNY)

TERMINAL

WYŚWIETLACZ LCD

GSM

Q1
7,3728MHz

C1

22p

C2
22p

DIR

1A

2

1B

3

1Y

4

2A

5

2B

6

2Y

7

3A

11

3B

10

3Y

9

4A

14

4B

13

4Y

12

A/B

1

G

15

U2

74LS157

DIR

#A
#B
#C
#D
#E
#F
#G
#H

13

12

U4F
74HCT14

11

10

U4E
74HCT14

1

2

3

JP2

1

2

3

JP1

R20

270

R21

750

GSM-TXD
GSM-RXD

15

1

2

16

ISO1A

PC849

14

4

3

13

ISO1B

11

5

6

12

ISO1C

10

8

7

9

ISO1D

15

1

2

16

ISO2A

14

4

3

13

ISO2B

11

5

6

12

ISO2C

10

8

7

9

ISO2D

#A

#B

#C

#D

#E

#F

#G

#H

R11

10k

C4
1u

VCC

RST

RST

R8

1k

1

2

X8

R7

1k

1

2

X7

R6

1k

1

2

X6

R5

1k

1

2

X5

R4

1k

1

2

X4

R3

1k

1

2

X3

R2

1k

1

2

X2

R1

1k

1

2

X1

R10

47k

R9

47k

VCC

D1
LED

9

8

U4D

R19
560

VCC

5

6

U4C

3

4

U4B

1

2

U4A

74HCT14

VCC

VIN

1

VOUT

3

2

GND

U3
7805

C12
470u

C9
100u

C11
0,1u

C10
0,1u

VDD

VCC

1

2

X10

VSS

D3
1N4148

PD6/ICP

11

PD0/RXD

2

PD1/TXD

3

RST

1

XTAL1

5

XTAL2

4

PB7/SCK

19

PB6/MISO

18

PB5/MOSI

17

PB4

16

PB3/OC1

15

PB2

14

PB1/AIN1

13

PB0/AIN0

12

PD5/T1

9

PD4/T0

8

PD3/INT1

7

PD2/INT0

6

U1

AT90S2313

1
2
3
4
5
6

X14

1

2

Z1

1

2

Z2

RL1

LED

D4

1N4148

D5

1N4148

D6

1N4148

COL

background image
background image
background image

1

3

5

7

9

2

4

6

8

10

X11

1

2

3

4

5

6

7

8

9

0

ESC

ENTER

W1-PC6

W2-PC3

W3-PC4

W4-PC5

K3-PC2

K2-PC1

K1-PC0

W2-PC3
K2-PC1

W1-PC6
W4-PC5
W3-PC4
K3-PC2
K1-PC0

background image
background image