PREZENTAREA APLICATIEI
Obiectivul principal al proiectului este realizarea a unui sistem de monitorizare al unor incaperi la distanta folosind reteaua Ethernet . Aplicatia se bazeaza pe un microsistem cu microcontroler C8051F120 pe care va fi implementat un server web accesibil printr-o retea internet sau intranet.
Fig. 10 Schema bloc a aplicatiei
Aplicatia functioneaza in primul rand ca un sistem de monitorizare a unor parametrii tipici unei incinte , cum ar fi :
Contacte usi
Senzori magnetici usi
Senzori de identificare a prezentei prin infrarosu
De asemenea aplicatia poate receptiona semnal video de la camere plasate in diverse puncte ale incaperilor. Toate aceste semnale de intrare sunt preluate si integrate ca variabile dinamice intr-una sau mai multe pagini web, care apoi pot fi vizualizate de aplicatii aflate pe statii client.
Pe de alta parte de la aplicatiile client se pot transmite , tot prin ethernet, setari care apoi vor fi tranformate in comenzi ce vor actiona diferite relee de tensiune.
Practic sistemul poate fi privit ca un automat de comanda si de control in care utilizatorul aflat la distanta pe o statie client joaca rolul factorului decizional. In final s-a dorit implementarea practica a unui sistem de monitorizare Inteligent de avertizare in cazul patrunderii prin efractie dar si de comanda la distanta al anumitor sisteme electrice (usi garaj, porti electrice, lumini in camere, etc).
Aplicatia realizata consta in urmatoarele :
Proiectarea unei interfete de comanda al unor sisteme actionate prin motor electric pe baza unor semnale provenite de la microsistemul cu microcontroler C8051F120.
Proiectarea unor interfete de achizitie a informatiei provenite de la senzor contact si senzor pir pentru microsisitemul cu C8051F120
Proiectarea unei interfete de achizitie a informatiei video provenite de la camerele video.
Implementarea unui server integrat pe microsistem cu C8051F120.
Proiectarea unor functii interfete CGI utilizate la comunicarea informatiilor achizitionate sub forma de variabile, serverului.
Odata stabilita pozitionarea senzorilor de proximitate a contactelor pe usi si a comenzilor utilizatorul are controlul asupra aplicatiei printr-o interfata web .
El accseaza de pe o statie client prin intermediul unui navigator adresa de internet corespunzatoare serverului din microsistem.
Dupa autentificare este afisata fereastra client de tipul celei din figura de mai jos :
Fig.11. Schema bloc a aplicatiei de monitorizare
Fereastra permite in primul rand monitorizarea incaperilor prin afisarea de imagini captate de la fata locului precum si a starii senzorilor. Pe de alta parte aplicatia permite si generarea unor comenzi cum ar fi: activare dezactivare monitorizare precum si comenzi de pornire oprire a unor module electrice ce actioneaza diferite dispozitive.
Schita planului supravegheat este prezentata in figura de mai jos:
Fig. 12. Schema planului supravegheat
Dezvoltarea aplicatiei
1. Descrierea hard a microsistemului
In figura de mai jos este prezentata schema bloc hardware a sistemului.
Fig. 13 Schema bloc hardware a sistemului
Microsistemul creat isi propune citirea starii unor senzori de la distanta, monitorizarea cu ajutorul unei camere video a unei zone delimitate iar in functie de starea acestor parametrii poate actiona anumite dispozitive de iesire globale sau si comunica prin reteaua ethernet cu un client conectat la un server local.
1.1. Unitatea centrala (C8051F120)
Unitatea centrala e realizata cu ajutorul microcontrolerului C8051F120, care are rolul de a gestiona starile intrarilor provenite de la modulul de comunicatie wireless, de a reliza comunicarea cu modulul de camera video si senzorul de declansare al ei, de a comunica cu o magistrala externa nemultiplexata cu modulul ethernet CP2200 si in functie de sistemul decizitional de a actiona elemente de iesire ca : sirena , lampi de control, surse de lumina, etc.
Microcontrolerul este pilotat cu un oscilator cu quartz cu o frecventa de 22,11 MHz. Programarea lui, si depanarea programului se face cu ajutorul interfetei JTAG care se conecteaza direct la pinii microcontrolerului. Aceasta interfata permite, ca prin intermediul unui microcontroler si a controlerului serial-USB, accesul direct din PC la memoria Flash si registrii microcontrolerului.
Comunicatia cu modulul wireless se face prin intermediul unor pini de port paralel iar prin citirea acestora poate fi stabilita starea senzorilor de intrare definiti in 4 zone de lucru. Comunicatia cu camera video si cu modulul de declansare se face cu ajutorul unui pin de port paralel configurat ca linie de intrerupere pentru modulul de declansare al imaginii si cu ajutorul converterului serial MAX3223 pentru comunicatia cu modulul de camera video. Necesitatea acestui convertor din semnale digitale(0-3 V) in semnale diferentiale (+7V / -7V) se datoreaza faptului diferentei tensiunii de alimentare a microcontrolerului (3 V) si a camerei video care este la 5 V. Observand aceasta incompatibilitate de nivele de semnal este necesara conversia lor in semnale diferentiale. Comunicatia cu modulul ethernet se face printr-o magistrala externa nemultiplexata formata din pinii a doua porturi de tip paralel : unul pentru comunicatia datelor si altul pentru transmiterea comenzilor.
Comanda blocurilor de iesiri se face prin intermediul unui port de tip paralel urmand ca aceste semnale sa fie decodate si amplificate de etajele specifice fiecarei iesiri.
1.2. Blocuri de intrari
Este realizat cu un microsistem de comunicatie wireless care are rolul de a gestiona toti senzorii de intrare, indiferent care ar fi tipul lor(senzor usi, senzori PIR, etc.), impartiti pe patru zone de lucru. Senzorii sunt compusi din senzori propriu zis si modulul de comunicatie radio fiecare senzor avand o adresa bine definita. In momentul montarii unui senzor adresa lui va fi memorata in microsistemul de comunicatie wireless si alocata unei zone de lucru.
Fiecarei zone de lucru ii pot fi alocate 16 senzori, astfel la microsistem pot fi monitorizati maxim 64 de senzori organizati pe 4 zone de lucru.
De exemplu zona 1: sunt alocati 2 senzori PIR si 4 senzori magnetici de usi.
1. Modulul de comunicatie wireless
Modulul de comunicatie wireless e format dintr-un microsistem realizat cu un controler de tip PIC16F876 si o memorie EEPROM de tipul 24C16 cu o organizare 16Ko . Unitatea centrala are rolul de a monitoriza comunicatia wireless cu senzorii de a compara adresa acestora cu adresa memorata in EEPROM si de a semnaliza prin cele 4 relee zona care a fost activata. Semnalul de la cele 4 relee este citit de unitatea centrala si trimis pe reteaua ethernet. Comunicatia wireless este facuta pe frecventa de 433 MHz, iar comunicatia este securizata pe baza unui algoritm de cod saritor fiind impiedicata astfel patrunderea unor alarme false provenite de la alti senzori sau decriptarea informatiei de la diferiti senzori. Un senzor nu poate fi citit decat daca adresa lui a fost memorata in EEPROM-ul microsistemului de comunicatie wireless la punerea lui in functiune. Algoritmul de criptare/decriptare a fost construit si implementat de firma MicroChip.
1. Blocul de iesiri
Blocul de iesiri este format dintr-un sistem care preia semnalele digitale intre 0-3V de la unitatea centrala si in functie de destinatia acestora le converteste in semnale de iesire.
De exemplu : Pentru activarea sirenei semnalul intre 0-3V este transformat intr-un semnal intre 0-12V cu un curent de 0.5A necesar alimentarii sistemului audio construit pe baza unui difuzor Piezo cu oscilator incorporat. Pentru deschiderea garajului dintr-un semnal de 0-3V se obtine un semnal de 220V curent alternativ, acesta fiind obtinut prin prin amplificarea in curent si tensiune cu ajutorul unui tranzistor si apoi prin comanda unui releu permitandu-se alimentarea cu curent alternativ a motorului pentru deschidere use garaj, etc.
1.5. Blocul de declansare camera video si preluarea imagini video
Acest bloc e realizat cu ajutorul unui senzor PIR miniatural alimentat la o tensiune intre 4 si 12V care are rolul in momentul sesizarii unui corp in miscare sa declanseze pe iesirea lui un semnal electric cu amplitudinea tensiunii de alimentare. Intrucat aceasta poate fi variabila intre 4- 12V este necesara conversia ei intr-un semnal de 3V care poate fi citit de catre unitatea centrala. Acest lucru este realizat cu ajutorul unui montaj cu doua tranzistoare. Camera video, de tip CMOS, este alimentata cu o tensiune de 3V iar pe baza comenzilor primite de la unitatea centrala pe interfata seriala RS232 poate prelua, stoca si trimite catre unitatea centrala imagini cu rezolutia de 640x480 in format JPEG. Pentru a adapta seriala camerei de luat vederi la seriala unitatii centrale este nevoie de construirea unui convertor 0-3V la +7V -7V acest lucru fiind realizat cu un circuit special de tip MAX3232.
Modul de functionare este urmatorul: Unitatea centrala pe baza semnalului provenit de la senzorul PIR sau serverul local declansaza setul de comenzi pentru captura imagine. Totodata pe baza unor comenzi provenite de la unitatea centrala, imaginea este descarcata in memoria RAM a unitatii centrale, de acolo ea fiind transmisa prin modulul ethernet la serverul local.
1.6. Modulul Ethernet
Acesta are rolul de a prelua si gestiona informatia intre unitatea centrala si serverul local, este realizat cu ajutorul unui microsistem construit pe baza Cip-ului specializat CP2200 (Ethernet controller), care respecta normativul IEEE 802.3 MAC (Media Access Controller), care este compatibil in totalitate cu retelele 100/1000 BASE-T, detecteaza si corecteaza automat polaritatea, retransmisie automata a datelor si suporta adresare „broadcast” si „multi-cast”.
Caracteristicile modulului ethernet sunt:
Interfata paralela
Mod de 8 biti multiplexat sau nemultiplexat
Numai 11 pini de Intrari/Iesiri necesari in modul multiplexat
Format de bus Intel sau Motorola
Memorie Flash – 8 kB
Memorie non-volatila ISP de 8192 bytes
Adresa unica MAC de 48 biti pre programata de fabrica
Nu necesita EEPROM extern
Alte caracteristici
2 kB RAM dedicati pentru transmitere buffer si 4 kB RAM pentru a primi FIFO buffer
CP2200 este un cip de controler ethernet care contine un IEEE 802.3 integrat MAC, 10 BASE-T strat fizic (PHY) si 8 kB de memorie flash non volatila. CP2200 poate adauga conexiune ethernet la mai multe microcontrlare sau procesoare gazda cu 11 sau mai multe porturi de Intrare/Iesire. Bus-ul interfetei paralele pe 8 biti suporta format de bus atat Intel cat si Motorola in modul multiplexat sau nemultiplexat. Rata transferului de date in modul nemultiplexat poate depasi 30 Mbps.
Memoria flash integrata pe cip poate fi folosita pentru a stoca constante ale utilizatorului, continutul serverului web sau ca memorie cu scop general. Flash-ul e programat de fabrica cu o adresa unica MAC de 48 biti stocata in ultimele 6 locatii de memorie.
1.7. Blocul de alimentare
Are rolul de a adapta tensiunea provenita de la o priza (220V curent alternativ) la tensiunile necesare functionarii intregului sistem, acestea fiind : pentru unitatea centrala 5V si 0.5 A, pentru modulul comunicatie wireless, senzor PIR miniatura si blocul de iesiri 12V si 0.7A iar pentru modulul camera video CMOS 3V si 0.4A. Este construit cu ajutorul mai multor etaje de stabilizare liniare sau in comutatie.
2. Proiectarea software
2.1. Organizarea software a proiectului
Schema bloc a aplicatiei software este prezentata in figura de mai jos.
Fig.15 Organizarea aplicatiei software
Elementul central in aplicatia software il reprezinta serverul integrat. Acesta foloseste protocolul 727j99h HTTP pe nivelul aplicatie din stiva TCP-IP pentru transmisia informatiilor la distanta, prin reteaua internet, catre aplicatiile client care vor afisa informatiile.
Pe de alta parte, exista mai multe interfete care trebuiesc construite pentru achizitionarea datelor de la intrarile sistemului, pentru monitorizare precum si pentru actionarea unor dispozitive prin comenzi pe iesiri.
Practic se poate imagina un flux al datelor care „traverseaza” nivele diferite de protocoale.
Astfel, se incepe de la un nivel „fizic” al captarii intrarilor pinilor microcontroler-ului. Acesta se face practic prin utilizarea registrilor care acceseaza resurse fizice ale microcontrolerului cum ar fi porturi paralele sau intrari seriale. Mai departe aceste valori sunt transmise prin intermediul functiilor CGI unor protocoale „superioare” stivei TCP-IP. Acestea ajung sub forma unor obiecte care sunt transmise prin serviciul aplicatie HTTP. Comunicarea inseamna de fapt o „coborare” prin stiva TCP-IP pana la nivelul fizic, acela al canalului de comunicatie.
Comenzile preluate de la client – de exemplu un buton apasat in interfata client – sunt preluate de pe retea aduse la nivelul serviciului HTTP si apoi coborate la nivelul „fizic” al aplicatiei, prin scripturile CGI, pana la functii care actioneaza setul de registrii ai microcontroler-ului.
In acest moment se contureaza unul din obiectivele principale ale proiectarii software si anume construirea serverului HTTP, care asigura legatura dintre diferitele nivele de protocoale care sunt utilizate in acest proiect.
In paragraful urmator sunt pezentate cateva din caracteristicile servere-lor HTTP. Paragraful 2. este dedicat construirii serverului integrat in microsistem iar in 2. este prezentata cosntruirea functiilor de interfata CGI intre server si resursele fizice ale microcontrolerului: porturi paralele si canalul serial.
2.2. Relatia SERVER - CLIENT
2.2.1. Paginile web de pe servere web
Pentru a intelege cum functioneaza relatia server-client, prima data trebuiesc intelease serverele web care opereaza pe arhitectura PC-ului. La accesarea de catre un utilizator al Retelei Globale, paginile web care sunt vizualizate se impart in doua categorii:
pagini HTML statice
pagini HTML dinamice
Paginile HTML statice sunt pagini web care nu se schimba. De exemplu, un site web poate fi dedicat primului calculator inventat. Pagina sa poate afisa poze ale calculatorului si o descriere a lui. Paginile sunt vizualizate in acelasi mod de catre toata lumea.
Paginile HTML dinamice isi schimba continutul bazat pe un raspuns de la un utilizator sau alt eveniment extern. Un prim exemplu este motorul de cautare. Pagina web afisata ca rezultat al realizarii cautarii se schimba in functie de datele introduse intr-un formular. Baza online ofera un alt exemplu. Unele baze permit fiecarui client sa se inregistreze folosind webul si sa vizualizeze, printre alte lucruri, balanta de verificare a unui cont. Nu fiecare client duce aceeasi balanta, nici nu vizualizeaza aceeasi pagina. Aceste pagini trebuiesc generate dinamic folosind intrari primite de la utilizator (nume si parola) si surse externe (considerat ca raportul primit de la baza calculatorului).
O pagina HTML dinamica este compusa din:
Cod HTML
Flash
Applet
Scripturi Java
Scripturi CGI.
Introducerea paginilor dinamice este esentiala in acest proiect pentru preluarea datelor de pe porturile microcontroleru-ului si pentru comanda unor periferice.
2.2.2. Servere web pe sisteme de calculatoare
O pagina statica HTML este o colectare de informatii care obisnuieste sa locuiasca in sistemul de fisiere a serverului. Cand un navigator web cere o pagina web statica, serverul HTTP primeste informatia ceruta si o trimite navigatorului web. Nu se intampla nici o
Fig.16. Structura unui server WEB
schimbare, si aceeasi informatie este trimisa fiecarui utilizator care cere acea pagina web.
Paginile dinamice web nu pot fi salvate ca fisiere deoarece continutul lor se schimba. Continutul dinamic poate fi creat printr-o varietate de moduri, dar cel mai comun este folosirea secventelor interfetelor portilor computer. Secventele CGI sunt programe care, cand sunt executate, genereaza HTML-ul pe parcurs bazat pe informatia trimisa de la server si/sau sursele externe.
Paginile web statice sunt usor de creat deoarece ele nu se modifica. Paginile web dinamice sunt mai complicate de creat deoarece o pagina HTML este generata atunci cand se ruleaza.
Orice ar contine o pagina, serverul este structurat pe directoare, fiecare director avand propria utilitate, in functie de fisierele care le contie. Astfel exista directoare pentru fisiere text, multimedia, scripturi si applet-uri, baze de date, etc.
2.2. Servere web integrate
Caracteristicile unui server pe o statie de lucru trebuie, in mod firesc, sa fie aceleasi si pentru un server integrat. In fond, aplicatia client, care ruleaza pe calculatorul la distanta, are nevoie de aceleasi servicii fie ca este vorba de un server clasic, care ruleaza pe un calculator sau de un server integrat intr-un microsistem.
Solutia de server integrat are anumite limitari fata de solutia pe sistem. In primul rand aici se renunta la arhitectura interna pe directoare, deoarece nu exista un dispozitiv de stocare care sa permita acest lucru. La serverele integrate solutia de stocare este data de memoria nevolatia pe care o detine sistemul. Arhitectura organizata pe directoare este in acest caz emulata, pentru a furniza clientului un comportament similar cu varianta reala.
De exemplu, daca intr-o pagina exista un link catre un fisier imagine, clientul trebuie sa primeasca datele legate de acest fisier la accesarea acestui link, exact ca si cum fisierul s-ar gasi in server. In realitate el nu are cum sa fie prezent deoarece organizarea tipica unui spatiu de stocare cu sistem de alocare a fisierelor lipseste. In schimb clientul primeste un pointer catre un vector de octeti care este imaginea si asociaza cu acest pointer o cale catre fisierul virtual, asa cum este ilustrat in figura de mai jos.
O alta limitare pe care o au servere-le integrate este data de dimensiunea alocata pentru fisierele care acestea le contin. Toate resursele care sunt accesate intr-un server sunt depuse intr-o memorie semiconductoare, de regula nevolatila. Dimensiunea ocupata de server este limitata deci la dimensiunea memoriei.
Resursele hardware pe care un server integrat le are la dispozitie sunt, in general, foarte reduse comparativ cu solutia implementata pe calculator. Din acest motiv si tehnicile folosite trebuie selectate astfel incat ele sa poata fi aplicate pentru o memorie de date de dimensiuni reduse (1k – 4ko), un spatiu de stocare de asemenea redus (128k, 256k, 512ko) si o putere de calcul relativ mica (<100MHz).
HTML VECTORI OCTETI
SCRIPTURI CGI FUNCTII (SUBRUTINE) VECTORI
IMAGINI VECTORI OCTETI
Fig.17. Reprezentari utilizate in serverele integrate
Un mare avantaj al servere-lor integrate il constituie gradul foarte mare de miniaturizare. Acestea se pot gasi in aplicatii care necesita un volum ocupat mic si un consum energetic redus. Sistemul de monitorizare si comanda proiectat in aceasta lucrare necesita tocmai aceste cerinte. Solutia cu un calculator server care sa ruleze permanent programe de monitorizare este inlocuita cu un server integrat intr-o aplicatie care se poate gasi chiar in microsistemul ce comanda dispozitivele de avertizare. Avantajele legate de gabaritul redus al solutiei, de securitatea in exploatare (evitarea problemelor de supraveghere a statiei server) precum si de consum redus sunt evidente. De asemenea, un alt avantaj este cel legat de securitatea sistemului de monitorizare insusi. Calculatorul server poate fi vulnerabil in cazul incercarilor de patrundere prin efractie, in timp ce microsistemul pe care ruleaza server-ul este mult mai dificil de localizat.
2. Proiectarea server-ului integrat
Dezvoltarea unui server implica mai multe etape.
O etapa o reprezinta proiectarea site-ului – pagina sau paginile web care vor fi apoi accesate de client. Pentru proiectarea paginilor web se folosesc limbaje specializate printre care cel mai comun este limbajul HTML.
A doua etapa consta in proiectarea serverului propriu-zis, capabil sa raspunda la cerintele clientului.
Pentru crearea serverului se vor folosi pachetele de librarii Silabs TCP-IP care contin functiile pentru implementarea serviciilor la nivelul aplicatie. Aceste libarii contin urmatoarele fisiere:
Fisier |
Director destinatie |
Mn_callback.c |
Root |
Mn_vars.c |
Root |
Mn_defs.h |
Root |
Mn_errs.h |
Root |
Mn_funcs.h |
Root |
Mn_stackconst.h |
Root |
Mn_userconst.h |
Root |
Mn_stack_bank_039.lib |
Root |
Mn_stack_common_039.lib |
Root |
Mn_defs.h |
RootPagina |
Mn_stackconst.h |
RootPagina |
Html2c.exe |
RootPagina |
Fisierul html2c.exe este un utilitar care va fi folosit pentru conversia paginilor create din format html, in care ele sunt descrise, in formatul c pentru a putea fi apoi importate in proiect.
Etapa 1 Crearea paginilor web statice
Pentru crearea site-ului este necesara utilizarea unor limbaje specializate. Cel mai comun dintre acestea este html. Un fisier html se poate realiza:
Un exemplu de cod sursa HTML pentru descrierea paginii index arata ca in listingul din continuare:
<html>
<head><title>Sistem pentru monitorizare</title><head>
<body bgcolor='green' text='white' link='yellow' vlink='red' alink='blue'>
<h1>Sistem pentru monitorizare</h1> <br><br>
<B>folosind stiva de protocoale TCPIP Silabs</B><br>
</body>
</html>
Listing 1. Declaratia paginii HTML statice
Dupa salvare, fisierul are in mod normal atasat ca program implicit de rulare browser-ul activ. Pentru a verifica corectitudinea introducerii datelor se poate rula fisierul si se va observa pagina pe calculator.
Etapa urmatoare consta in conversia fisierului din format html in format c si h pentru a putea fi importat in proiectul serverului. In urma acestei conversii, fisierul html este transformat intr-un sir de octeti (coduri ASCII) care sunt apoi transmise de server la client. Practic interpretarea este facuta de catre browser. Se vor crea de catre utilitar doua fisiere index.c si index.h.
Asa cum s-a aratat si in paragrafele anterioare clientul va primii paginile HTML ca un sir de date care contin tag-urile. Fiecare tag este apoi interpretat de catre aplicatia client.
De exemplu, semnificatia codului de mai sus este aceea ca se creaza o pagina care are in bara de titlu scris mesajul „Sistem pentru monitorizare” iar pe un fond verde cu scris alb sunt afisate niste mesaje in pagina.
In urma conversiei este creat, in fisierul index.c, un vector de octeti care reprezinta codurile ASCII la valorile de mai sus.
#define INDEX_C_INC 1
#include 'index.h'
cmx_const byte index_html[]=
Listing 2. Vectorul rezultat in urma conversiei fisierului HTML
Fisierul index.h rezultat contine declaratia dimensiunii si a vectorului asa cum acesta este apelat din alte functii din proiect.
#ifndef INDEX_H_INC
#define INDEX_H_INC 1
#include 'mn_defs.h'
#define INDEX_SIZE 286
#ifndef INDEX_C_INC
extern cmx_const byte index_html[INDEX_SIZE];
#endif
#endif
Listing Fisierul index.h care contine dimensiunea si declaratia vectorului rezultat
Fisierele rezultate in urma conversiei contin deci vectori care reprezinta codul static.
Alaturi de aceste fisiere la proiect sunt adaugate fisierele libraii enumerate in tabelul de mai sus. Toate aceste fisiere au fost create de producatorii microcontroler-ului C8051F120 ca libarii necompilate pentru stiva TCP-IP, care se includ in proiect. Alaturi de aceste librarii necompilate, exista si o serie de librarii statice compilate (fisiere lib) care de asemenea trebuie de asemenea incluse in proiect. Aceste librarii contin o serie de functii care sunt apelate in proiect asa cum se va prezenta in sectiunea urmatoare.
Etapa 2 Crearea functiilor interfata CGI
Asa cum s-a prezentat, accesul la resursele fizice ale microcontroler-ului se face prin intermediul functiilor interfata CGI. Functiile contin declaratii de registrii care sunt utilizati pentru configurarea circuitelor periferice. Functiile CGI sunt particularizate in functie de destinatia lor si vor fi descrise in cele ce urmeaza.
2. Initializarea perifericelor, server-ului si bucla principala
Programul incepe, in primul rand, cu initializarea circuitelor periferice. Toate listing-urile prezentate in cele ce urmeaza sunt fragmente de program, considerate importante pentru descrierea care urmeaza. Listingul cu programul complet se va regasi atasat la anexa.
O prima etapa in editarea programului este includerea librariilor.
#include 'mn_userconst.h' // librarie constante TCP-IP
#include 'mn_stackconst.h' // librarie constante TCP-IP
#include 'mn_errs.h' // librarie coduri erori
#include 'mn_defs.h' // librare definire tipuri
#include 'mn_funcs.h' // librarie prototipuri functii
#include 'paginaindex.h' //fisier declaratie pagina
#include <c8051F120.h> // definitii specifice C8051F120
Listing Includerea librariilor TCPIP si librariilor tipice microcontroler-ului
Astfel sunt incluse in primul rand libariile de functii pentru stiva TCP-IP create de producatorii microcontroler-ului. Dupa includerea tipurilor de date generice sunt accesate fisierele care contin declaratiile functiilor standard C precum si declaratiile setului de registri ai microcontroler-ului.
Bucla principala a programului se poate reprezenta ca in figura17. Prima etapa in programul principal este initializarea circuitelor periferice. Sunt setate porturile paralele, canalele de comunicatie seriala precum si canalele timer.
// Prototipuri functi
// Subrutine de initializare
void PORT_Init (void);
void SYSCLK_Init (void);
void EMIF_Init(void);
int establish_network_connection();
// Functia principala
void main(void)
// conectarea la retea
establish_network_connection();
// adaugare pagina web la sistemul virtual de fisiere al serverului
// pagina principala trebuie denumita index.htm sau index.html
mn_vf_set_entry((byte *)'index.html', INDEX_SIZE, index_html, VF_PTYPE_FLASH);
// porneste serviciile de retea nivelul aplicatie
mn_server();
}
Listing 6. Initializarea serverului integrat
In primul rand se apeleaza functia mn_init care face parte din libraria TCP-IP pentru microcontroler-ul C8051F120. Functia se ocupa de initializarea stivei TCP-IP. Daca valoarea returnata de aceasta functie este negativa inseamna ca a aparut o problema la initializare. In acest caz programul ramane intr-o bucla infinita.
Si la acest nivel se simt diferentele intre solutiile software pentru PC si solutiile integrate pe un microsistem. In timp ce pe PC iesirea dintr-o eroare fatala (eroare cauzata de eroarea la initializare a unui modul considerat critic pentru executarea in continuare a programului) se facea prin suspendarea completa a programului: instructiunile exit() sau return. Programul ceda controlul sistemului de operare in care rula iar programatorul trebuia sa revada conditiile care au generat aparitia acelei erori. Eventual inainte de apelarea functiei de iesire propriu zisa se afisa un mesaj. In cazul proiectarii aplicatiilor integrate ar fi o greseala suspendarea completa a programului. Aceasta deoarece aici nu exista un sistem de operare care sa preia sarcinile. Iesirea completa din program, echivalenta cu un salt la sfarsitul programului, ar reprezenta o pierdere completa a controlului intrucat dupa ultima instructiune valida unitatea centrala din microcontroler va executa in continuare codurile care le va intalni. Evitarea acestui lucru se poate face in doua modalitati: suspendarea executiei procesorului la sfarsitul programului sau utilizarea unor bucle infinite.
Suspendarea executiei procesorului prin utilizarea unei instructiuni de tip suspend poate afecta starea circuitelor periferice astfel incat, prin intermediul interfetei de depanare, programatorul sa nu mai poata discerne eroarea care a determinat suspendarea executiei. Utilizarea buclei infinite de program are drept efect pastrarea starii procesorului care a dus la intrarea in aceasta eroare cu pastrarea activa a circuitelor periferice si a intreruperilor. Printr-o interfata de depanare se poate usor localiza locul in care programul a ramas „agatat”.
O alta functie apelata este establish_network_ connection declarata in fisierul main.c. Rolul ei este de a stabili conexiunea la retea pe baza adresei de IP (declarata ca o constanta in fisierul mn_userconst.h).
Adaugarea unei pagini la site se face prin utilizarea functiei, definita in librariile TCPIP, mn_vf_set_entry. Functia are 4 parametrii. Primul reprezinta imaginea virtuala asociata cu fisierul html solicitat asa cum va fi ea transmisa clientului cand acesta solicita pagina. Practic imaginea reprezinta de fapt un pointer catre un sir de caractere ce contine numele fisierului virtual, asa cum se regaseste in server.
mn_vf_set_entry((byte*)'index.html',INDEX_SIZE,index_html, VF_PTYPE_FLASH );
Al doilea parametru reprezinta lungimea vectorului in care se afla informatia din obiectul care va fi trimis clientului. Constanta INDEX_SIZE din apelul functiei prezentat este preluata din fisierul index.h si reprezinta dimensiunea paginii index convertita la sir de octeti. Al treilea parametru reprezinta un pointer catre vectorul care va fi transmis clientului (in cazul de fata index_html). Cel de-al patrulea parametru determina locatia unde se afla stocat vectorul. Acest parametru poate fi dat de constantele declarate in fisierul mn_stackconst.h dupa cum urmeaza:
#define VF_PTYPE_DYNAMIC 0x01 // tipul pagina alocat dinamic in memorie
#define VF_PTYPE_STATIC 0x02 // tipul pagina alocat static in memorie
#define VF_PTYPE_FLASH 0x04 //tipul pagina alocat in memoria FLASH
#define VF_PTYPE_RAM 0x08 // tipul pagina alocat in memoria RAM
#define VF_PTYPE_HTML 0x80 // pagina declarata html
Listing 7. Tipurile de resurse utilizate pentru stocarea vectorului
In toate cazurile este vorba despre un vector. Primele doua tipuri definesc alocarea vectorului undeva in memoria de date folosind tehnicile de alocare dinamica sau statica. Alocarea dinamica permite eliberarea resurselor de memorie dupa ce variabila vector nu mai este utilizata. Alocarea statica presupune declararea variabilei initial si apoi ea ramane rezidenta permanent. Ambele metode vizeaza memoria de date interna si externa a microcontroler-ului.
Tipul VF_PTYPE_FLASH se refera la stocarea vectorului obiect in memoria FLASH. Este evident ca acest tip este valabil pentru HTML static in care pagina ramane constanta. Tipul VF_PTYPE_RAM se refera la faptul ca pagina este prezenta intr-o memorie RAM interna sau externa. Specificarea acestui tip se face in corelatie cu modul de alocare al memoriei de date, prezentat.
O ultima situatie se poate utiliza pentru paginile HTML neconvertite (formatul html). In aceasta situatie nu mai este necesara conversia paginii dar solutia nu poate fi utilizata pentru interogarea dinamica a resurselor microcontroler-ului.
Adaugarea unor pagini prin utilizarea functiei mn_vf_set_entry este o etapa obligatorie care trebuie facuta la inceput. Trebuie specificat ca alaturi de pagini prin aceasta functie se pot adauga in general orice obiecte care sunt solicitate de client la server, cum ar fi scripturi, imagini, etc. Serverul va sti ca, in functie de cerinta care apare de la un client, sa preia din corpul mesajului de cerinta numele obiectului solicitat sa il compare cu imaginea sa virtuala si apoi sa ii asocieze vectorul care va fi transmis mai departe clientului.
Ultima etapa este pornirea server-ului propriu-zis utilizand functia mn_server() de asemenea declarata in librariile TCPIP.
2.5. Functii apelate la initializare
Asa cum s-a prezentat in paragraful anterior, exista mai multe functii care sunt apelate la initializarea modulelor.
I. Initializarea conexiunii la retea
Functia establish_network_connection asigura stabilirea unei conexiuni la retea si este prezentata in listingul de mai jos.
// stabilire conexiune retea
// functia apeleaza mn_ether_init() pentru initializarea machetei si conectarea
// la retea.
// daca se efectueaza conexiunea la retea functia returneaza 1
// daca nu exista nici o conexiune functia asteapta pana apare o coenxiune
// sau macheta este resetata in acest moment se pot efectua si alte task-uri
int establish_network_connection()
// daca retval este mai mic ca 0 sau e diferit de AUTO_NEG_FAIL , eroare conexiune
else if ((retval < 0) && (retval != AUTO_NEG_FAIL))
}while((retval < 0) && (retval != AUTO_NEG_FAIL));
return (1);
Listing 8. Functia establish_network_connection
In interiorul functiei sunt apelate proceduri declarate in librariile TCPIP. In primul rand, prin apelul functiei mn_ether_init, este demarata procedura de deschidere sesiune (demararea protocoalelor la nivel transport pentru stabilirea unei sesiuni). Functia returneaza un cod de eroare sau confirmarea ca sesiunea s-a deschis cu succes.
Daca se returneaza LINK_FAIL sau AUTO_NEG_FAIL inseamna ca negocierea a esuat si se asteapta un reset. Iesirea din functie semnifica faptul ca sesiunea de lucru a fost deschisa.
II. Initializarea circuitelor periferice ale MCU80C51F120
Caracteristica de baza pe care o are aplicatia este, asa cum s-a aratat, implementarea unui server pe microsistemul cu MCUC8051F120. Deci o caracteristica fundamentala pe care o are proiectul este combinarea elementelor de programare pentru servere, tipice aplicatiilor software de nivel inalt, cu elemente de programare „low-level” la nivel de registri ai microcontroler-ului.
Una din primele etape care trebuie efectuate la initializare este reprezentata de initializarea circuitelor periferice ale microcontroler-ului. Asa cum a fost prezentat in cadrul capitolului dedicat prezentarii microcontroler-ului C8051F120, accesul la perifericele acestuia se face prin intermediul unor registri de configurare. Scrierea in acesti registrii presupune configurarea circuitelor periferice. Transferul de date cu circuitele periferice se face, de asemenea, prin intermediul unor registri de date.
Etapele parcurse in initializare necesita prezentarea structurii unor registri. Acestia au fost detaliati in capitolul dedicat microcontroler-ului C8051F120. In continuare nu se va mai insista decat asupra prezentarii aspectelor legate de initializarea acestora in conditiile aplicatiei.
Arhitectura microcontroler-ului C8051F120 se bazeaza, asa cum s-a aratat in capitolele anterioare, pe un nucleu de microcontroler 8051. Alaturi de functiile tipice pe care le putea implementa un 8051 acesta are o serie de functii extinse, configurarea acestora se face prin secvente tipice numai lui C8051F120.
Numarul de registri de configurare este, in aceste conditii, mai mare decat cel al registrilor la un microcontroler 8051 clasic. Din acest motiv spatiul de memorie alocat pentru registri cu functii speciale (spatiu SFR – special function registers) este mai mare. Pentru pastrarea compatibilitatii cu programele facute pentru orice microcontroler din seria 8051, unul din obiectivele propuse de fabricantii familiei C8051F1xx, s-a utilizat adresarea paginata a spatiului SFR.
La fel ca si la 8051 spatiul SFR este plasat incepand cu adresa 80h pana la adresa FFh in spatiul de memorie direct adresabil, deci ocupa 128 de octeti din zona adresabila direct. Spre deosebire de acesta insa, exista mai multe pagini de memorie care se pot suprapune peste acest spatiu. In realitate, zona de memorie destinata registrilor cu functii speciale ocupa un total de 640 de octeti adica 5 pagini de memorie a cate 128 de octeti fiecare. Prin intermediul registrilor pe 8 biti SFRGCN, SFRPAGE, SFRNEXT si SFRLAST se determina care din cele 5 pagini sunt accesibile la un moment dat. Instructiunile 8051 acceseaza spatiul de memorie de 128 de octeti stabilit din configuratia registrilor sus amintiti.
Registrul SFRGCN este un registru cu organizarea de mai jos:
SFRPGEN |
Bitul SFRPGEN determina intrarea in modul automat de schimbare a paginii SFR. Daca acesta este 1 va avea drept urmare setarea automata a paginii SFR. Aceasta inseamna ca, in conditiile aparitiei unei intreruperi declansate de un circuit periferic, pagina se va pozitiona automat pe spatiul de memorie care poseda registri de configurare a perifericului respectiv.
In registri SFRPAGE, SFRNEXT si SFRLAST se va depune adresa paginii SFR care se doreste accesata. Pagina este codificata sub forma unui numar care poate avea 5 valori distincte. SFRNEXT si SFRLAST contin adresele paginilor SFR in conditiile in care pagina curenta a fost depusa in stiva. Stiva poate sa contina trei locatii distincte, fiecare continand o pagina SFR.
Valoarea paginii curente se va gasi intotdeauna in registrul SFRPAGE. Registrul poate sa contina urmatoarele valori: 00h, 01h, 02h, 03h si 0Fh. In functie de registri care se pot accesa din pagina curenta s-au definit urmatoarele constante:
#define CONFIG_PAGE 0x0F /* sistem si configurare porturi */
#define LEGACY_PAGE 0x00 /* pagina clasica 8051 */
#define TIMER01_PAGE 0x00 /* TIMER 0 si TIMER 1 */
#define CPT0_PAGE 0x01 /* COMP 0 */
#define CPT1_PAGE 0x02 /* COMP 1 */
#define UART0_PAGE 0x00 /* UART 0 */
#define UART1_PAGE 0x01 /* UART 1 */
#define SPI0_PAGE 0x00 /* SPI 0 */
#define EMI0_PAGE 0x00 /* interfata memorie externa */
#define ADC0_PAGE 0x00 /* ADC 0 */
#define ADC2_PAGE 0x02 /* ADC 2 */
#define SMB0_PAGE 0x00 /* SMBUS 0 */
#define TMR2_PAGE 0x00 /* TIMER 2 */
#define TMR3_PAGE 0x01 /* TIMER 3 */
#define TMR4_PAGE 0x02 /* TIMER 4 */
#define DAC0_PAGE 0x00 /* DAC 0 */
#define DAC1_PAGE 0x01 /* DAC 1 */
#define PCA0_PAGE 0x00 /* PCA 0 */
#define PLL0_PAGE 0x0F /* PLL 0 */
#define MAC0_PAGE 0x03 /* MAC 0 */
Listing 9 Definirea constantelor pagina SFR
Pagina 0 este similara ca organizare cu memoria SFR de la 8051. Aici se regasesc registri pentru configurarea canalelor timer 0 si 1 (TIMER0 si TIMER1), configurarea portului serial UART0, dar si registri pentru configurarea unor periferice extinse fata de versiunea 8051, canalul timer 2, interfata SPI, interfata I2C, convertorul digital analogic DAC0, etc.
Pagina 1 detine registri pentru comparatorul analogic COMP0, al doilea canal serial UART1, circuitul TIMER3 si al doilea convertor DAC1.
Pagina 2 contine registri pentru comparatorul analogic COMP1, convertorul analog digital ADC2 si circuitul TIMER
Pagina 3 contine registri utilizati pentru configurarea interfetei ethernet, iar pagina 4 configurarea sistemului (circuitul de monitorizare „watchdog”), configurarea buclei PLL si registri pentru configurarea iesirilor pe portul paralel.
O parte din registri de configurare a perifericelor au imagine in toate paginile de memorie
a. Initializarea porturilor paralele de uz general
Pornind de la observatia legata de setul de registri ai microcontroler-ului C8051F120, organizarea porturilor de intrare iesire de uz general este similara cu cea la 8051 chiar daca acestea sunt mai multe (8 porturi pe 8 biti). Porturile sunt denumite utilizand litere si cifre de forma P0 … P7. Fiecare port are corespunzator, in memoria registrilor cu functii speciale, un registru pe 8 biti cu acelasi nume cu cel al portului. Simpla operatie de scriere intr-un registru determina o operatie de scriere pe port iar simpla operatie de citire a continutului registrului declanseaza o operatie de citire a portului.
Registrii P0 .. P7 au imaginea vizibila din toate paginile, deci accesarea acestora pentru operatii de scriere si citire se face avand curent setata orice pagina.
Pentru porturile care sunt utilizate ca iesiri microcontroler-ul C8051F120 are, in plus, un set de registri pentru configurarea tipului de etaj de iesire denumiti PxMDOUT unde x poate fi orice numar cuprins intre 0 si 7 si corespunde portului vizat pentru configurare.
Structura registrului PxMDOUT este prezentata mai jos:
PMx.7 |
PMx.6 |
PMx.5 |
PMx.4 |
PMx.3 |
PMx.2 |
PMx.1 |
PMx.0 |
Fiecare bit in parte permite configurarea starii iesirii pinului respectiv. Daca unul din pini este 0 atunci iesirea acestuia va fi de tipul OpenDrena iar daca este setat 1 logic iesirea este de tipul push-pull (stabilirea unei referinte de tensiune pentru eventualele etaje de intrare de tip pull-up care se vor conecta la iesirea respectiva).
In cazul aplicatiei construite, una din primele etape este stabilirea configuratiei pinilor de port paralel in functie de cerintele impuse. Asa cum reiese si din schema hard, prezentata la capitolul anterior, functiile pinilor care intereseaza si modul in care acestia sunt alocatie pentru aplicatia de fata sunt urmatoarele:
P0 |
Bit | ||||||||
Nume |
INT |
RX0 |
TX0 |
||||||
Directie |
in |
in |
out |
P1 |
Bit |
| |||||||
Nume |
LED0 | ||||||||
Directie |
out |
P2 |
Bit | ||||||||
Nume |
INT |
LED2 |
LED1 |
SW2 |
SW1 |
||||
Directie |
in |
out |
out |
in |
in |
P3 |
Bit | ||||||||
Nume |
SW0 |
LUM |
SIR |
MINP |
AZ4 |
AZ3 |
AZ2 |
AZ1 |
|
Directie |
in |
out |
out |
in |
in |
in |
in |
in |
P4 |
Bit | ||||||||
Nume |
WR |
RD |
RST |
LED2 |
LED1 |
SW2 |
SW1 | ||
Directie |
out |
out |
out |
out |
out |
in |
in |
P5 |
Bit | ||||||||
Nume |
CS | ||||||||
Directie |
out |
P6 |
Bit | ||||||||
Nume |
A6 |
A5 |
A4 |
A3 |
A2 |
A1 |
A0 |
||
Directie |
out |
out |
out |
out |
out |
out |
out |
P7 |
Bit | ||||||||
Nume |
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
|
Directie |
in/out |
in/out |
in/out |
in/out |
in/out |
in/out |
in/out |
in/out |
Din modul in care este construita macheta de dezvoltare pentru C8051F120 si macheta Ethernet trebuie asigurate urmatoarele semnale:
pentru modulul Ethernet (interfata Ethernet)
o D7 .. D0 date comunicatie intre Ethernet CP2200 si C8051F120;
o A6 .. A0 adrese spatiu registrii circuit Ethernet CP2200;
o CS semnal selectie circuit Ethernet CP2200;
o INT pin semnalizare eveniment sfarsit transmisie sau receptie pachet date ethernet;
o RD selectie citire date de la modul Ethernet CP2200;
o WR selectie scriere date la modul Ethernet CP2200;
pentru dispozitivele de intrare iesire:
o SW1 butonul 1 aflat pe macheta Ethernet;
o SW2 butonul 2 aflat pe macheta Ethernet;
o LED1 comanda LED 1 aflat pe macheta Ethernet;
o LED2 comanda LED 2 aflat pe macheta Ethernet;
o SW0 butonul 0 aflat pe macheta C8051F12xDK;
o LED0 comanda LED 0 aflat pe macheta C8051F12xDK.
Alaturi de aceste conexiuni au fost stabilite urmatoarele pentru aceasta aplicatie:
pentru testarea starii senzorilor PIR in vederea declansarii alarmei:
o AZ4 senzor declansare alarma zona de monitorizare 4;
o AZ3 senzor declansare alarma zona de monitorizare 3;
o AZ2 senzor declansare alarma zona de monitorizare 2;
o AZ1 senzor declansare alarma zona de monitorizare 1;
o MINP senzor mini PIR declansare alarma proximitate sistem;
comanda activarii unor dispozitive:
o SIR comanda activare sirena;
o LUM comanda activare lumini;
interfata seriala pentru comunicarea cu dispozitivul camera:
o TX transmisie date interfata seriala;
o RX receptie date interfata seriala.
Pentru a evita orice probleme legate de tipul intrarilor care sunt comandate, toate iesirile din microcontroller se vor configura de tipul push-pull asa cum se poate vedea in listingul functiei de initializare a circuitelor periferice de mai jos.
void PORT_Init (void)
Listing 10 Initializarea circuitelor periferice
Se poate observa ca functia incepe cu salvarea paginii curente SFR in variabila locala SFRPAGE_SAVE urmand ca aceasta sa fie restaurata la sfarsitul functiei. Astfel se asigura integrarea functiei oriunde in program cu restaurarea la sfarsitul acesteia a paginii curente pe care s-a operat inainte de apelul functiei.
Pentru registrii PxMDOUT este necesara trecerea pe pagina CONFIG_PAGE. Toti bitii de iesire de pe porturi sunt configurati ca avand etajul de iesire push-pull.
b. Initializarea intreruperilor externe
O alta resursa utilizata de modulul Ethernet este o intrerupere externa. Libariile ethernet utilizeaza intreruperea externa INT0 pentru a realiza sincronizarea intre C2200 si microcontroler-ul C8051F120.
Configurarea intreruperii externe se face prin intermediul registrului TCON. Structura acestuia este prezentata mai jos:
TF1 |
TR1 |
TF0 |
TR0 |
IE1 |
IT1 |
IE0 |
IT0 |
De interes aici este bitul IT0 care realizeaza configurarea sursei generarii intreruperi externe 0. Astfel, in cazul de fata, IT0 este pus 0 logic ceea ce are drept efect generarea de intreruperi pe palierul 0 logic al semnalului care ajunge pe intrarea INT.
c. Alocarea pinilor pentru circuitele periferice
O caracteristica a microcontroler-lor din familia C8051F1xx este posibilitatea configurarii pinilor de functii alternative. La microcontroler-ul 8051 toate functiile alternative erau alocate pe pinii portului P3 pe pozitii fix stabilite. La C8051F120 fiecare circuit periferic poate avea mai multe posibilitati de alocare a pinilor pe care acesta opereaza.
Registri responsabili cu configurarea pinilor in functii alternative sunt XBR0, XBR1 si XBR2. Structura acestora este prezentata in figura de mai jos.
XBR0
CP0E |
ECI0E |
PCA0ME |
UART0EN |
SPI0EN |
SMB0EN |
XBR1
SYSCKE |
T2EXE |
T2E |
INT1E |
T1E |
INT0E |
T0E |
CP1E |
XBR2
WEAKPUD |
XBARE |
CNVST2E |
T4EXE |
T4E |
UART1E |
EMIFLE |
CNVST0E |
Pinii alocati canalului serial UART0: TX0 si RX0 sunt alocati pe pinii P0.0 respectiv P0.1. Acestia nu pot fi schimbati, din punctul de vedere al configurabilitatii alocarii se numesc pini cu gradul cel mai mare de prioritate.
In continuare urmeaza pinii alocati pentru canalul SPI, care au gradul de prioritate 2 cu doua optiuni posibile. Aceasta inseamna ca daca este utilizata interfata UART0 deci si pinii TX0 si RX0 atunci pentru interfata SPI se va aloca cea de-a doua optiune de pini.
Spre exemplu pinul SCK din interfata SPI are alocat pinul de port P0.0 ca prima optiune si P0.2 a doua optiune. Daca este utilizat canalul USART0 cu pinul de transmisie TX0 pe P0.0 atunci pinul SCK din interfata SPI va fi alocat pe P0.2. Daca nu se mai utilizeaza canalul USART0 pinul se va aloca pe P0.0.
Registrii XBAR0, XBAR1 si XBAR2 contin de fapt starea fiecarui periferic in sensul in care acesta are alocati pinii sau nu ii are. In exemplu dat mai sus, utilizarea portului serial USART0 si alocarea pinilor acestuia se configureaza prin setarea pinului UART0EN in 1 logic iar utilizarea portului SPI si alocarea pinilor pentru acesta se configureaza prin setarea bitului SPI0EN in 1 logic.
In ordinea prioritatii alocarii pinilor se afla, in continuare interfata I2C cu gradul de prioritate 3 (6 optiuni posibile), interfata seriala USART1 cu gradul de prioritate 4 (8 optiuni posibile), intreruperile externe cu gradul de prioritate 5 (10 optiuni) si asa mai departe. Cel mai mic grad de prioritate il are declansarea externa a convertorului analog digital (gradul 15 deci are 30 de optiuni posibile).
Concluzionand celor descrise mai sus, alocarea pinilor pentru periferice se face prin configurarea tuturor celor 3 registri in sensul validarii lucrului cu perifericele respective.
De aceea, in secventa de initializare se afla si validarea circuitelor periferice si alocarea pinilor acestora:
XBR0 = 0x84;
XBR1 = 0x04;
XBR2 = 0x40;
Listing 11. Configurarea alocarii pinilor pentru circuitele periferice
Functia de initializare se termina cu restaurarea paginii SFR la starea anterioara apelului functiei.
d. Configurarea memoriei externe
Spatiul extern de adresare este utilizat pentru comunicarea cu circuitul CP2200. Similar cu familia 8051 spatiul de adresare extern este pe 16 biti avand doua porturi pe 8 biti de adrese si un port de date pe 8 biti. Intre cel mai semnificativ octet de adrese si octetul de date se poate efectua o multiplexare pentru reducerea numarului de linii de port folosite. Microcontroler-ul C8051F120 poate accesa spatiul extern de adrese si intr-un mod nemultiplexat. In aceasta situatie sunt utilizati 16 biti de adrese si 8 biti de date.
Registri care sunt utilizati pentru adresarea unei memorii externe sunt EMI0CN, EMI0CF si EMI0TC. Acestia configureaza diferite functii pentru magistrala externa.
Registrul EMI0CN este utilizat pentru configurarea celui mai semnificativ octet de adresa la instructiunile de tip MOVX pe 8 biti. Spre exemplu, daca valoarea stocata in registrul EMI0CN este 12h atunci un grup de instructiuni in asamblare de tipul:
MOV R0,#34h
MOVX A,@R0
va avea drept efect citirea in acumulator de la adresa 1234h .
Instructiunile MOVX pe 8 biti sunt utilizate frecvent de compilator ca solutie optimizata la atribuirea unei valori. De exemplu declaratia urmatoare, facuta in C:
int a;
a = 10;
se poate implementa folosind instructiuni MOVX pe 8 biti in locul celor pe 16 biti cu registrul DPTR. Spatiul alocat in memoria de program pentru acestea este cu doi octeti mai mic decat echivalentul pe 16 biti care utilizeaza registrul DPTR.
In cazul de fata, pentru alocarea spatiului de adrese extern dincolo de memoria de date interna (de 8k) de la adresa 2000h in sus se utilizeaza configurarea registrului EMI0CN cu valoarea 20h. In listingul de mai jos, in care sunt prezentate secventele de initializare ale spatiului extern de memorie s-a utilizat atribuirea EMI0CN = BASE_ADDRESS cu BASE_ADDRESS declarat cu directiva define.
#define BASE_ADDRESS 0x20
void EMIF_Init (void)
Listing 12. Initializarea spatiului extern de memorare
Registrul EMI0CF este utilizat pentru configurarea spatiului extern de adresare. Structura acestuia este prezentata mai jos.
PRTSEL |
EMD2 |
EMD1 |
EMD0 |
EALE1 |
EALE0 |
Bitul PRTSEL selecteaza liniile de port accesibile pentru adresarea externa. Pentru pastrarea compatibilitatii cu versiunile de programe pentru familia 8051 PRTSEL trebuie pus in 0 logic. Aceasta inseamna ca spatiul extern este alocat peste porturile P0..P3 la fel ca la versiunile de 8051 standard. Daca se doreste alocarea pinilor pentru spatiul extern de memorie pe porturile P.P7 atunci acest bit se pune in 1 logic.
Alocarea pinilor pentru memoria externa are gradul de prioritate 0, ceea ce inseamna ca, indiferent de functia alternativa asociata pinilor de port configurarea acestora ca pini pentru adresarea spatiului extern are drept consecinta anularea functiilor alternative in favoarea lucrului cu spatiul extern.
In cazul de fata adresele si datele pentru accesul la circuitul Ethernet CP2200 s-au stabilit pe porturile P6 respectiv P7, deci bitul PRTSEL trebuie sa fie 1 logic.
Bitul EMD2 determina selectia modurilor de adresare. In cazul de fata, circuitul CP2200 nu ocupa decat 256 de locatii in spatiul de adresare, deci nu era necesara multiplexarea. De aceea bitul EMD2 a fost pus in 1 logic deci modul de lucru nemultiplexat.
Bitii EMD1 si EMD0 se programeaza impreuna determinand modul de alocare al spatiului extern. In cazul de fata valoarea acestora este stabilita la 10 (EMD1 1 si EMD0 0) adica spatiul de adresare extern peste adresa 2000h corespunde circuitului extern CP2200 in timp ce spatiul intern, pana la adresa 2000h corespunde memoriei interne RAM de date (8k).
Starea bitilor EALE1 si EALE0 decid stabilirea latimii semnalului ALE, folosit la adresarea multiplexata. Intrucat nu se lucreaza in modul multiplexat starea acestora nu prezinta importanta.
e. Initializarea ceasului sistemului
Spre deosebire de versiunile mai vechi de microcontrolere din familia 8051, microcontroler-ul C8051F120 are mai multe posibilitati de a genera semnalul de ceas care ii asigura functionarea. Pentru aceasta poate utiliza un oscilator extern, la fel ca versiunile anterioare de 8051, dar si oscilator intern integrat si chiar bucla de modulare in faza (PLL – phase – locked loop) care o are integrata.
Frecventa de la oscilatorul extern poate fi pana la maxim 30MHz iar frecventa oscilatorului intern calibrat de maxim 25 MHz.
Calibrarea oscilatorului intern se face prin intermediul registrului OSC0CL. Acesta defineste practic frecventa de baza a oscilatorului extern. Pentru valoarea implicita (adica 00h) frecventa generata de oscilatorul intern este de 25MHz.
Registrul OSCICN realizeaza configurarea oscilatorului intern. Structura acestuia este prezentata mai jos:
IOSCEN |
IFRDY |
IFCN1 |
IFCN0 |
IOSCEN este utilizat pentru validarea oscilatorului intern. In cazul de fata oscilatorul intern s-a utilizat pentru generarea frecventei de baza de lucru, deci IOSCEN este setat 1 logic. Bitul IFRDY permite monitorizarea lucrului oscilatorului intern. Prin interogarea acestuia se pot detecta eventualele neconcordante de frecventa ale oscilatorului intern. Bitii IFCN1 si IFCN0 realizeaza o divizare a semnalului de ceas cu o anumita valoare. Daca cei doi biti sunt pusi in 1 logic (deci 11 pe IFCN1 IFCN0) atunci divizarea ceasului este 1.
Registrul CLKSEL este utilizat pentru configurarea sursei ceasului sistemului. Structura acestuia este prezentata mai jos:
CLKDIV1 |
CLKDIV0 |
CLKSL1 |
CLKSL0 |
CLKDIV1 si CLKDIV0 configureaza un prescaler aplicat sursei de ceas selectate. Valoarea 00 (deci CLKDIV1 0 si CLKDIV0 0) semnifica aplicarea unui semnal de ceas de la sursa nedivizat. Precizam ca divizarea aplicata sursei, setata din registrul CLKSEL, se aplica semnalului selectat de la sursa. Astfel, de exemplu, daca oscilatorul intern este configurat cu un prescaler 2 si din registrul CLKSEL se configureaza o alta impartire cu doi atunci semnalul final, in conditiile in care sursa este selectata ca fiind oscilatorul intern, este divizat cu 4 fata de cel original.
Bitii CLKSL1 si CLKSL0 determina sursa semnalului de ceas. Doua setari sunt utilizate in initializarea noastra: 00 ceea ce semnifica sursa semnalului de ceas ca fiind oscilatorul intern si 10 ceea ce semnifica sursa semnalului de ceas ca fiind din bucla PLL.
Se poate observa ca sursele semnalelor de ceas se pot configura independent, chiar daca nu sunt cele selectate la un moment dat. Acelasi lucru se intampla si aici. Initial procesorul este trecut pe sursa interna de ceas. Apoi este configurata bucla PLL si in final are loc comutarea pe aceasta.
Configurarea oscilatorului extern se face prin intermediul registrului OSCXCN, nefiind utilizat in aceasta aplicatie. Cuartul extern poate fi utilizat ca o potentiala sursa de frecventa pentru bucla PLL
// SYSCLK_Init
// initializeaza ceasul sistemului
void SYSCLK_Init (void)
Listing 13 Initializarea oscilatorului.
Configurarea buclei PLL este facuta prin intermediul a 4 registri: PLL0CN, PLL0MUL, PLL0DIV si PLL0FLT. Circuitul PLL este utilizat pentru generarea unei frecvente de ceas multiplicata fata de frecventa de referinta aleasa.
Formula dupa care se calculeaza frecventa de iesire din bucla PLL este:
unde PLLN este valoarea de multiplicare, programata in registrul PLL0MUL si PLLM valoarea de divizare programata in registrul PLL0DIV (ultima numai pe 6 biti).
Configurarea buclei PLL se face prin intermediul registrului PLL0CN care are urmatoarea structura:
PLLCK |
PLLSRC |
PLLEN |
PLLPWR |
Activarea generatorului PLL se face prin setarea bitului PLLEN in 1 logic. Validarea alimentarii generatorului se face prin trecerea bitului PLLPWR in 1 logic. Secventa de alimentare trebuie sa fie inaintea validarii generatorului.
Bitul PLLSRC selecteaza sursa frecventei de referinta care este utilzata. In cazul de fata frecventa de referinta este cea care provine de la oscilatorul intern. De aceea PLLSRC este configurat, de la inceput, 0 logic. Bitul PLLCK este folosit pentru monitorizarea starii generatorului de frecvente PLL.
Registrul PLL0FLT se ocupa cu configurarea filtrelor care asigura functionalitatea buclei PLL. Structura registrului este urmatoarea:
PLLICO1 |
PLLOCO0 |
PLLLP3 |
PLLLP2 |
PLLLP1 |
PLLLP0 |
Prin bitii PLLICO1 si PLLOCO0 se programeaza domeniul de valori pentru frecventa de la iesirea generatorului. In cazul de fata ele au fost setate 00 pentru o frecventa cuprinsa intre domeniul de valori 65MHz 100MHz.
Pe de alta parte bitii PLLLP3, PLLLP2, PLLLP1 si PLLLP0 sunt utilizati pentru specificarea domeniului de valori al frecventei de intrare. In cazul de fata prin 0001 s-a selectat domeniul 19-30MHz (asa cum s-a aratat frecventa de intrare este aproximativ 25MHz din oscialtorul intern).
In concluzie, frecventa semnalului de ceas obtinta este de 75MHz, dintr-o frecventa de referinta de 25 MHz, factor de multiplicare 3 si factorul de divizare 1.
Ordinea secventelor de initializare este prezentata in figura de mai jos.
O prima consecita a lucrului la frecventa de 75MHz este schimbarea modului de operare cu memoria de program. Exista un registru care permite configurarea frecventei de lucru pentru a asigura o viteza corecta de operare cu memoria FLASH, in primul rand la citirea secventelor de program.
Registrul FLSCL prezinta urmatoarea structura:
FLRT |
FLWE |
Bitii FLRT permit selectarea domeniului de valori in care opereaza frecventa ceasului sistemului. Specificarea acestui domeniu este importanta pentru stabilirea vitezei de extragere a secventelor din memoria FLASH. In cazul de fata, FLRT are valoarea 11 deci domeniul de valori este unul cuprins intre 75MHz si 100MHz.
FLSCL = 0x30;
Fig.14 Initializarea oscilatorului utilizand bucla PLL pentru multiplicarea frecventei.
f. Generarea semnalelor de RESET 0 si RESET 1 pentru modulul Ethernet CP2200
Ultimele functii, prezentate la capitolul functii de initializare, sunt reprezentate de functiile care realizeaza reset-ul la circuitul CP2200. Asa cum s-a precizat in paragraful dedicat initializarii porturilor de uz general IO, pinul P5 este conectat la semnalul de RESET al modulului CP2200.
Din modul de functionare al circuitului CP2200 s-au dedus doua modalitati de lucr cu RESET. RESET-ul 0 consta in aplicarea unui semnal 0 pe pinul RESET. Acesta are drept urmare initializarea circuitului CP2200.
Trecerea in 1 a semnalului de RESET are drept urmare demararea functionarii circuitului CP2200. Semnalizarea functionarii acestuia se face tot pe pinul RESET prin trecerea acestuia in 1.
Deci, RESET-ul in 0 este efectuat de functia ether_reset_low.
void ether_reset_low()
Listing 15 Reset-ul 0 al circuitului CP2200.
Toate tehnicile descrise in sectiunile anterioare, din cadrul acestui subcapitol sunt utilizate si in aceasta functie: comutarea paginii SFR, scrierea pe port a unei valori prin accesarea registrului corespunzator portului.
Accesul la un singur bit din registru se face prin mascarea bitilor care se doresc nemodificati.
Ridicarea semnalului de RESET in 1 este realizat de functia ether_reset_high. Si aici se poate observa comutarea paginii SFR, accesarea pentru scriere si pentru citire a portului P
void ether_reset_high (void)
Listing 16. Reset 1 la circuitul CP2200
2.6. Configurarea si comunicarea cu dispozitivul camera digitala
Etapa urmatoare, dupa initializarea circuitelor periferice si construirea server-ului, este construirea scripturilor CGI pentru accesul la semnalele achizitionate de circuitele periferice.
Desi camera digitala face parte din categoria dispozitivelor externe care sunt interogate si accesate de catre client prin intermediul functiilor CGI, am optat pentru prezentarea functiilor de acces ale acesteia intr-un subcapitol separat dat fiind complexitatea lucrului cu aceasta.
Asa cum am mentionat in capitolul dedicat prezentarii dispozitivelor hardware care sunt folosite in acest proiect, camera este un dispozitiv care poate prelua imagini si le poate transmite apoi, prin intermediul interfetei RS232, catre un sistem in vederea stocarii si prelucrarii acestora.
Camera C328 permite efectuarea de capturi si transmiteri de imagini atat in formatul necomprimat (RAW), pentru prelucrari ulterioare, cat si in formatul JPEG, deci comprimat, pentru o transmitere facila a acestora catre alte dispozitive externe.
Pentru aplicatia noastra, care isi propune preluarea unor imagini in vederea transmiterii catre aplicatii client folosind reteaua ethernet, cea mai potrivita forma de captura este, in mod evident, cea JPEG.
Inainte de achizitionarea propriuzisa de imagini, trebuie mentionat ca este nevoie de realizarea unor configurari ale lui C328, astfel incat raspunsul acesta sa fie conform cerintelor aplicatiei.
In figura 19 sunt prezentate principalele etape parcurse la lucrul cu C328.
In primul rand, trebuie stabilit protocolul de comunicatie intre camera si sistemul cu microcontroler C8051F120. Asa cum am mentionat, camera comunica si este configurata prin intermediul interfetei seriale RS232. Viteza de comunicare este determinata automat de catre camera prin transmisia mai multor secvente de sincronizare.
Cu exceptia pachetelor care contin informatiile legate de imaginile propriu-zise, toate celelalte pachete care vor trebui transmise sau care sunt receptionate la/de la C328 au o dimensiune de 6 octeti.
Structura unui pachet generic este prezentata in tabelul de mai jos:
AAh |
Functie |
Parametru 1 |
Parametru 2 |
Parametru 3 |
Parametru 4 |
Fig.19 Operarea cu dispozitivul camera C328 pentru capturarea unor imagini JPEG
Toate pachetele incep cu codul AAh. Acesta este urmat apoi de codul functiei si de 4 parametrii. In cazul in care functia nu are 4 parametrii, acestia vor fi 00h.
Sincronizarea, prima etapa care va duce la determinarea, de catre C328, a vitezei de comunicatie seriala, consta de fapt intr-o functie care are urmatoarea forma:
AAh |
0Dh |
00h |
00h |
00h |
00h |
Acest pachet este numit SYNC (de la sincronizare - syncronize). Determinarea vitezei de comunicatie de catre C328 se face in mai multe etape de aceea e nevoie de mai multe pachete SYNC care trebuie transmise (numarul acestora, la o sincronizare, este cuprins intre 20 si 30). Confirmarea determinarii corecte a vitezei de comunicatie este facuta de camera prin transmiterea unui pachet de confirmare (denumit ACK – acknowledge confirmare). Pachetul ACK are urmatoarea structura:
AAh |
0Eh |
0Dh |
00h |
00h |
00h |
Cel de-al treilea octet, returnat de camera, reprezinta ID-ul functiei care a determinat generarea pachetului. Asa cum se poate vedea si in figura, din momentul sincronizarii fiecare comanda care este transmisa de la C8051F120 la camera este urmata de o confirmare din partea camerei ca a receptionat si este in curs de executie comanda respectiva.
Dupa ce camera a returnat confirmarea receptiei functiei de sincronizare, ea va genera, la randul ei, o functie de sincronizare care va fi transmisa catre microcontroler. C8051F120 va trebui sa raspunda la acest pachet de sincronizare cu un ACK de forma de mai jos:
AAh |
0Eh |
00h |
00h |
00h |
00h |
In acest moment, fiind incheiat un transfer bidirectional de informatie rezulta ca viteza de comunicatie a fost stabilita, prin urmare se poate demara procedura de transfer al imaginilor.
Inainte de a efectua un transfer, trebuie generat pachetul INIT prin care se configureaza tipul imaginii si tipul capturii care se doreste efectuata.
Formatul pachetului INIT este urmatorul:
AAh |
01h |
00h |
Culoare |
Rezolutie RAW |
Rezolutie JPEG |
„Culoare” poate fi un numar cuprins intre 01h si 07h si se refera la adancimea de culoare si tipul imaginii. In cazul nostru, dorind sa efectuam un transfer de imagine comprimata JPEG, deci „culoare” va fi 07h. Rezolutia RAW se refera la rezolutia imaginii necomprimate, care nu este utilizata pe parcursul acestui lucrari. In schimb, rezolutia JPEG este setata la valoarea 03h adica 160x128. Alte rezolutii JPEG permise sunt 80x64 (01h), 320x240 (05h) si 640x480 (07h).
Asa cum am mentionat, la transmiterea acestui pachet, C328 va raspunde prin generarea unei confirmari cu 01h codul functiei generate.
Dupa stabilirea conditiilor initiale se pot seta dimensiunea unui pachet de imagine si viteza de comunicatie.
Stabilirea vitezei de comunicatie are ca urmare scaderea timpului de sincronizare dar, de observat ca la deconectarea camerei de la sursa toate datele stocate sunt sterse, deci oricum trebuie refacute configurarile.
Pachetul care permite setarea vitezei de comunicatie este de forma:
AAh |
07h |
Div1 |
Div2 |
00h |
00h |
Pentru viteza de 9600bps cei doi parametrii sunt configurati BFh si 01h (div1 respectiv div2).
Transmisia imaginilor de la camera la C8051F120 se face in mai multe etape, prin utilizarea unor pachete. Stabilirea dimensiunii acestor pachete este o alta etapa in stabilirea unei sesiuni complete de comunicatie intre C328 si C8051F120. Dimensiunea unui pachet este stabilita prin urmatoarea functie:
AAh |
06h |
08h |
Lungime low |
Lungime high |
00h |
Lungimea unui pachet poate fi cuprinsa intre 64 si 512 octeti. Structura unui pachet este prezentata in figura .
In aplicatie, datorita limitarii resurselor de memorare, am folosit pachete cu lungimea de 64 de octeti.
Dupa ce C328 a raspuns prin secventa de ACK la ultima functie transmisa se poate demara procedura de captura a imaginii.
Captura reprezinta un proces prin care imaginea este capturata si inregistrata in memoria interna a dispozitivului C328. In cazul in care se face o captura JPEG, imaginea este si comprimata JPEG.
Captura se face prin comanda SNAP, cu formatul urmator:
AAh |
05h |
Tip |
Nr. cadre low |
Nr. cadre high |
00h |
Tip se refera la formatul imaginii capturate, comprimata sau necomprimata. S-a optat, asa cum am spus, pentru o metoda de comprimare JPEG, deci Tip aici va fi 00h. Captura este facuta la momentul respectiv de timp, deci nu va lasa nici un numar de cadre suplimentar sa treaca (deci va fi 0000h).
Dupa efectuarea capturii, pasul imediat urmator este preluarea imaginii capturate si transmiterea acesteia catre C8051F120. Pentru aceasta se foloseste cuvantul GETPICTURE.
AAh |
04h |
Tip |
00h |
00h |
00h |
Iar „tip” se refera la tipul imaginii preluate. In cazul nostru va fi 01h adica imagine capturata.
Din acest moment se va demara receptia datelor in pachete si reunirea acestora pentru construirea imaginii finale.
O prima etapa in construirea si transmiterea seriala a tuturor acestor pachete o reprezinta configurarea canalului USART0. Acesta nu a fost reprezentat la capitolul dedicat initializarii circuitelor periferice deoarece portul este initializat numai in interiorul functiei care efectueaza transmisia la camera. Restul timpului canalul serial UART0 alaturi de canalul TIMER1, cel prin care se asigura frecventa de comunicatie.
Functia care realizeaza initializarea canalului serial este prezentata in listingul de mai jos:
void UART1_Init (void)
Listing 17 Initializarea portului serial UART0
Accesul la configurarea portului serial UART0 se face prin intermediul registrilor SCON1, TMOD, CKCON si TH1.
Registrul SCON1 are urmatoarea structura:
S1MODE |
MCE1 |
REN1 |
TB81 |
RB81 |
TI1 |
RI1 |
S1MODE configureaza dimensiunea pachetlui receptionat: pe 8 sau 9 biti. Se va merge pe solutia cu 8 biti de date deci S1MODE este 0 logic. MCE1 este utilizat pentru comunicatia multiprocesor – aici va fi 0 logic. REN1 reprezinta bitul care trebuie pus in1 logic pentru validarea receptiei. TB81 si RB81 sunt utilizati pe post de cel de-al 9-lea pin de date la transmisie si la receptie. TI1 si RI1 permit monitorizarea transmisiei si receptiei. In urma unei transmisii TI devine 1 numai dupa ce secventa de transmisie s-a incheiat iar buffer-ul la transmisie este gol. La receptie RI1 indica momentul in care buffer-ul de receptie este plin.
Registrul TMOD este utilizat pentru configurarea canalului Timer 1, care asigura frecventa de comunicatie. Structura acestuia este urmatoarea:
GATE1 |
CT1 |
T1M1 |
T1M0 |
GATE0 |
CT0 |
T0M1 |
T0M0 |
De interes aici sunt primii 4 biti cei mai semnificativi. CT1 determina modul de lucru al circuitului timer. In cazul de fata se doreste sa fie in modul Timer adica sa numere semnalul de ceas intern al sistemului. T1M1 si T1M0 decid modul de lucru. In cazul de fata trebuie sa fie numarator pe 8 biti cu reancarcarea rezultatului sau modul 2 de lucru. Valoarea T1M1 T1M0 este, in acest caz 10.
Registrul CKCON permite configurarea prescaler-ului la semnalul de ceas al sistemlui. Astfel, structura acestui registru este urmatoarea:
T1M |
T0M |
SCA1 |
SCA0 |
T1M determina daca ceasul care ajunge pe timer-ul 1 este sau nu divizat cu un factor de prescalare configurat in SCA1 SCA0. Se utilizeaza aceasta prescalare, deci T1M este 0. Prescalarea se programeaza la 48 deci SCA1 SCA0 este 10.
In registrul TH1 se va depune constanta de divizare a timer-ului.
Rata de transfer calculata va fi :
Dupa stabilirea vitezei de transfer pasul urmator este activarea canalului timer prin setarea in 1 a bitului TR1 din registrul TCON.
Asa cum se poate observa, in functia de initializare constanta de divizare este stabilita in functie de valoarea frecventei sistemului, prin intermediul directivelor de compilare.
In listingul de mai jos sunt prezentate secventele de program care efectueaza initializarea camerei, configurarea acesteia precum si comenzile de captura si de preluare poza.
//sincronizare
while(!RI1)
}
//receptie ack
data_rec[0]=SBUF1;
RI1 = 0;
for(c=1;c<6;c++)
data_rec[c] = get_ch();
//receptie sync
for(c=0;c<6;c++)
data_rec2[c] = get_ch();
//transmisie ack
for(c=0;c<6;c++)
put_ch(ack[c]);
for(i=0;i<20000;i++);
send_cmd(init,6);
//transmisie setare dimensiune pachet
for(i=0;i<20000;i++);
send_cmd(size,6);
//transmisie comanda captura imagine
for(i=0;i<20000;i++);
send_cmd(snap,6);
//transmisie comanda cerere imagine
for(c=0;c<6;c++)
data_rec2[c]=0x41;
for(i=0;i<20000;i++);
send_cmd(getp,6);
//receptie data
for(c=0;c<6;c++)
data_rec2[c] = get_ch();
Listing 18 Secventa pentru initializarea, configurarea si demararea comunicatiei cu dispozitivul camera
Dupa transmiterea comenzii de preluare imagine, camera raspunde cu un ACK, pentru confirmarea receptiei comezii, si apoi transmite un pachet denumit DATE cu structura ca mai jos:
AAh |
0Ah |
Tip |
Lungime0 |
Lungime1 |
Lungime2 |
Tip este un raspuns la tipul de date solicitat prin functia GETPICTURE. In cazul nostru el trebuie sa fie 01h. Lungime este un numar pe trei octeti si reprezinta lungimea, in octeti, a imaginii. Ea va fi folosita pe post de indicare al sfarsitului transmisiei, prin atingerea ultimului octet din imagine.
Transmiterea imaginii se face prin intermediul unor pachete de date, asa cum se poate observa in figura 20.
Fig.20. Structura unui pachet de date returnat de C328
Fiecare pachet de date contine un ID propriu, generat in ordine crescatoare. La un moment dat, printr-o comanda de tip cerere confirmare (ACK) microsistemul poate solicita unul din aceste pachete. Forma cuvantului ACK este:
AAh |
0Eh |
00h |
00h |
Pachet low |
Pachet high |
Numarul pachetului este, deci, pe doi octeti, cu ocmps primul si ocms al doilea. La receptia acestui pachet camera va transmite pachetul de date corespunzator cu structura prezentata in figura .
Cererea si receptia in continuare a pachetelor, cu dezasamblarea acestora, ca in figura 21 vor duce in final la reconstituirea intregii imagini.
Fig. 21. Formarea imaginii din pachete de date
In organigrama de mai jos este prezentata secventa pentru receptia unei imagini sub forma unor pachete de date.
Fig.22. Receptia pachetelor de date emise de C328
Salvarea fiecarui pachet in parte este reprezentata in organigrama de mai jos:
Fig.2 Salvarea unui pachet de date
In listingul de mai jos este prezentata secventa de program care efectueaza acest lucru.
//receptie data
for(c=0;c<6;c++)
data_rec2[c] = get_ch();
image_size = ((data_rec2[5]<<16)&0xff0000)+((data_rec2[4]<<8)&0x00ff00)+data_rec2[3];
if(image_size>4000)
image_size=4000;
index = 0; pachet = 0;
//pregatire ack
data_rec2[0]=0xaa;
data_rec2[1]=0x0e;
for(c=0;c<4;c++)
data_rec2[c+2]=0;
while(index<image_size)
for(c=0;c<pachet_size+2;c++)
if(control!=test_img[pachet_size+4])
control=100;
pachet++;
}
data_rec2[5]=0xf0;
data_rec2[4]=0xf0;
for(i=0;i<20000;i++);
send_cmd(data_rec2,0);
Listing 19 Receptia pachetelor de date de la C328
Asa cum se poate observa si din listing, dupa receptia pachetului DATA din acesta se extrage lungimea totala a imaginii. Concatenarea celor doi octeti si obtinerea lungimii se face prin operatii de deplasare la stanga cu 16 (inmultiri cu 65536), deplasari cu 8 pozitii (inmultiri cu 256) si adunari:
image_size = ((data_rec2[5]<<16)&0xff0000)+((data_rec2[4]<<8)&0x00ff00)+data_rec2[3];
Dupa un test de limita maxima (permisa de resursele interne ale microcontroler-ului) are loc pregatirea pachetului ACK. Dupa ce acesta este transferat (send_cmd(data_rec2,4)) are loc receptia primilor 4 octeti din pachet (ID-ul si lungimea campului de date din pachet). Lungimea este extrasa, pentru a se cunoaste numarul de octeti de date astepatti in cadrul pachetului, fiecare octet este citit si stocat apoi in vectorul imagine. La fiecare depunere a unui octet in vectorul imagine variabila index este incrementata. Tot algoritmul se termina atunci cand index, deci octetul curent receptionat ajunge la valoarea lungimii imaginii. In acel moment se transmite un pachet ACK in care in campurile pachet sunt valorile F0h F0h. Acesta informeaza ca receptia datelor s-a terminat.
Imaginea se afla, dupa receptie intr-un vector imagine. Asa cum s-a aratat la capitolul dedicat proiectarii server-ului, se va asocia o imagine de fisier virtual cu acest vector imagine. Cand un client va solicita accesul la acest fisier se va transmite catre acesta vectorul imagine.
2.7. Proiectarea functiilor CGI
Comunicarea dintre dispozitivele conectate la circuitele periferice ale microcontroler-ului si o aplicatie client conectata la distanta prin reteaua ethernet se face prin intermediul functiilor CGI.
Asa cum am aratat, variabilele definite in cadrul aplicatiei din microsistem, utilizate la achizitia datelor, pot fi integrate intr-o pagina WEB pentru monitorizare de la distanta in doua etape:
declararea variabilelor afisate sub forma unor obiecte care fac referire la functiile (scripturile) CGI;
declararea si explicitarea functiilor (scripturilor) CGI.
Prima etapa se face printr-o declaratie apel in interiorul TAG-ului HTML, care inlocuieste formula statica, utilizata de obicei.
De exemplu, pentru afisarea statica a unei imagini (fisier JPEG) se foloseste tag-ul HTML:
<img src='imagine.jpg'' align='bottom'>
La intalnirea acestui tag, clientul (browser-ul in acest caz) transmite o cerere catre server pentru receptia fisierului imagine.jpg care se gaseste, in mod normal, pe discul radacina al server-ului (altfel ar fi trebuit sa existe o cale specificata, relativa la directorul radacina al server-ului).
Aceasta este o imagine statica, un fisier care trebuie sa se gaseasca in statia server pe tot timpul rularii acestuia.
Plasarea imaginii in pagina se face in locul in care este declarat TAG-ul raportat, fata de linia de afisare, cu alinierea declarata in TAG-ul align.
Un asemenea tip de imagine este utilizat in site-uri pentru afisarea unor imagini statice, care raman permanent pe pagina sub aceeasi forma, de exemplu antet, logo-uri etc.
In cazul de fata, pentru o imagine, cum ar fi planul unei locuinte, se doreste afisarea unor elemente dinamice, de exemplu starea unor senzori plasati in diferitele puncte ale locuintei. Intr-un punct, la un moment dat, se semnalizeaza o patrundere. Imaginea in acest moment trebuie actualizata cu indicatia, pe punctul respectiv.
O alta situatie este captarea imaginii de la camera video. Asa cum s-a aratat in subcapitolul anterior, imaginea care o transmite camera este in formatul JPEG (comprimat). Aceasta este afisata intr-un chenar in pagina WEB. In mod evident, la un moment dat daca se doreste realizarea unei alte capturi imaginea se schimba, deci ea va trebui retransmisa clientului.
Se intalnesc, deci, doua situatii in care metoda de declarare statica a imaginii, pe care am mentionat-o mai sus, nu este satisfacatoare: ce se intampla daca in acelasi chenar se doreste la un moment dat afisarea altei imagini sau chiar a aceeasi imagini dar cu informatiile schimbate. Ambele situatii sunt provocate de evenimente provocate de dispozitive conectate la perifericele microcontroler-ului.
Solutia la problema este prin declararea obiectelor care apeleaza o functie in forma intalnita mai jos:
<img src='get_data?imagine' align='bottom'>
Se observa ca numele efectiv al imaginii a fost inlocuit de un apel de functie. Get_data este un apel de functie in care se asteapta o declaratie care va transmite catre client informatia dorita. Alaturi de cererea de informatie clientul va trimite si numele obiectului care solicita informatia (in acest caz imagine).
Fig.24 Fluxul de date client server in cazul apelului unui obiect
Server-ul primeste numele functiei care se va executa precum si numele obiectului care va identifica, in functie, tipul datei pe care il solicita clientul.
Acest tip de functie este practic o interfata intre retea si subrutinele „comune” care acceseaza dispozitivele periferice ale microcontroler-ului de unde si numele de functie CGI (Common Gateway Interface). In aplicatiile client server de nivel inalt, acestea sunt declarate ca apeluri in pagina HTML, din aceasta cauza in mod curent se foloseste denumirea de scripturi (aplicatii scrie in alte limbaje integrate in pagina HTML) CGI.
In cazul nostru, am utilizat mai multe asemenea obiecte cu apel de functii CGI in pagina: un obiect imagine dinamica pentru schema locuintei si altul pentru imaginea incarcata de la camera.
<img src='get_data?imagine' align='bottom'>
<img src='get_data?contact' align='bottom'>
<img src='get_data?pir1' align='bottom'>
<img src='get_data?pir2' align='bottom'>
<img src='get_data?pir3' align='bottom'>
<img src='get_data?pir4' align='bottom'>
Aplicabilitatea obiectelor CGI este mult mai generala, generarea dinamica a imaginilor folosind apeluri de functii este un caz particular.. Practic orice obiect HTML integrat in pagina poate fi generat dinamic folosind apeluri de functii
In mod normal, o functie CGI trebuie sa contina, in interiorul ei, urmatoarele secvente logice, descrise in figura 25.
Declaratia unei functii CGI se face ca mai jos:
void get_data(PSOCKET_INFO socket_ptr);
Din punctul nostru de vedere exista doua tipuri de cereri de obiecte care pot aparea: obiectul imagine care solicita transmisia unei imagini si invers, butoanele care au asociate obiecte transmit stari catre circuitele periferice.
Fig.25 Interogare cerere client in functia CGI
Functia nu returneaza nici o valoare deoarece este apelata de obiect ca o procedura. Are un singur parametru: o variabila de tipul PSOCKET_INFO
Tipul PSOCKET_INFO reprezinta un pointer catre o structura de tip socket utlizata de protocolul TCPIP. Declararea structurii este prezentata in listingul de mai jos:
typedef struct socket_info_s SOCKET_INFO_T;
Listing 20. Tipul de date socket utilizat in implementarea protocolului TCPIP
Variabila pointer send_ptr este utilizata pentru a indica pointer-ul catre sirul de octeti de date care este transmis catre client. Send_len reprezinta lungimea sirului de octeti care se doreste transmis. Recv_ptr reprezinta pointer-ul catre buffer-ul la receptie iar recv_len dimensiunea sirului receptionat.
Functia mn_http_find_value este o functie care apartine libariilor SiLabs si este utilizata pentru extragerea din buffer-ul de receptie a mesajelor de la client care contin apeluri de obiecte.
I) Transmiterea datelor achizitionate de la circuitele periferice la aplicatia client
In listing-ul de mai jos este prezentata tratarea unui mesaj receptionat de la client in care se solicita transmisia de date la obiectul imagine:
if (mn_http_find_value(BODYptr,(byte *)'imagine',msg_buff))
}
Listing 21 Functia de tratare a apelului obiect imagine
Asa cum se poate observa si in listing, se incepe testarea receptiei vreunui mesaj de la obiectul imagine. Daca este receptionat vreun mesaj, semnalizat prin valoarea TRUE la functie, se intra in tratarea efectiva a solicitarii. Asa cum se observa aici, se apealeaza functia camera. Functia camera contine proceduri care au fost descrise ulterior la prezentarea modului de operare cu C328. In final, in vectorul imagine vom avea intreaga poza capturata.
Pasul urmator este atribuirea pointer-ului send_ptr din structura socket_info_s cu valoarea pointer-ului imagine si configurarea lungimii transmise (send_len) cu valoarea image_size.
In aceste conditii, singura problema care ramane este determinarea algoritmilor “low-level” pentru captarea informatiilor de interes de pe porturi. O data acestea captate sunt transformate in variabile care, prin intermediul tehnicii cu functii CGI se pot asocia cu obiectele pe care clientul le cere.
Fig.26 Organigramele bloc pentru achizitia datelor la camera C328
Sunt definite urmatoarele functii pentru accesarea circuitelor externe:
Functii de care lucreaza cu dispozitivul C328, descrise sumar in organigramele din figura dar detaliate in subcapitolul dedicat lucrului cu dispozitivul camera video C328. Obiectivul acestora este de a reactualiza imaginea preluata de la camera video;
Functii care preiau starea de la dispozitivele de tip contact (montate la usi). O schema bloc de achizitie a acestor date este prezentata in figura de mai jos:
Fig.27 Achizitia datelor de la dispozitivele de tip contact
Starea contactului este preluata prin citirea pinului unui port paralel (descrierea acestora este prezentata la capitolul dedicat initializarii circuitelor periferice). In urma citirii acestuia este pozitionata variabila contact in 0 sau 1. Aceasta variabila va fi apoi utilizata pentru a specifica tipul de imagine care se incarca pe pagina.
In listingul de mai jos este prezentat codul sursa pentru interogarea liniilor de port atat pentru functiile care achizitioneaza datele de la contacte, tratate mai sus cat si cele de la PIR tratate in paragraful imediat urmator:
newP = P3;
//test schimbare stare pini alarma
if((newP&0x01f)^(oldP&0x01f))
else
//testare alarma PIR
if(newP&0x1e)
//reactulalizare
oldP = newP;
Listing 22 Interogarea liniilor de port pentru contact si PIR
Functii care preiau starea de la senzorii PIR, de asemenea de tip contact. Organigrama de mai jos prezinta lucrul cu acestia.
Fig.27 Achizitia datelor de la dispozitive PIR
Modul de lucru aici este similar cu cel de la tratarea contactelor. In fond, senzorul PIR este de asemenea un sezor de tip contact, asa cum a fost descris in capitolul dedicat prezentarii acestora. Preluarea datelor de la acestia urmareste acelasi principiu cu preluarea datelor de la senzorii contact.
La fel ca si la achizitia datei de la camera si aici aceste variabile preluate trebuie transferate sub o forma clientului la cererea acestuia. Modul in care se vor transmite aceste variabile catre client va fi sub forma unor imagini modificate ale schemei incintei monitorizate, asa cum se prezinta in listingul de mai jos:
if (mn_http_find_value(BODYptr,(byte *)'contact',msg_buff))
else
}
//transmitere imagini stare senzori
cuvant[0]='p';
cuvant[1]='i';
cuvant[2]='r';
cuvant[4]= ;
for(i=0;i<4;i++)
else
}
Listing 23 Tratarea apelurilor de la obiectele contact si pir
II) Transmiterea setarilor de la aplicatia client la circuitele periferice
Un alt flux de date este reprezentat de comenzile care se dau de la client catre circuitele periferice, deci parcurgerea in sens invers a buclei.
Asemanator cu parcurgerea inversa a fluxului si aici este nevoie de declaratii de obiecte inserate in TAG-urile HTML.
De exemplu, pentru preluarea starii unui buton si transmiterea acesteia catre server se folosesc butoanele ascunse declarate astfel:
<INPUT NAME='setari' TYPE=hidden VALUE='1'><INPUT TYPE=submit VALUE='Activare alarma '>
Primul buton declarat cu TAG-ul INPUT este un buton ascuns si are asociat obiectul cu numele setari si valoarea 1. Cel de-al doilea este un buton vizibil. Acesta va avea practic si el asociat obiectul „setari”.
Acesta este transmis la server la actionarea butonului.
La server, functiile CGI trebuie sa preia valoarea obiectului si sa o testeze luand decizii in functie de aceasta, ca in organigrama de mai jos.
Fig.28 Script CGI pentru interpretarea apasarii butonului in aplicatia client
Functia CGI utilizata pentru preluarea starii butoanelor si generarea de comenzi catre circuitele periferice se declara intr-un mod similar cu cea utilizata la monitorizarea starii:
void remote_control(PSOCKET_INFO socket_ptr)
Fig.29. Transferul client server a unor setari generate din interfata client
La fel ca si aceasta contine apeluri ale functiei mn_http_find_value Deosebirea este ca aceasta preia valori din pachetul receptionat si le testeaza, asa cum se poate vedea in listing-ul de mai jos:
if (mn_http_find_value(BODYptr,(byte *)'setari',msg_buff))
// returneaza index.html
socket_ptr->send_ptr = (byte *)index_html;
socket_ptr->send_len = INDEX_SIZE;
}
Listing 24 Functia CGI pentru interogarea starii butoanelor si efectuarea comenzii
Dupa setarea configuratiilor perifericelor se returneaza clientului pagina index ca o confirmare a receptiei obiectului.
CAPITOLUL 5
ETAPE DE PROIECTARE SI PROBLEME INTAMPINATE
Proiectarea hardware si proiectarea software au constat in mai multe etape care au fost realizate pe parcursul pregatirii acestui proiect.
Demararea proiectului a inceput pe 1 august 2009 cand s-a demarat etapa de documentare. Au fost studiate caracteristicile tehnice ale microcontroler-ului C8051F120 si machetei de dezvoltare cu acesta. S-a studiat, de asemenea, tipurile de protocoale de comunicatie si metode de implementarea ale acestora in microsisteme.
Cunoscand detaliile tehnice ale machetei de dezvoltare si posibilitatile de interfatare dintre aceasta si reteaua ethernet, pe 1 octombrie 2009 s-a pornit construirea software a proiectului. Prima etapa a fost posibilitatea implementarii unui server HTTP in interiorul sistemului capabil sa poata raspunde la solicitari din partea clientilor si sa poata interoga si variabilele locale microsistemului. Implementarea a reusit, cu succes, pe 30 noiembrie 2009. In continuare s-au analizat posibilitatile de comunicare ale camerei video CMOS. S-a construit sursa de alimentare si interfata de comunicatie seriala a acesteia utilizand circuitul MAX232. Lucrul cu aceasta a durat pana in februarie 2010. Din acest moment s-a inceput lucrul la partea hardware legata de comanda releelor de alarma si preluarea informatiei de la senzorii de proximitate.
Integrarea proiectului a fost facuta in luna aprilie 2010, moment in care s-au inceput testele finale.
Problemele intampinate pe parcursul dezvoltarii au fost urmatoarele:
Serverele de tip HTTP se implementeaza in mod normal pe statii de lucru (calculatoare). Implementarea lor pe microsisteme ridica o serie de probleme legate de limitarea resurselor hardware de care dispunem.
La lucrul cu camera CMOS, datorita limitarii sursei de alimentare, cand se facea o captura de imagini peste o anumita rezolutie camera intra intr-un mod de blocare din care nu iesea decat prin realimentare. Solutia a fost redimensionarea sursei de alimentare astfel incat sa suporte un curent de peste 1.5A.
La imagini prea mari nu este posibila stocarea acestora in memoria locala itnerna de 4k. Solutia este utilizarea modului de captura pentru imagini de dimensiuni mici (320x240).
CAPITOLUL 6
CONCLUZII SI TENDINTE
Serverele implementate pe microsisteme au un domeniu foarte mare de aplicabilitate: sisteme mobile de achizitie, telemetrie, sisteme de navigatie, sisteme de securitate. In acest proiect s-a implementat un sistem de monitorizare si alerta cu anumite comenzi care se pot da de la distanta, prin ethernet.
Sistemul utilizeaza protocolul HTTP de comunicatie prin care un client HTTP (browser) poate accesa serverul implementat pe microsistem. Serverul monitorizeaza permanent starea unor variabile care indica statutul unor senzori de proximitate.
Tehnicile de lucru din acest proiect sunt cele tipice programarii in C pentru microcontrolere, programarea in limbaj HTML si limbaj Java precum si implementarea unor module hardware pentru asigurarea unor interfete de comunicatie.
Posibile directii de dezvoltare ar fi cresterea dimensiunii resurselor interne pentru marirea calitatii imaginilor afisate si utilizarea mai multor camere pentru surprinderea mai multor unghiuri de monitorizare.
De asemenea, cresterea resurselor ar implica si posibilitatea realizarii de filme care apoi sa fie integrate in aplicatii de vizualizat din browsere.
BIBLIOGRAFIE
1. https://www.silabs.com/ C8051f120 datasheet
2. www.COMedia.com C328 datasheet
Gheorghe Serban – Note de curs, microprocesoare , editura Universitatii din Pitesti 2002
Bruce Eckel – Thincking in C++
5. Bogdan Patrut – Aplicatii in C si C++, editura Teora 1998
5. Randy Katz – Contemporany logic design – Adison Wesley Publishing Company, 1993
6.Steven Steinke – Network tutorial, V Edition – CMP Books, 2003
ANEXA LISTINGUL PROGRAMULUI
//#include <c8051F120.h>
#include 'init.h'
#include 'global.h'
//////functie care incearca conectarea la camera
const unsigned char sync[6]=;
const unsigned char baud[6]=;
const unsigned char ack[6]=;
const unsigned char init[6]=;
const unsigned char size[6]=;
const unsigned char snap[6]=;
const unsigned char getp[6]=;
const unsigned char reset[6]=;
unsigned char data_rec[70],data_rec2[6];
unsigned int index=0;
unsigned int pachet = 0;
unsigned int pachet_size = 0;
unsigned char control = 0;
unsigned char c_temp;
unsigned char get_ch(void)
void put_ch(unsigned char car)
void send_cmd(unsigned char *vec,unsigned char size)
void init_camera()
if(!RI1)
for ( i = 0; i < SYSCLK/200; i++)
if(RI1) break;
}
//receptie ack
data_rec[0]=SBUF1;
RI1 = 0;
for(c=1;c<6;c++)
data_rec[c] = get_ch();
//receptie sync
for(c=0;c<6;c++)
data_rec2[c] = get_ch();
d = getchar();
e = getchar();
//transmisie ack
for(c=0;c<6;c++)
put_ch(ack[c]);
for(i=0;i<20000;i++);
send_cmd(reset,6);
void camera()
if(!RI1)
for ( i = 0; i < SYSCLK/200; i++)
if(RI1) break;
}
//receptie ack
data_rec[0]=SBUF1;
RI1 = 0;
for(c=1;c<6;c++)
data_rec[c] = get_ch();
//receptie sync
for(c=0;c<6;c++)
data_rec2[c] = get_ch();
d = getchar();
e = getchar();
//transmisie ack
for(c=0;c<6;c++)
put_ch(ack[c]);
for(i=0;i<20000;i++);
send_cmd(reset,6);
//sincronizare
while(!RI1)
if(!RI1)
for ( i = 0; i < SYSCLK/200; i++)
if(RI1) break;
}
//receptie ack
data_rec[0]=SBUF1;
RI1 = 0;
for(c=1;c<6;c++)
data_rec[c] = get_ch();
//receptie sync
for(c=0;c<6;c++)
data_rec2[c] = get_ch();
d = getchar();
e = getchar();
//transmisie ack
for(c=0;c<6;c++)
put_ch(ack[c]);
RI1 = 0;
for(c=0;c<6;c++)
//sincronizare
RI1 = 0;
while(1)
if(RI1) break;
}
//receptie ack
data_rec[0]=SBUF1;
RI1 = 0;
for(c=1;c<6;c++)
data_rec[c] = get_ch();
//receptie sync
for(c=0;c<6;c++)
data_rec2[c] = get_ch();
for(i=0;i<200;i++);
for(c=0;c<6;c++)
put_char(sync[c]);
//receptie ack
for(c=0;c<6;c++)
data_rec[c] = get_ch();*/
//transmisie rata de transfer
//for(c=0;c<6;c++)
put_char(baud[c]);
//receptie ack
for(c=0;c<6;c++)
data_rec[c] = getchar();
//transmisie initializare
for(i=0;i<20000;i++);
send_cmd(reset,6);
for(i=0;i<20000;i++);
send_cmd(init,6);
for(c=0;c<6;c++)
put_char(init[c]);
//receptie ack
for(c=0;c<6;c++)
data_rec[c] = get_ch();
//transmisie setare dimensiune pachet
for(i=0;i<20000;i++);
send_cmd(size,6);
for(i=0;i<20000;i++);
send_cmd(baud,6);
for(c=0;c<6;c++)
put_char(size[c]);
//receptie ack
for(c=0;c<6;c++)
data_rec[c] = get_ch();
//pauza pentru camera
for(i=0;i<SYSCLK/100;i++);
//transmisie comanda captura imagine
for(i=0;i<20000;i++);
send_cmd(snap,6);
//transmisie comanda cerere imagine
for(c=0;c<6;c++)
data_rec2[c]=0x41;
for(i=0;i<SYSCLK/200;i++);
for(i=0;i<20000;i++);
send_cmd(getp,6);
//receptie data
for(c=0;c<6;c++)
data_rec2[c] = get_ch();
//preluare lungime imagine
image_size = 0;
image_size = data_rec2[5];
image_size = (image_size<<16)&0xff0000;
image_size = ((data_rec2[5]<<16)&0xff0000)+((data_rec2[4]<<8)&0x00ff00)+data_rec2[3];
if(image_size>4000)
image_size=4000;
index = 0; pachet = 0;
//pregatire ack
data_rec2[0]=0xaa;
data_rec2[1]=0x0e;
for(c=0;c<4;c++)
data_rec2[c+2]=0;
//testare DE SCOS
data_rec2[5]=0;
data_rec2[4]=0x0a;
for(i=0;i<20000;i++);
send_cmd(data_rec2,4);
//sfarsit testare
while(index<image_size)
for(c=0;c<pachet_size+2;c++)
if(control!=test_img[pachet_size+4])
control=100;
pachet++;
if(pachet==0x0a)
pachet++;
}
data_rec2[5]=0xf0;
data_rec2[4]=0xf0;
for(i=0;i<20000;i++);
send_cmd(data_rec2,0);
// Disable Timer1
SFRPAGE = TIMER01_PAGE;
TR1 = 0; // Stop Timer1
TMOD = 0x00; // Readuce registrul TMOD
// la valoarea de reset
CKCON = 0x00; // Readuce registrul CKCON
// la valoarea de reset
// Disable UART1
SFRPAGE = UART1_PAGE;
SCON1 = 0x00; // Dezactiveaza UART1
SFRPAGE = SFRPAGE_SAVE; // Reface pagina SFR
// main.c
// Version: 1.0
// Descriere:
Acest exemplu se comporta ca un server web HTTP.
// Functioneaza cu un microcontroler C8051F120 conectat la o placa ethernet cu procesor CP2200 .
#include 'mn_userconst.h' //Libraria de constante TCP/IP
#include 'mn_stackconst.h' // Libraria de constante TCP/IP
#include 'mn_errs.h' // Libraria codurilor de eroare
#include 'mn_defs.h' // Libraria definitiilor tipurilor
#include 'mn_funcs.h' // Libraria prototipurilor functiilor
#include 'VFILE_DIRindex.h'
#include 'VFILE_DIRTemperature.h'
#include 'VFILE_DIRTemp.h'
#include 'VFILE_DIRTemp$Update.h'
#include 'VFILE_DIRon.h'
#include 'VFILE_DIRoff.h'
#include 'VFILE_DIRlogo.h'
#include 'VFILE_DIRcmxlogo.h'
//#include <c8051F120.h> // Definitii SFR specifice c8051f120
#include 'C:SiLabsMCUIDEfilesC51INCstdio.h' // Adauga suport pentru printf, etc.
#include 'C:SiLabsMCUIDEfilesC51INCstdlib.h'
#include 'C:SiLabsMCUIDEfilesC51INCstring.h'
#include 'camera.h'
#include 'global.h'
#include 'init.h'
// Main Routine
void main(void)
// Conectarea la retea
establish_network_connection();
// Adaugati pagini web la fisierul virtual de sistem.
// Aceasta pagina principala trebuie sa se numeasca index.htm sau index.html.
mn_vf_set_entry((byte *)'index.html', INDEX_SIZE, index_html, VF_PTYPE_FLASH);
mn_vf_set_entry((byte *)'Temperature.html', TEMPERATURE_SIZE, temperature_html, VF_PTYPE_FLASH);
mn_vf_set_entry((byte *)'logo.gif', LOGO_SIZE, logo_gif, VF_PTYPE_FLASH);
mn_vf_set_entry((byte *)'cmxlogo.gif', CMXLOGO_SIZE, cmxlogo_gif, VF_PTYPE_FLASH);
mn_vf_set_entry((byte *)'Temp.class', TEMP_SIZE, temp_class, VF_PTYPE_FLASH);
mn_vf_set_entry((byte *)'Temp$Update.class', TEMPUPDATE_SIZE, tempupdate_class, VF_PTYPE_FLASH);
mn_vf_set_entry((byte *)'on.gif',134, on_gif, VF_PTYPE_RAM);
// Adaugati scripturile CGI la fisierul virtual de sistem.
mn_pf_set_entry((byte *)'remote_control', remote_control);
mn_pf_set_entry((byte *)'get_data', get_data);
mn_server();
}
while(1);
#include 'global.h'
// VARIABILE Globale
char data_buffer[DATA_LEN + 1] = '80.5rnrn';
long OFFSET = 42950; // Default Temp Sensor Offset
unsigned char code first_time = 0xFF; // poate fi scris doar odata dupa
// fiecare download-are pentru ca este
// initializat la 0xFF
char xdata* data ptr_first_time = &first_time;
unsigned char code ip_address[4] _at_ 0x0000; // gasit in zona Scratchpad
char xdata* data ptr_ip_address = &ip_address;
long image_size = 0; //lungimea imaginii receptionate
unsigned char imagine[4000];
unsigned char apasa = 0;
unsigned char test_img[100];
#include 'mn_userconst.h' // Libraria de constante TCP/IP
#include 'mn_stackconst.h' // Libraria de constante TCP/IP
#include 'mn_errs.h' // Libraria codurilor de eroare
#include 'mn_defs.h' // Libraria definitiilor de tipuri
#include 'mn_funcs.h' // Libraria prototipurilor functiilor
#include 'VFILE_DIRindex.h'
#include 'VFILE_DIRTemperature.h'
#include 'VFILE_DIRTemp.h'
#include 'VFILE_DIRTemp$Update.h'
#include 'VFILE_DIRon.h'
#include 'VFILE_DIRoff.h'
#include 'VFILE_DIRlogo.h'
#include 'VFILE_DIRcmxlogo.h'
//#include <c8051F120.h> // Definitii specifice SFR
#include 'C:SiLabsMCUIDEfilesC51INCstdio.h' // Adauga suport pentru printf, etc.
#include 'C:SiLabsMCUIDEfilesC51INCstdlib.h' // Adauga suport pentru atoi
#include 'C:SiLabsMCUIDEfilesC51INCstring.h'
// Prototipurile Functiilor
// Initializarea Rutinelor
void PORT_Init (void);
void SYSCLK_Init (void);
void EMIF_Init(void);
int establish_network_connection(void);
// Adauga suport pentru configurarea adresei IP prin portul serial
void UART1_Init (void);
void ipconfig(void);
// Adauga suport pentru scripturile CGI
void remote_control(PSOCKET_INFO socket_ptr) cmx_reentrant;
void get_data(PSOCKET_INFO socket_ptr) cmx_reentrant;
void ADC0_Init (void);
// mn_vars.c
// Descriere:
// Acest fisier contine variabile folosite de stiva TCP/IP .
#include 'mn_defs.h'
#include 'mn_userconst.h'
// Setarea adresei IP
byte ip_dest_addr[IP_ADDR_LEN] = IP_DEST_ADDR;
byte ip_src_addr[IP_ADDR_LEN] = IP_SRC_ADDR;
//Setarea adresei MAC
// Daca se foloseste CP2200, mn_ether_init va rescrie aceasta valoare cu adresa
// MAC stocata in memoria Flash a lui CP2200.
byte eth_src_hw_addr[ETH_ADDR_LEN] = ETH_SRC_HW_ADDR;
byte eth_dest_hw_addr[ETH_ADDR_LEN] = ETH_DEST_HW_ADDR;
// Daca e folosit gateway setati adresa IP gateway si
// subnet mask de mai jos.
// Daca un gateway nu este folosit:
setati gateway IP address la
si subnet mask la
byte gateway_ip_addr[IP_ADDR_LEN] = GATEWAY_IP_ADDR;
byte subnet_mask[IP_ADDR_LEN] = SUBNET_MASK_ADDR;
// Declararea variabilelor STIVEI
// Aceste array sunt folosite de stiva TCP/IP. Acestea nu pot fi sterse sau editate.
SOCKET_INFO_T sock_info[num_sockets];
byte null_addr[IP_ADDR_LEN];
byte recv_buff[recv_buff_size];
byte send_buff[xmit_buff_size];
byte ping_reply_buff[ping_buff_size + 9];
VF_PTR http_vf_ptrs[num_sockets];
TEMP_SSI_S temp_ssi_info[num_sockets];
byte HTTPBuffer[http_buffer_len];
VF vf_dir[num_vf_pages];
PAGE_SEND_T page_send_info[num_sockets];
POST_FUNCS pf[num_post_funcs];
ARP_INFO_T arp_info[arp_cache_size];
// Constantele FLASH
// Aceste constante definesc comportamentul stivei. Acestea nu ar trebui sterse sau editate
// Device
byte code DEVICE_ID = device_id;
// Sockets
byte code NUM_SOCKETS = num_sockets;
word16 code XMIT_BUFF_SIZE = xmit_buff_size;
word16 code RECV_BUFF_SIZE = recv_buff_size;
word16 code SOCKET_WAIT_TICKS = socket_wait_ticks;
// Ethernet
word16 code ETHER_WAIT_TICKS = ether_wait_ticks;
// ARP
word16 code ARP_KEEP_TICKS = arp_keep_ticks;
byte code ARP_RESEND_TRYS = arp_resend_trys;
word16 code ARP_WAIT_TICKS = arp_wait_ticks;
byte code ARP_CACHE_SIZE = arp_cache_size;
byte code ARP_AUTO_UPDATE = arp_auto_update;
// HTTP
word16 code HTTP_BUFFER_LEN = http_buffer_len;
// IP
byte code TIME_TO_LIVE = ip_time_to_live;
byte code MULTICAST_TTL = multicast_ttl;
//
word16 code PING_BUFF_SIZE = ping_buff_size;
// TCP
word16 code TCP_WINDOW = tcp_window;
word16 code TCP_RESEND_TICKS = tcp_resend_ticks;
byte code TCP_RESEND_TRYS = tcp_resend_trys;
// Virtual File
byte code NUM_VF_PAGES = num_vf_pages;
byte code NUM_POST_FUNCS = num_post_funcs;
// Timer
byte code TL0_FLASH = tl0_flash;
byte code TH0_FLASH = th0_flash;
|