Sistem Alerta a Asistentelor In Spitale
Proiect de diplomă
Sistem alertă a asistentelor
în spitale
Cuprins
Cap I. Prezentare generală a proiectului
I.1 Motivația alegerii temei
I.2. Prezentare generală sistem
Cap II. Prezentare sistem
II.1. Softul de interfațare a dispozitivului central cu Pc-ul
II.2. Dispozitiv central
II.2.1. Functionare
II.2.2. Tastatura
II.2.3. Modulul LCD
II.2.4. Buzzer
II.2.5. Comunicația serială
II.2.6. FTDI
II.2.7. RFID
II.2.8. Modul recepție wireless
II.3. Dispozitivul de salon
II.3.1. Funcționare
II.3.2. Modulul RFID
II.3.3. Telecomenzile cu fir
II.3.4. Modulul wireless si telecomenzile fără fir
Cap III. Prezentare generală a procesoarelor folosite
III.1. Procesorul PIC 18F452
III.1.1. Arhitectură
III.1.2. Porturi de intrare/ieșire
III.1.3. Modulele Timer
III.1.3.1. Timer 0
III.1.3.2. Timer 1
III.1.3.3. Timer 2
III.1.3.4. Timer 3
III.1.4. Modulul detecție tensiune alimentare joasă
III.1.5. Modulul de captură/comparare/PWM (CCP)
III.1.5.1. Modul Captură
III.1.5.2. Modul Comparare
III.1.5.3. Modul PWM
III.1.6. Modulul port serial sincron master(MSSP)
III.1.6.1. Modul SPI
III.1.6.2. Modul I2C
III.1.7. Modulul Convertor Analog-Digital
III.1.8. Registre cu funcții speciale
III.2. Procesorul PIC 16F648
III.2.1. Arhitectură
III.2.2. Porturi de intrare/iesire
III.2.3. Modulele Timer
III.2.3.1. Timer 0
III.2.3.2. Timer 1
III.2.3.3. Timer 2
III.2.4. Modulul de captură/comparare/PWM (CCP)
III.2.4.1. Modul Captură
III.2.4.2. Modul Comparare
III.2.4.3. Modul PWM
III.2.5. Modulul Comparator
III.2.6. Modulul referința de tensiune
III.2.7. Modulul USART
III.2.8. Registre cu funcții speciale
III.3. Transcieverul FTDI
Cap IV. Concluzii
Cap V. Bibliografie
Anexa 1. Coduri sursă folosite de dispozitivul central
Anexa 2. Coduri sursă folosite de dispozitivului de salon
Anexa 3. Schema electrica dispozitiv salon
Cap Prezentare generală a proiectului
I.1 Motivația alegerii temei
Într-un sistem sanitar în plină dezvoltare, orice încercare de înbunătățire a acestuia poate fi considerată o reusită. Deși este în plină dezvoltare, nevoile pacientilor nu sunt satisfăcute întotdeauna. De ce? Pentru că asistentele sunt prea puține pentru numărul mare de pacienți și nu sesizează mereu faptul că un pacient are nevoie de ajutor. De asemenea, asistenta poate observa pacientul care are nevoie de ajutor dar, din cauza problemelor celorlalți, poate uita de nevoia primului. O a treia cauză a acestei probleme poate fi comoditatea și absența dorinței de a practica această meserie. Pentru toate aceste probleme se încearcă gasirea unei soluții care să fie viabilă și ieftină.
Această încercare de găsire a unei soluții la problema prezentată anterior a determinat încercarea de creere a unui dispozitiv care să fie ușor de utilizat pentru pacienți, să reușească să atenționeze asistentele asupra nevoilor pacienților, să fie ușor de pus în funcțiune, să fie cât mai compact(în sensul existenței a cât mai puține fire de conectare între module) și în același timp să aibă un preț rezonabil. Prețul trebuie să fie cât mai mic întrucât se știe că fondurile asociate spitalelor nu sunt foarte mari și de aceea sunt orientate mereu catre achiziția de aparatură medicală.
Din această incercare de rezolvare a problemei a rezultat “Sistemul de alertare al asistentelor”, care va fi prezentat în cele ce urmează.
I.2. Prezentare generală sistem
Sistemul este proiectat să opereze în spitale, locuri în care de cele mai multe ori cablurile sunt o problemă. Pentru rezolvarea acestei probleme, comunicațiile între dispozitivele sistemului sunt de tip wireless. Sistemul este alcătuit dintr-un dispozitiv central ce va fi așezat în camera de gardă a asistentelor și mai multe dispozitive de salon care vor trimite cererile pacienților către dispozitivele centrale. Pe lângă aceste dispozitive fizice există și un soft care va salva toate înregistrările evenimentelor pe un pc. Accesoriile acestui sistem sunt reprezentate de telecomenzile wireless care se vor afla la fiecare pat, cardurile RFID cu ajutorul cărora asistentele vor putea fi recunoscute de sistem, un card master care va fi ținut de către asistenta șefă și va permite intrarea acesteia în meniul de configurare al dispozitivului central, și o telecomandă wireless master cu ajutorul căreia se vor putea introduce cardurile RFID în memoria dispozitivelor de salon.
Cu ajutorul telecomenzilor cu sau fără fir, pacienții crează cereri. Aceste cereri sunt trimise wireless de către dispozitivul de salon, către dispozitivul central. Acesta, după ce procesează mesajul va emite o avertizare vizuală și auditivă asupra evenimentului. În cazul în care mesajul nu a ajuns la destinație corect, lucru care este confirmat de faptul că asistenta nu a ajuns la salon, codul de alertare va fi trimis din nou de către dispozitivul de salon. Schema de principiu a procesului este prezentată în figura precedentă.
Pentru confirmarea faptului că asistenta a luat la cunoștință despre cererile făcute de pacienți, mesajul de pe LCD care indică patul și salonul de unde s-a efectuat cererea va fi reafișat. De asemenea pentru cazurile în care asistenta nu este atentă la acest dispozitiv sau este în altă încăpere, dispozitivul va emite o dată pe minut un semnal sonor a cărui volum poate fi modificat.
În momentul în care asistenta a luat la cunostintă despre cererile pacienților, ea va trebui să meargă în salon cât se poate de repede. Repede nu doar pentru a ajuta pacienții dar și pentru a opri alarma. Oprirea alarmării se face cu ajutorul cardului de asistentă individual. Cardul de asistentă ajută la recunoașterea asistentei de către sistem. O schema de principiu a operației de rezolvare a cererilor este prezentată în figura următoare:
Cu ajutorul cardurilor de asistentă, managerii spitalelor vor putea determina pe baza înregistrărilor memorate indicii de performanță a asistentelor.
Sistemul Central.
Dispozitivul central trebuie așezat în camera de gardă a asistentelor în apropierea unui calculator deoarece cablul USB care face legatura între acesta și dispozitiv nu trebuie să depășească 3 metri. Lungimea de 3 metri este recomandată deoarece asigură un transfer de date fără zgomote.
Dispozitivul prezintă o interfată cu utilizatorul prin intermediul unui ecran LCD și a unei tastaturi.
Pe ecranul LCD va fi afișată în permanență data și ora curentă. În momentul în care un pacient solicită o asistentă, pe ecran va aparea salonul și patul care a efectuat cererea. În momentul apariției cererii, aceasta va fi memorată în dispozitiv pentru o vizualizare ulterioară a evenimentelor. Dacă se realizează mai multe cereri în același timp, din saloane diferite, pe ecranul LCD se va afișa la interval de 1 minut câte o cerere până când asistenta va răspunde cererii respective. Ecranul LCD va afișa numai prima cerere dintr-un salon, deoarece în momentul rezolvării cererii afișate asistenta va încerca să ajute și restul pacienților din salonul respectiv, în cazul în care aceștia au nevoie.
Tastatura conține 12 taste dispuse în 3 colane și 4 linii, reprezentând cifrele de la 0 la 9 și cuvintele “OK”(butonul dreapta jos) și “Cancel”(butonul stânga jos). Tastatura permite asistentelor să modifice nivelul volumului de alarmare în funcție de necesități. Modificarea puterii alarmei se face apăsând una din tastele 2 sau 8 pentru creșterea respectiv reducerea volumului de alarmare. Intrarea în meniul dispozitivului poate fi făcută doar de către asistenta șefă prin intermediul cardului master. Pentru intrarea în meniu se va apasa butonul OK timp de 5 secunde, moment în care dispozitivul intră în rutina de așteptare a cardului master. După intrarea în meniu, utilizatorul are urmatoarele opțiuni: Vizualizare evenimente, Înregistrare asistentă, Stergere asistentă și Setare dată.
Vizualizare evenimente.
În cazul în care nu există evenimente în memoria dispozitivului, pe ecranul LCD se va afișa mesajul:” Nu există evenimente în baza de date”. Dacă există evnimente se va afișa primul eveniment. În funcție de apăsarea tastelor 4 sau 6 se va face avansarea în baza de date cu evenimente, înapoi respectiv înainte. Dacă se dorește ieșirea din acest meniu se va apasa tasta “C”.
Înregistrare asistentă
Utilizatorul se va folosi de tastele 2,4,6 și 8 pentru introducerea numelui. Prin tastele 2 și 8 se introduce litera iar prin tastele 4 și 6 se va face trecerea de la o literă la alta în cuvânt. Introducerea spațiilor se face prin simpla trecere peste locul ce se dorește a fi lăsat liber. Numele introduse pot să aibă maxim 16 caractere.
După introducerea numelui se apasă tasta OK moment în care dispozitivul va intra în rutina de așteptare a cardului asistentei care se vrea a fi înregistrat.
Reușita înregistrării asistentei va fi afișată pe ecranul LCD după care se va reveni la meniul principal.
Stergere asistentă.
În acest meniu se vor folosi tastele 4 și 6 pentru navigarea prin baza de date ce conține asistentele. În cazul în care în baza de date nu sunt înregistrate asistente pe ecranul LCD va apărea un mesaj ce va semnala acest lucru.
Iesirea din acest meniu se face apăsând tasta “C”. În momentul în care se doreste stergerea unei asistente se va apasa tasta “OK”. Pe ecranul LCD va apărea un mesaj în care se va solicita confirmarea stergerii. În cazul în care nu se doreste ștergerea din baza de date se va apasa butonul ”C” moment în care se va reveni la meniul anterior. Dacă într-adevăr se dorește ștergerea asistentei din baza de date, se va apăsa butonul “OK”, moment în care va apărea confirmarea stergerii.
Setare data.
În acest meniu cu ajutorul tastelor 4 și 6 ne deplasăm la locația pe care dorim să o modificăm iar cu butoanele 2 și 8 modificăm locația prin creșterea numărului respectiv prin descreșterea acestuia.
Butonul “C” este folosit pentru întoarcerea la meniul anterior fără modificarea datei iar butonul “OK” este utilizat pentru întoarcerea la meniul precedent cu salvarea datei.
Sistemul de salon.
Dispozitivul trebuie așezat în fiecare salon pentru ca asistenta să-și dea
seama de locația pacientului care are nevoie de ajutor. Sistemul prezintă un led ce stă aprins pe culoarea verde semnalând funcționarea corespunzătoare a acestuia.
Dispozitivul are nevoie de telecomenzi pentru a interacționa cu pacienții. Telecomenzile pot să fie cu fir, fără, sau ambele în funcție de dorința cumpărătorului.
La punerea în funcțiune dispozitivul va efectua un test în care va verifica dacă există telecomenzi cu fir, pentru a ști cum să codeze informațiile ce vor fi transmise către dispozitivul central.
La prima punere în funcțiune, deoarece este necesar măcar un card de asistentă, dispozitivul va aștepta telecomanda master. În momentul în care aceasta este sesizată se va face înregistrarea primului card de asistentă. După această primă înregistrare, ori de câte ori se apasă pe telecomanda master dispozitivul va intra în rutina de așteptare a unui nou card de asistentă. Dispozitivul poate memora până la 10 carduri. După sesizarea și înregistrarea cardurilor se va auzi o secvență de beepuri ce confirmă reușita memorării.
Dispozitivul necesită învațarea cardurilor nu doar pentru identificarea asistentelor de către sistemul central dar și pentru evitarea situațiilor de generare de evenimente false. Evenimentele false sunt reprezentate de apropierea altor carduri RFID ce nu aparțin sistemului.
Telecomenzile cu fir nu au nevoie de înregistrare. În sistem pot fi conectate maxim 10 telecomenzi cu fir. Telecomenzile fără fir necesită o rutină de învățare pentru ca dispozitivul să le recunoască pe acestea. Sistemul este prevăzut cu un sistem de siguranță care previne crearea unui eveniment în momentul în care altă telecomandă ce nu aparține salonului respectiv, este apăsată.
Pentru învațarea telecomenzilor fără fir nu este nevoie decât de un card de asistentă care a fost memorat în prealabil în dispozitiv. Sistemul nu ea
seama de locația pacientului care are nevoie de ajutor. Sistemul prezintă un led ce stă aprins pe culoarea verde semnalând funcționarea corespunzătoare a acestuia.
Dispozitivul are nevoie de telecomenzi pentru a interacționa cu pacienții. Telecomenzile pot să fie cu fir, fără, sau ambele în funcție de dorința cumpărătorului.
La punerea în funcțiune dispozitivul va efectua un test în care va verifica dacă există telecomenzi cu fir, pentru a ști cum să codeze informațiile ce vor fi transmise către dispozitivul central.
La prima punere în funcțiune, deoarece este necesar măcar un card de asistentă, dispozitivul va aștepta telecomanda master. În momentul în care aceasta este sesizată se va face înregistrarea primului card de asistentă. După această primă înregistrare, ori de câte ori se apasă pe telecomanda master dispozitivul va intra în rutina de așteptare a unui nou card de asistentă. Dispozitivul poate memora până la 10 carduri. După sesizarea și înregistrarea cardurilor se va auzi o secvență de beepuri ce confirmă reușita memorării.
Dispozitivul necesită învațarea cardurilor nu doar pentru identificarea asistentelor de către sistemul central dar și pentru evitarea situațiilor de generare de evenimente false. Evenimentele false sunt reprezentate de apropierea altor carduri RFID ce nu aparțin sistemului.
Telecomenzile cu fir nu au nevoie de înregistrare. În sistem pot fi conectate maxim 10 telecomenzi cu fir. Telecomenzile fără fir necesită o rutină de învățare pentru ca dispozitivul să le recunoască pe acestea. Sistemul este prevăzut cu un sistem de siguranță care previne crearea unui eveniment în momentul în care altă telecomandă ce nu aparține salonului respectiv, este apăsată.
Pentru învațarea telecomenzilor fără fir nu este nevoie decât de un card de asistentă care a fost memorat în prealabil în dispozitiv. Sistemul nu poate memora mai mult de 16 telecomenzi fără fir. Pentru înregistrarea unei noi telecomenzi asistenta va ține cardul apropiat de dispozitiv până când se aude o secvență de bip-uri fapt ce semnalează intrarea în meniul de programare. După intrarea în meniu, asistenta va ține cardul apropiat de dispozitiv până va auzi un număr de bip-uri corespunzătoare cu numărul telecomenzii ce se dorește a fi înregistrată. În acest moment se îndepartează cardul de dispozitiv și se acționează telecomanda fără fir ce se doreste a fi memorată. Reușita memorării telecomenzii va fi anunțată printr-o secventă de bip-uri.
În timpul funcționării normale a dispozitivului, la apropierea unui card înregistrat, ledul de funcționare normală se va aprinde în culoarea galbenă ceea ce semnifică identificarea cardului de către sistem. Intrarea dispozitivului în meniul de programare este semnalată de asemenea vizual, prin aprinderea ledului în culoarea roșie.
Interfața cu PC-ul.
Pentru a funcționa, programul de interfațare cu dispozitivul central are nevoie de un driver ce se găsește pe CD-ul din cutia dispozitivului. După instalarea driverului, programul poate fi pornit sau oprit la orice moment în timp. Programul are trei butoane: unul de citire a evenimentelor de pe sistemul central, unul de salvare a datelor și unul de ieșire.
Afișarea datelor citite din dispozitiv se face într-un tabel în care apar salonul și patul de unde s-a efectuat cererea, asistenta care a raspuns cererii, data și ora la care s-a făcut cererea și data și ora la care asistenta a ajuns în salon și a raspuns la nevoile pacienților.
Salvarea datelor este posibilă doar după ce s-a terminat citirea datelor sau utilizatorul a apăsat pe butonul de oprire a citirii datelor. Datele pot fi salvate pe orice mediu de stocare în format Excel. S-a ales acest format de stocare deoarece oferă posibilitatea așezării datelor în tabele. Un alt beneficiu al alegerii acestui format de salvare a datelor este portabilitatea maximă. Aproape toate calculatoarele din lume dispun de acest soft.
Cerinta principala ca acest program sa functioneze este să dispună de un port USB 2.0. Programul nu a fost testat pe USB 1.0.
În viitoarele versiuni ale softului de interfațare cu pc-ul va fi introdusă și opțiunea de printare directă a datelor. De asemenea, din motive de securitate, softul va necesita o licență care va fi achziționată o dată cu dispozitivele fizice.
Cap II. Prezentare sistem
II.1. Softul de interfațare a dispozitivului central cu Pc-ul
Cu ajutorul acestei interfețe, evenimentele memorate în dispozitivul central cu privire la cererile pacienților, răspunsurile asistentelor împreună cu timpii aferenți, pot fi transferate pe calculator și salvate în format Excel. Pe baza datelor obținute din memoria dispozitivului, utilizatorul poate stabili performanțele și eficiența asistentelor în rezolvarea nevoilor pacienților.
Aplicația permite vizualizarea înregistrarilor din dispozitivul central într-un tabel în care sunt trecute patul și salonul care au cerut asistență, asistenta care a ajuns la salon și a satisfăcut cererile pacienților, data și ora cererii, data și ora intervenției precum și un număr de contorizare.
Pentru funcționarea programului este nevoie ca driverul aferent dispozitivului central să fie instalat pe calculator. Driverul conține numărul de identificare al dispozitivului și stringul de descriere:”ALERTER_V10”. Când se startează, programul realizează teste de verificare a conexiunii cu dispozitivul central.
Programul dispune de 3 butoane: unul de citire a evenimentelor, unul de salvare a datelor în format Excel și unul de ieșire din aplicație. Butonul de citire a avenimentelor are și rolul de a opri transferul de date. Acest lucru se realizează o data cu startarea transmisiei, când, pe buton va aparea cuvântul “Stop”.
Butonul de salvare este inițial dezactivat. Doar la terminarea transmisiei utilizatorul va putea memora datele. În momentul apăsării pe acest buton se deschide dialogul de salvare care permite utilizatorului să aleagă locul și numele sub care vor fi salvate datele. La apasarea butonului “Save”, se va deschide în background fără a fi observabilă, o aplicație Excel unde datele citite din dispozitivul central vor fi salvate sub formă de tabel. Odată salvarea efectuată, datele pot fi scoase la imprimantă sau mutate pe alte calculatoare.
Butonul “ieșire” va inchide aplicația și comunicația cu dispozitivul central.
Deși timerul este setat pentru a genera întrerupere la 1 ms, sistemul de operare nu permite acest lucru. Sistemul de operare va ceda prioritatea tuturor dispozitivelor programului o dată la 55 ms. De aceea în rutina de tratare a intreruperii de timer se va folosi un contor care va citi 9 înregistrări din memoria dispozitivului. Dacă timpii de citire a magistralei USB nu sunt respectati, aplicația se va bloca deoarece bufferele de intrare – ieșire USB ale sistemului de operare nu pot fi resetate. Blocarea acestor buffere se datorează vitezei de citire care diferă de viteza de scriere.
II.2. Dispozitiv central
II.2.1. Functionare
La punerea sub tensiune pe LCD apare numele dispozitivului și data curentă a sistemului. Data sistemului va rămâne afișată pe ecran și în momentul în care apare cod de alertare.
După inițializarea sistemului se intră în bucla de așteptare a evenimentelor de la dispozitivele de salon. În momentul apariției unui eveniment, acesta va fi memorat în memoria externa a procesorului.
Dacă s-a primit cod de alertă de la unul din dispozitivele de salon, pe ecranul LCD va fi afișat salonul și patul de unde s-a efectuat cererea. În același timp se activează și sonorul de alarmare. În momentul salvării în memoria externă se va face un update și la variabila care conține numărul de evenimente care există memorate și la vectorul de reafișare a evenimentului. Vectorul de reafișare a evenimentelor este baleat o dată la 500 ms când se face și actualizarea variabilei care calculează secunda. Această baleere a evenimentelor a fost concepută în scopul maximizării eficienței asistentelor: două asistente nu vor merge la același salon.
Dacă s-a primit cod de card, ceea ce înseamnă că asistenta a ajuns în salon, se salvează acest eveniment în memoria externă, se actualizează vectorul de reafisare, se șterge ecranul LCD, și se dezactivează sonorul de alarmare.
Daca există mai multe cereri dintr-un anumit salon, în memoria externă va fi memorată o singura cerere. Dispozitivul testeaza daca de la ultimul eveniment de card există deja memorată o cerere din salonul respectiv. Daca un eveniment salonul respectiv a fost memorat, atunci următorul eveniment din același salon nu va mai fi salvat. După introducerea unui card de asistentă, de la salonul unde a fost introdus cardul se va memora în continuare o singură cerere. Această singură memorare are rolul de a eficientiza spațiul de memorie folosit.
Data curentă este citită la inițializarea sistemului, din memoria internă a procesorului. Odată cu data mai sunt citite din memoria internă numărul de asistente memorate și numărul de evenimente memorate.
Data curentă este actualizată cu ajutorul Timer 1 care funcționează în regim de real time clock deoarece genereaza întrerupere la 500 ms.
În acelasi timp cu așteptarea evenimentelor, dispozitivul citește și tastatura pentru a se vedea dacă se dorește intrarea în meniul de configurare sau modificarea volumului. Dacă se dorește intrarea în meniul de configurare, utilizatorul trebuie să țină apăsată tasta OK timp de 5 secunde. Intrarea în meniul de configurare este condiționată de prezența cardului RFID master. Pentru citirea cardului se pornește modulul serial deoarece procesorul principal nu comunică cu procesorul care citeste cardul RFID în permanență. Citirea cardurilor se face în permanență de către procesorul secundar pentru a evita complicarea comunicației și a minimiza numărul componentelor externe. În momentul în care cardul master a fost citit de 3 ori bine se intră efectiv în meniul de configurare. Meniul de configurare conține 4 înregistrari: Vizualizare evenimente, Înregistrare asistentă, Stergere asistentă și setare data.
În meniul de “Vizualizare evenimente”, datele sunt citite din memoria externă și afișate pe ecranul LCD. Cu ajutorul tastelor este posibilă deplasarea la stanga sau la dreapta în baza de date a evenimentelor.
În meniul “Înregistrare asistente” cu ajutorul tastelor stanga și dreapta se permite deplasarea printre cele 16 caractere ce vor constitui numele asistentei iar cu ajutorul tastelor sus și jos se balează literele. O dată introdus numele se intră în rutina de așteptare a cardului asistentei. Pentru aceasta se inițiaza o noua recepție pe modulul serial și se așteaptă codul de card. În cazul în care se iese din meniul de înregistrare fără a introduce un card sau un nume, înregistrarea nu va fi memorată.
În meniul de ștergere al asistentei se afișează pe ecranul LCD numărul de ordine și numele asistentei care sunt citite din memoria externă. Cu ajutorul tastelor dreapta și stânga se balează înregistrările din baza de date. La acest meniu s-a avut în vedere faptul că dacă în baza de date nu există înregistrări se afisează acest eveniment, dacă înregistrarea care se doreste a fi ștearsă este ultima, după ștergere se evita deplasarea în memoria externă la adresa următoare, în momentul în care se șterge o persoană, să existe o confirmare de decizie a stergerii și, de confirmare a faptului că înregistrarea a fost ștearsă.
Meniul “Setare dată” ajută utilizatorul să configureze data sistem pe baza căreia vor fi memorate întregistrările.
Deoarece sistemul poate fi conectat la un pc pentru salvarea evenimentelor, în rutina de întrerupere serială este așteptat un cuvant de start din partea programului ce rulează pe Pc. Dacă pc-ul inițiază o comunicație cu dispozitivul central, se începe citirea memoriei și trimiterea acestora pe modulul serial.
Recepția datelor se face tot în rutina de tratare a întreruperilor la modulul captură. În momentul în care se sesizează un început de transmisie wireless se pornește timer-ul. La generarea întreruperii se citește timerul și se observă dacă valoarea citită se încadrează între anumite valori. Deoarece se folosește un protocol de comunicație wireless de tip T-2T, rutina de tratare a înteruperii de captură conține două teste de timp care vor spune daca bitul citit este 1 sau 0.
Procesorul ales pentru realizarea acestui dispozitiv este PIC 18F452 deoarece dispune de două unități de Comparare/Captura/PWM, necesare la receptia datelor și la generarea sunetului de alarmă.
Atât schema electrică cât și pcb-ul aferent dispozitivului central sunt prezentate în Anexa 4 si Anexa 6.
II.2.2. Tastatura
Tastatura dispozitivului este construită pe 3 coloane și 4 linii. La intersecția unei coloane cu o linie va exista un buton. Această arhitectură a fost folosită în scopul minimizării numărului de pini folositi. Pentru a minimiza mai mult numărul de pini folosiți, liniile sunt multiplexate cu magistrala de date a modulului LCD. Această minimizare este folositoare datorită faptului că implementările viitoare ale acestui dispozitiv vor putea folosi un procesor cu un număr mai mic de pini.
Prin baleerea coloanelor se realizează citirea datelor. Primul pas în citirea tastaturii este însă setarea direcției liniilor ca intrare. Inițial coloanele au nivelul logic ‘1’. Setând ieșirea unei coloane pe ‘0’ logic, se citesc liniile. La intersectia coloanei selectate și a liniei de pe care s-a citit nivel ‘0’ logic, va exista o apăsare de buton. Liniile au rezistențe de pull-up deoarece nivelul logic când nu este nici o tastă apasată trebuie sa fie ‘1’.
După o citire a tastaturii, dacă există două butoane apăsate în același timp, funcțiile atașate butoanelor apasate se vor efectua în ordine secvențială în funcție de testul de citire a tastelor. Sesizarea faptului că există două taste apăsate în același timp se face prin memorarea acestora într-un vector. La o baleere a tastaturii, pe locațiile din vector unde există tastă apasată va fi memorată valoarea ‘1’ logic. Restul tastelor neapăsate va fi reprezentat de valoarea ‘0’ logic pe pozițiile corespunzătoare din vector.
După o baleere a tastelor, dacă se observă o valoare de ‘1’ logic în vectorul de taste, citirea se va repeta de câteva ori pentru confirmarea faptului că tasta citită ca fiind apăsată nu a fost de fapt un zgomot.
Dupa ce s-a realizat rutina de citire a tastaturii, se face o baleere a vectorului de taste. Pentru fiecare buton apăsat se va executa câte o rutină.
II.2.3. Modulul LCD
În prezent majoritatea dispozitivelor care necesită interfațarea cu omul folosesc un display realizat în tehnologia cristalelor lichide. LCD-urile(liquid cristal display) sunt prezente pe piață într-o varietate mare de modele de aceea, trebuie avută în vedere alegerea unuia care să se potrivescă aplicatiei. Pentru dispozitivul central s-a folosit un LCD ce afișează 2 linii a câte 16 caractere fiecare deoarece este ieftin și poate afișa atât data cât și evenimentele ce se produc.
LCD-urile dispun de o magistrală de date de 8 biti însă pot lucra și pe 4 biti în funcție de setările inițiale. Modulul LCD prezent în dispozitivul central folosește magistrala de date pe 4 biti, magistrală ce este multiplexată cu liniile tastaturii.
În funcție de opțiunea aleasă LCD-urile pot veni echipate cu un chip care generează tensiunea negativă necesară alimentării ledurilor de backlight. Această opțiune se reflecta în cost dar este mult mai acceptabilă decât realizarea unui circuit dedicat care ocupă spațiu în pcb și este și scump.
Pe langa magistrala de date, modulul LCD dispune și de pini de activare și dezactivare a modulului astfel încat aplicațiile care au restricție de consum de curent să nu le depașească decât atunci când este nevoie, pini de selectie al registrelor în care se vor scrie datele de pe magistrală: registre de control sau registre de date, pini de citire scriere cu ajutorul carora utilizatorul poate citi mesajul scris pe LCD sau poate scrie un mesaj pe LCD, și un pin de control al contrastului.
Pe ecranul LCD al dispozitivului central va fi afișată mereu data sistemului care este preluată de la un ceas de timp real implementat cu ajutorul modulului Timer1. Folosirea modulului Timer1 ca ceas de timp real este necesară deoarece produsul se încearcă a fi cât mai ieftin. Comparația se face cu un ceas de timp real extern care pe lângă faptul ca este destul de scump, mai necesită și spațiu pe pcb.
II.2.4. Buzzer
Scopul dispozitivului central este de a alerta asistentele asupra nevoilor pacienților. Pentru aceasta pe langă alertarea vizuală este folosită și cea auditivă. Un difuzor piezo-elecric de putere este pus în paralel cu o bobină care va crește nivelul tensiunii astfel încât la ieșirea buzzer-ului să existe un semnal de amplitudine mare.
Difuzorul piezo electric[19] a fost ales în defavoarea difuzorului cu membrană datorită prețului, fapt ce a redus costul de productie fără a reduce calitatea.
Cu ajutorul tranzistorului care are colectorul legat la VDD se crează acea ridicare de nivel. În baza tranzistorului menționat va exista un semnal PWM. Tranzistorul a cărui colector este legat la bobină va regla tonalitatea sunetului prin închiderea și deschiderea sa. Frecvența sunetului emis de buzzer este de aproximativ 3 KHz pentru a putea fi auzit de oameni.
II.2.5. Comunicația serială
Majoritatea sistemelor, fie ele dedicate sau pc-uri, dispun de o magistrală ce implementează comunicația serială. De ce? Pentru ce este simplă, dispune de registre cu ajutorul cărora se poate selecta viteza de transfer și nu are nevoie decât de 3 fire: transmisie, recepție și masa.
Comunicația serială a dispozitivului central trebuie să realizeze un transfer între trei module ale sistemului: transcieverul de USB, cititorul RFID și procesorul principal. Întrucat procesorul principal trimite date numai către transcieverul USB, linia TX a procesorului este directă având o diodă zener legată la masa pentru a se obține o stabilizare a tensiunii astfel încât să nu se depașească capacitățile electrice ale procesorului. Pe linia de recepție a procesorului sunt prezente cele două module care trimit date. Pentru aceasta se folosește o rezistență de pull-up și două diode, fiecare având catodul orientat către pinul TX al modulelor ce trimit. Diodele sunt necesare pentru a realiza functia SAU și a nu lega ieșirile celor două module direct.
Astfel, dioda orientată invers va preveni intrarea datelor dintr-un modul pe pinul de transmisie al celui de-al doilea. Rezistența de pull-up ține linia de transmisie pe nivelul ‘1’ logic. În momentul în care se inițiază o comunicație de la un modul, când pinul modulului va avea valoarea ‘0’ logic, intrarea în procesor va avea aceiași valoare deoarece dioda îndreptată către pinul modulului va permite trecerea curentului către masă. Cand va exista ‘1’ logic pe ieșiea TX a modulului, dioda va fi blocată și rezistența de pull-up va genera nivel high pe intrarea RX a procesorului.
Viteza de 62500 Kbaud a fost aleasă deoarece este singura care permite atât interfatarea celor două procesoare cât și interfațarea procesorului central cu pc-ul.
II.2.6. FTDI
Modulul FTDI[14] este cel care realizează comunicația efectivă între pc și dispozitivul central. El realizează conversia datelor venite de pe magistrala USB la magistrala seriala. Modulul FTDI are nevoie de memoria externă prezentă în schema dispozitivului pentru a memora textul de descriere al sistemului. Astfel când se face conexiunea între pc și dispozitiv, cel din urma va fi detectat ca “ALERTER_V10”. Aceasta daca a fost instalat driverul pentru sistemul de alertare a asistentelor. Pentru funcționarea corectă a modulului este nevoie de condensatorii de decuplare care se află foarte aproape de pinii de alimentare. Condensatorii de decuplare vor fi prezenti și la memoria externă.
Deși modulul a fost testat și la viteze mai mari s-a observat ca la interfațarea cu cele două procesoare există discrepanțe în sensul că softul de interfațare nu putea comunica cu dispozitivul central datorită unei mici modificări a vitezei venite din partea procesoarelor.
II.2.7. RFID
Modulul RFID(radio frequency identification)[1] folosește un procesor separat care trimite pe liniile de comunicatie serială codul valid de card.
Pe pinul CCP al procesorului se generează un semnal PWM de frecvența 125 KHz și factor de umplere 50%. Această frecvența este necesară pentru ca bobina din interiorul cardului să intre în rezonanță cu bobina dispozitivului. Cât timp cardul va primi energie de la bobina sistemului, memoria internă a cardului va genera numărul de identificare. Datele trimise de card prin intermediul bobinei dispozitivului vor fi introduse în amplificatorul LM358 care aduce semnalul de intrare la nivelele logice ‘0’ si ‘1’, specifice TTL. Datele amplificate cu ajutorul LM358 vor fi introduse în procesor prin intermediul întreruperii externe a carei functie se afla pe pinul RB0. Întrucât codul cardului este transmis prin eter, se folosește o codare de tip . De asemnea codul trimis conține o zona de detectie a erorilor. După prelucrarea datelor, codul poate fi utilizat în trimiterea pe magistrala serială a confirmării de card master necesar la intrarea în meniul de configurare.
II.2.8. Modul recepție wireless
Dipozitivul central folosește un transciever wireless care va trimite și recepționa datele pe frecventa 433MHz. Deși modulul[17] de recepție conține și un emitator, acesta nu va fi folosit.
Modulul wireless poate lucra în 4 moduri. Power down mode este primul mod de funcționare a modulului și constă în ținerea pinului de ENABLE în starea ‘0’ logic fapt ce face ca modulul să consume mai putin de un micro Amper. În acest mod modulul nu poate să primească sau să trimită date din și în eter.
Al doilea mod de funcționare, “Idle Mode”, reprezintă starea premergătoare transmisiei de date când modulul este setat ca transmițător. În acest mod curentul consumat este de 4,5A.
În modul de transmisie se face efectiv trimiterea datelor în eter.
În modul de recepție datele primite de către modul sunt trimise mai departe către procesor spre analiză.
Selectia functionării modulului wireless în mod recepție se face prin punearea pinului RX/TX la masa. Pe alimentarea modulului a fost amplasat un condensator de decuplare cu rolul de a stabiliza sursa de tensiune și a nu introduce paraziți pe liniile de transmisie și recepție. Pentru a controla sensibilitatea modulului la zgomotele din eter, o rezistenta de 100K a fost pusă la masă pe linia AN-OUT. Valoarea rezistenței a fost aleasă în urma testelor unde s-a observat că datele recepționate au zgomote mai mici.
Protocolul de comunicație folosit este T-2T. Acest protocol implică următoarele:
pentru nivelul ‘1’ logic: periada cât este citit nivel high este T
perioada cât este citit nivel low este 2*T
pentru nivelul ‘0’ logic: perioada cât este citit nivel high este 2*T
perioada cât este citit nivel low este T
Pentru inițierea transmisiei este necesară o aducere la nivel a semnalului. Aceasta înseamnă ca la o recepție primii biți nu vor fi luați în considerare deoarece au perioade foarte scurte(o micro secunda). Aducerea la nivel semnifică eliminarea zgomotelor de fond care pot afecta comunicatia. De asemnea pentru confirmarea existenței unei comunicații valide din partea dispozitivelor de salon codul producatorului va fi transmis de două ori la fiecare comunicație.
II.3. Dispozitivul de salon
II.3.1. Funcționare
La punerea sub tensiune a dispozitivului se verifică existența telecomenzilor cu fir. Această verificare se face prin testarea pinului RA4 care are un jumper ce poate fi pus la masă(J11). Testarea existenței telecomenzilor fixe este necesară pentru a ști ce cod vom trimite către dispozitivul central în caz de alarmare: dacă nu există telecomenzi fixe în sistem, telecomenzile fără fir vor fi afișate pe ecranul LCD al dispozitivului central încipand cu numărul 1. Daca există telecomenzi cu fir, cele fără fir vor fi afișate pe LCD începand cu numărul 16 deoarece se pot introduce maxim 15 telecomenzi în sistem.
După testul de existență a telecomenzilor cu fir, dispozitivul va citi eprom-ul intern pentru a vedea dacă sunt memorate carduri de asistente. În cazul în care citirea memoriei nu returnează nici un rezultat se intră în rutina de programare carduri. Se intră în această rutină de programare deoarece fără existența unui card de asistentă nu se pot înregistra în sistem telecomenzile fără fir. Așteptarea nu are limită de timp. Pentru a putea adauga carduri de asistente în sistem este nevoie de o telecomandă master a carui cod este scris în memoria dispozitivului. În momentul în care între codul primit de la receptorul wireless și codul memorat există egalitate, se intră în meniul de așteptare a cardului. Ieșirea din meniul de programare este semnalizată sonor cu ajutorul buzzer-ului existent în sistem.
După testele și inițializările inițiale dispozitivul intră în rutina de așteptare. Deoarece dispozitivul trebuie să primească comenzi și coduri de la mai multe module aflate în sistem, fiecarei funcțiii de așteptare îi va fi asignat un timp de timeout. Daca în timpul util asignat nu se produce nici un eveniment se trece mai departe.
Funcțiile de așteptare se referă la citirea telecomenzilor cu fir, a celor fără fir și a modulului RFID.
În momentul citirii unui cod valid de telecomandă fără fir se caută în memorie existența acestuia. Acest test este necesar pentru a putea deosebi telecomenzile ce aparțin dispozitivului de telecomanzile ce aparțin altor saloane. Dacă s-a găsit codul telecomenzii în memorie, se efectuează o actualizare a vectorului de retransmisie care conține locațiile paturilor. Pe pozitia x în acest vector se poate observa dacă există alarmare sau nu din partea pacientului aflat în patul x.
Pentru telecomenzile cu fir nu se mai face testul de existentă a acestora în memorie deoarece el a fost făcut la inițializarea sitemului.
Odată ce o telecomandă validă a fost recunoscută de procesor, se incepe împachetarea și trimiterea datelor. Codurile de alertare vor fi retransmise la un moment aleatoriu de timp, până în momentul când o asistentă intră în salon și asează cardul în dreptul dispozitivului. Retransmisia codurilor de alertare este posibila datorită actualizării curente a vectorilor de retransmisie. Se realizează procedura de retransmisie deoarece protocolul de comunicatie folosit nu implementează functia acknoledge care să returneze dispozitivului starea transmisiei.
Dacă în rutina de asteptare principală este citita telecomanda master, se va intra în meniul de programare al cardurilor RFID. Din meniul de programare se va iesi doar atunci când a fost apropiat cardul de dispozitiv și s-a citit un cod valid.
La primirea unui răspuns din partea modulului RFID, sistemul intră în asteptare. Asteptare deoarece cu ajutorul unui card RFID se pot realiza două operații:
Confirmarea venirii asistentei în salonul respectiv în scopul ajutării unui pacient sau, înregistrarea telecomenzilor fără fir existente în salonul respectiv.
Dacă asistenta ține cardul apropiat mai putin de 5 secunde, se va trimite către dispozitivul central din camera de garda confirmarea ajungerii asistentei în salon. În același timp se vor reseta ți vectorii de retransmitere a alertei.
Dacă cardul RFID este menținut în apropierea dispozitivului mai mult de 5 sec, se intră în meniul de programare a telecomenzilor fără fir. În acest meniu se vor balea zonele de memorie corespunzătoare celor 16 paturi. Baleerea se realizează atât timp cât cardul este mentinut în apropierea dispozitivului, și este semnalată auditiv cu ajutorul buzzer-ului sistemului. În momentul îndepartarii cardului, pe ultima pozitie din memorie baleată se poate introduce o telecomanda fără fir. Codul telecomenzii este citit de cateva ori pentru o confirmare că este corect după care este memorat. Ieșirea din meniul de configurare al telecomenzilor fără fir este semnalată printr-o secventă de sunete.
Schema electrică si pcb-ul acestui dispozitiv sunt prezentate în Anexa 3 și Anexa 5.
II.3.2. Modulul RFID
Tehnologia RFID este folosită în prezent într-o gamă mare de aplicații care acoperă multe domenii. În domeniul securitate, modulele RFID elimină nevoia folosirii cheilor. Singura componentă elecronică care interfațează dispozitivul de alarmă de cardul RFID este bobina. În cazul unui scurtcircuit pe această bobină, singurul lucru afectat în sistem va fi recunoașterea cardurilor.
De asemnea în domeniul comercial, tehnologia RFID este folosită la recunoașterea produselor.
Modulele RFID sunt prezente pe piață în diferite tipuri: carduri, brelocuri pentru chei însă există și tehnologii mai avansate cum sunt modulele tip implant ce pot fi introduse atât în om cât și în animale.
Modulele RFID merg pe trei tipuri de frecvente: joasă(125 – 135KHz), inaltă frecvență(13,56 MHz) și foarte inaltă frecvență(850MHz – 2,46 GHz). Cele din urmă au o raza de actiune de pana la 12 metri, și sunt folosite în sistemul de transport, parcări și managementul containerelor.
Atât dispozitivul de salon cât și cel din camera de garda a asistentelor vor folosi module RFID cu frecvența de 125KHz deoarece implica costuri de producție mici și consum minim de curent.
Modulul RFID este cel cu ajutorul caruia asistentele se pot identifica în sistem. Pe ieșirea CCP a procesorului se generează un semnal PWM de frecvență 125KHz și factor de umplere 50%. Deoarece nu are puterea necesară de a excita bobina de comunicație, semnalul este trecut printr-un amplificator realizat cu un MOSFET și un tranzistor bipolar PNP. Numărul de spire al bobinei și condensatorul legat la masă trebuie sa fie la rezonanță. În momentul activarii modulului, semnalul introdus în bobina va crea un câmp electric care va alimenta cardul RFID. Odată alimentat, cardul va începe să trimită codul memorat în memoria sa. Numărul de identificare folosește codul și are o stuctură a cărui mapare este prezentată în figura urmatoare:
Primii 9 biți reprezintă headerul cardului și sunt programați ca “1”. Datorită configurației datelor și a biților de paritate această secvență nu se mai repetă nicăieri în cod. Headerul este urmat de 10 grupuri a câte 4 biți de dată ceea ce permite obținerea unui număr extrem de mare de combinații(100 de miliarde). Ultimul grup de 4 biți reprezintă biții de paritate de colană iar biții P0 – P9 reprezintă biții de paritate pe linie. Bitul S0 este bitul care îmi semnalează sfârșitul transmisiei. Primele doua grupuri de 4 biți(D00 – D03 si D10 – D13) reprezintă biții de identificare a clientului. Restul grupurilor, cei 32 biți de date rămași îl constituie codul care va fi memorat si prelucrat de către dispozitiv.
Odată ce datele trec de bobina modulului RFID sunt redresate și aduse la nivelele logice TTL.
Datele sunt sesizate de către procesor pe pinul de intrerupere externa(RB0). O dată cu citirea datelor se face și decodificarea din cod în cod normal. După verificarea corectitudinii codului, acesta este trimis mai departe pentru a realiza funcțiile sistemului.
II.3.3. Telecomenzile cu fir
Deoarece folosirea telecomenzilor cu fir implică citirea unui nivel de tensiune pentru a vedea ce buton a fost apăsat, s-a recurs la varianta folosirii unui generator de curent constant. Dacă se folosea simpla citire a tensiunii, pentru detectarea poziției butonului care a fost apăsat trebuiau să existe în sistem rezistențe de valori diferite(rețea R-2R). Astfel cu ajutorul a două diode și a unui tranzistor bipolar PNP s-a reușit realizarea sursei de curent constant. Căderea de tensiune pe baza tranzistorului este de Vdd -1,2 V datorită diodelor. Tranzistorul se deschide și permite curentului să treacă. Colectorul tranzistorului este legat la intrarea modulului comparator. O altă sursă de curent constant a fost realizată pentru a genera o tensiune crescatoare la a doua intrare a comparatorului. Cand se dorește citirea tastaturii se pune pinul RA4 în starea ‘1’ logic. În acest moment condensatorul începe să se încarce și nivelul tensiunii de pe condensator este masurat cu nivelul tensiunii de pe intrarea unde s-a pus prima sursa de curent. Când nivelul tensiunii pe condensator este egal cu nivelul tensiunii de la generatorul de curent vom avea o întrerupere. În funcție de butonul pe care se apasă, perioada de la punerea pinului RA4 pe ‘1’ logic până la generarea întreruperiii poate să crească sau să scadă. Această perioadă este masurată cu ajutorul unui timer și în funcție de anumite valori prestabilite, programul va ști ce tasta a fost apăsată.
II.3.4. Modulul wireless si telecomenzile fără fir
Telecomenzile wireless folosesc un codor care la apăsarea tastei va genera un șir de biți codat în protocol T-2T cu o perioada de bit de aproximativ 1,35 ms și cu o lungime de 24 de biți. Codul este apoi cedat către modulul wireless care îl trimite în eter pe frecvența de 433MHz.
Dispozitivul de salon este de asemnea echipat cu un transciever wireless pe frecventa 433MHz. La primirea datelor modulul wireless trebuie să lucreze în regim de receptor. Pentru aceasta pinul RX/TX al modulului trebuie setat pe ‘0’ logic. Datele primite din eter sunt trimise mai departe către procesor care dacă în momentul respectiv rulează rutina de citire a acestui modul va receptiona datele.
Modulul wireless are și un pin pentru stabilirea sensibilității dispozitivului la zgomotele din exterior. De aceea pe acest pin s-a pus o rezistență de 100K care ajută la receptionarea de date valide, neafectate de zgomotele din eter.
Deasemnea modulul dispune de un pin de enable care permite oprirea si pornirea sa atunci când este nevoie. În aplicatiile care necesită consum de curent cât mai mic, acest modul este ideal.
Pentru trecerea de la modul de lucru receptie la cel de transmisie este nevoie de o rutină de inițializare care dacă nu este respectată poate duce la încetinirea acestui modul.
Atat pentru recepția cât și pentru transmisia datelor se folosește protocolul T – 2T deoarece este usor de implementat.
Protocolul de transmisie folosit de dispozitivul de salon folosește un număr de biți pentru aducerea la nivel a liniei de transmisiei. Datorită zgomotelor din eter, datele valide trimise de dispozitivul de salon pot să ajungă modificate la dispozitivul central. În urma testelor s-a observat că după trimiterea biților de aducere la nivel, timp de aproximativ 7 ms nu mai apare nici un zgomot pe linia de transmisie.
Mesajele transmise către dispozitivul central nu diferă ca număr de biți(88) pentru a se putea realiza o prelucrare mai usoară a datelor. Mesajul de generare alerta conține codul de identificare al producătorului, codul de identificare al salonului de unde s-a generat cererea, 24 de biți de ‘0’ cu ajutorul cărora se ajunge la aceiași dimensiune cu mesajul trimis în cazul asistentelor, și codul patului. Mesajul de confirmare a ajungerii asistentei în salon contine codul de identificare al producatorului, codul salonului care a trimis mesajul și codul de identificare al asistentei. Pe baza codului de identificare asistentă ce a fost transmis se face cautarea în memoria dispozitivului central.
Cap III. Prezentare generală a procesoarelor folosite
III.1. Procesorul PIC 18F452
III.1.1. Arhitectură
Procesorul PIC18F452[13] face parte din gama procesoarelor cu adevărat performante din familia Microchip. Numărul mare de pini și de pachete în care este livrat fac din acest procesor un dispozitiv foarte util în aplicațiile complexe. Cu o memorie flash de 32 Kocteti și un EEPROM intern de 256 de octeti, PIC18F452 poate fi folosit în aplicații unde programele sunt foarte complexe. Printre trăsăturile sale menționăm că poate merge cu viteze de până la 40Mhz, întreruperilor li se poate atașa un nivel de prioritate, dispune de trei întreruperi externe, are două unități PWM, consumă puțin curent iar flashul și eepromul sunt de mare viteză. Pe lângă aceasta el poate funcționa la temperaturi ce țin de domeniul industrial(-55 grade Celsius – 125 grade Celsius).
Arhitectura de principiu a acestui procesor este prezentata in figura urmatoare:
Ca arhitectura, procesorul 16F648 folosește arhitectura Harvard în care programul și datele sunt accesate de pe magistrale separate din memorii separate. Această arhitectură face ca procesorul să ruleze mai rapid decât pe o arhitectură Von Newman unde programul și data sunt aduse din aceiași memorie. Sursa de clock este divizată intern cu 4 pentru a obtine perioade de clock separate care nu se suprapun. Acestea sunt numite Q1, Q2, Q3, Q4. Intern, program conter este incrementat la fiecare ciclu Q1 iar instrucțiunea este adusă din memorie și memorată în registrul de instrucțiuni în ciclul Q4. Perioadele Q2 și Q3 sunt destinate decodificarii instrucțiunii după cum se poate observa din figura urmatoare:
Opcode-urile au dimensiunea de 16 biti iar pipeline-ul în două stadii suprapune aducerea din memorie și executia instructiunilor. Fiecare ciclu de instructiune constă în cele 4 perioade de clock(Q1-Q4). Operatia de fetch este facută astfel încât aceasta consumă un ciclu de instrucțiune în timp ce decodarea și execuția instrucțiunii ocupă un alt ciclu de instrucțiune. Dar, datorită pipeline-ului cele trei operații se execută într-un singur ciclu instrucțiune dupa cum se observa in figura urmatoare:
Dacă o instrucțiune face ca program counter să se schimbe(instrucțiuni de genul GOTO) atunci este nevoie de două cicluri pentru a executa instrucțiunea. Operația de fetch începe odată cu incrementarea program counter și stadiul Q1. În stadiul de execuție, instrucțiunea este memorată în registrul de instrucțiuni(IR) în ciclulQ1. Aceasta instrucțiune este apoi decodată și executată în stadiile Q2,Q3 și Q4 a celui de-al doilea ciclu instructiune. Memoria de date este folosită în stadiile Q2 la citirea operanzilor și în stadiul Q4 pentru scriere a destinatiei.
În cele ce urmeaza se va face o prezentare a perifericelor ce intră în alcătuirea procesorului 18F452.
III.1.2. Porturi de intrare/ieșire
Procesorul PIC 16F452 dispunde de 5 porturi generale, cu litere ce pornesc de la A și se termina cu E. Porturile pot fi configurate individual, ca și pinii acestora, prin intermediul a trei registre: TRISx, PORTx si LATx. Primul port, TRISx, controlează direcția datelor pe port. Daca scriem 1 pe un bit al acestui port, pinul corespunzător acestuia va putea fi folosit ca intrare digitală. Daca în registrul TRIS avem biți de 0, pinii respectivi sunt considerati ieșire. Registrul PORTx este cel care conține datele efective al pinilor. O scriere în acest registru va seta pinii portului respectiv la valorile logice ale biților. O citire din PORTx va transfera în memorie datele de la pinii procesorului. LATx reprezintă registrul latch al fiecărui port. Cu ajutorul său se pot scrie sau citi valorile memorate în latch-urile pinilor. Deoarece arhitectura pinilor procesorului este diferită datorită modulelor care sunt multiplexate pe aceștia, în continuare se va prezenta o schemă de principiu a pinului RB0, indentică cu cea pentru pinii RB1 și RB2:
Toți pinii de uz general au două diode de protecție legate la Vdd și masă în cazul unei suprasarcini. De asemenea, pentru portul B există opțiunea activării sau dezactivării pull-up-ului intern ceea ce este foarte util deoarece nu mai necesită componente externe.
III.1.3. Modulele Timer
III.1.3.1. Timer 0
Modulul Timer 0 poate fi folosit atât ca un timer cât și ca un counter, lucrează pe 8 biți sau 16 în funcție de preferințe, are un prescaler programabil pe 8 biți și poate genera întreruperi.
De asemena sursa clockului poate fi selectată între frecvența oscilatorului /4 sau, dacă se dorește funcționarea Timer 0 ca un counter, impulsurile venite de la pinul RA4 al procesorului. Selectarea modulului counter se face prin setarea bitului T0CS. Bitul TOSE din registrul OPTION_REG va spune procesorului la ce tip de schimbare de nivel se va produce incrementarea Timer 0: tranziție low-high sau high-low.
Schema bloc este urmatoarea:
Registrul TMR0H nu reprezintă partea high a numărului ce sa va încarca în timer ci mai degrabă o versiune bufferută a acestuia. Registrul nu poate fi scris sau citit direct. Partea high a numărului ce va fi scris în timer 0 va fi citită odată cu TMR0L ceea ce elimină necesitatea verificării numărului încărcat.
Registrul folosit pentru configurarea timerului 0 se numeste T0CON și este prezentat în cele ce urmează.
TMR0ON permite pornirea și oprirea timerului ceea ce-l face util în aplicatiile unde nu necesită funcționarea sa continuă.
T08BIT setează modul de functionare al timerului: ca timer/counter pe 8 sau 16 biți. Când funcționează pe 8 biți registrul TMR0H nu mai este luat în considerare.
T0CS este bitul care va seta originea clock-ului. Intern adică frecvența oscilatorului/4 sau sursă externă de pe pinul RA4.
Bitul TOSE setează frontul pe care se va incrementa registrul de numărare atunci cand modulul funcționează în regim de counter.
Bitul PSA permite utilizatorului să treacă peste unitatea de prescaler a modulului și să incrementeze registrul TMR0 la fiecare clock intern al procesorului.
Cei mai putini semnificativi biți ai registrului T0CON sunt cei cu ajutorul cărora se poate stabili un prescaler pentru sursa modulului. Prescalerele pot impărți clock-ul de intrare astfel încât la ieșire să am o frecvență de clock echivalentă cu frecvența oscilatorului/32.
Pe langa acest registru, modulul timer0 mai poate avea nevoie de biții TMR0IE din registrul INTCON și TMR0IF din același registru, dacă aplicația cere ca timer-ul să lucreze pe bază de întreruperi. De asemnea, daca sursa folosită de Timer0 este externă este necesară setarea bitului TRISA4 din registrul TRISA ca intrare.
III.1.3.2. Timer 1
Modulul Timer1 este un counter/timer ce operează pe 16 biti în sensul crescător al incrementării, poate opera pe baza unui clock extern și poate genera întrerupere la depășirea de 0xFFFF la 0x0000. Schema de principiu este urmatoarea:
Toți biții care se pot observa în schema de mai sus și care controleaza modulul Timer1, sunt prezenți în registrul de configurare T1CON:
Bitul RD16 oferă posibilitatea utilizatorului să citească sau să scrie în registrul de incrementare într-o singură operație pe 16 biți sau în două operații pe 8 biți.
Biții 5, 4 și 3 stabilesc prescalerul ce va fi folosit de către acest modul.
În partea dreaptă a schemei se poate observa că între pinii T1OSI(intrare) și T1OSO(amplifier out) există un circuit oscilator ce poate genera frecvențe de până la 200Khz. Acest circuit este construit pentru oscilatoarele externe de tip low power în special pentru cele de 32KHz. Acest circuit poate fi activat sau dezactivat cu ajutorul bitului T1OSCEN.
Bitul T1SYNC are rolul de a permite sincronizarea clock-ului extern cu cel al magistralei interne atunci cand modulul functionează în regim de counter.
Regimul de counter sau cel de timer pot fi selectate prin setarea sau resetarea bitului TMR1CS iar cel mai putin semnificativ bit al registrului T1CON permite oprirea sau pornirea modulului în funcție de necesităti.
Pentru a folosi acest timer pe baza întreruperilor generate la overflow de la 0xFFFF la 0x0000 este necesară setarea bitului TMR1IE din registrul PIE1. Întreruperea va fi sesizată prin setarea bitului TMR1IF din registrul PIR1.
De asemenea, ca și la modulul Timer0, registrul TMR1H va fi actualizat în momentul scrierii TMR1L.
III.1.3.3. Timer 2
Timer 2, spre deosebire de de primele două module, este mai simplu ca arhitectură deoarece sursa sa de clock nu poate fi decât frecvența oscilatorului/4, nu poate lucra ca un counter și lucrează pe 8 biți. Pentru a se apropia însă ca performanțe de celelalte module, timer 2 dispune de un postscaler care îi permite să genereze overflow la perioade mari de timp. Schema de principiu a acestui modul este prezentată în cele ce urmează:
Cu ajutorul registrului de configurare T2CON se poate seta prescalerul, postscalerul, și se poate activa sau dezactiva acest modul. Atat prescalerul cat și postscalerul sunt resetate atunci când apare o scriere în TMR2 sau T2CON, sau, la resetul dispozitivului.
Deasemenea, timer 2 poate generea întreruperi la overflow, dar numai daca intreruperea asociata este activată. Biții care controlează întreruperile modulului Timer 2 sunt TMR2IE din registrul PIE1 și TMR2IF din registrul PIR1. Timer 2 generează overflow atunci când registrul numărător TMR2 este comparat cu registrul PR2 și se constată egalitate.
III.1.3.4. Timer 3
Modulul permite lucrul pe 16 biți, generează overflow de la 0xFFFF la 0x0000, poate fi sursă pentru module CCP și poate fi resetat de către acestea.
Asemanator celorlalte module, Timer 3 are o sursă selectabilă de clock: frecvența oscilatorului/4 sau oscilatorul intern al Timer1 care poate genera frecvențe de până la 200Khz. De asemenea există posibilitatea sincronizarii clock-ului extern cu cel al magistralei interne. Registrele folosite de Timer 3 sunt prezentate in tabelul ce urmeaza:
Legenda : x=necunoscut; u=nemodificat; -=neimplementat, citit ca ‘0’.
III.1.4. Modulul detecție tensiune alimentare joasă
În multe aplicații salvarea datelor și a configurației sistemului este esentială. De aceea s-a creat așa numitul “low voltage detect module”. Cu ajutorul său se poate programa nivelul de tensiune la care se generează întrerupere de atenționare. În timpul rămas până la caderea completă a tensiunii, se poate programa trecerea pe baterii a dispozitivului sau salvarea datelor esentiale.
Cu ajutorul registrului de configurare LVDCON se pot seta nivelurile de tensiune la care procesorul să sesizeze scăderea acesteia și de asemena pe poate activa sau dezactiva acest modul. De notat este faptul că acest modul operează când procesorul este în starea “sleep”. În momentul în care este sesizată o scădere a tensiunii, procesorul setează bitul LVDIF din registrul PIR1, își reia activitatea și încarcă programul de la adresa vectorului de întrerupere corespunzator acestui modul.
III.1.5. Modulul de captură/comparare/PWM (CCP)
Procesorul PIC 18F452 dispune de două module de captură/comparare/PWM. Fiecare modul CCP (Captură/Comparare/PWM) conține un registru de 16 biți, care poate funcționa ca registru de captură pe 16 biți, ca registru de comparare pe 16 biți sau ca registru PWM master/slave pentru ciclul util. Următorul tabel prezintă sursele de timer ale modurilor modulului CCP.
Modulele CCPx folosesc registrele CCPxCON pentru stabilirea configurației inițiale a modulului:
Bitii DCxB1 si DCxB0 reprezintă cei mai puțini semnificativi biți din registru de configurare a unității PWM și sunt nefolosiți de către celelalte module.
Modul de funcționare a modulelor CCP este stabilit prin configurarea celor mai putin semnificativi biți ai registrelor CCPxCON:
0000 = Modulul CCP este oprit
0001=Modulul CCP funcționeaza în regim de comparate(seteaza flagul CCPxIF la egalitate)
0100 = Modulul CCP funcționeaza în regim de captura la fiecare front descrescător
0101 = Modulul CCP funcționeaza în regim de captura la fiecare front crescător
0110 = Modulul CCP funcționeaza în regim de captura la fiecare al 4-lea front crescător 0111 = Modulul CCP funcționeaza în regim de captura la fiecare al 16-lea front crescător 1000 = Modulul CCP funcționează în regim de comparare. La initializare pinul CCP este setat pe nivel ‘0’ logic iar când apare o condiție de egalitate, pinul este forțat pe ‘1’ logic
În același timp se seteaza și flagul CCPIF
1001 = Modulul CCP funcționeaza în regim de comparare. La inițializare pinul CCP este setat pe nivel ‘1’ logic iar când apare o condiție de egalitate, pinul este forțat pe ‘0’ logic
În același timp se setează și flagul CCPIF.
1010 = Modulul CCP funcționează în regim de comparare. Se va genera întrerupere software când apare condiție de egalitate. Pinul CCP nu va fi afectat.
1011 = Modulul CCP funcționeaza în regim de comparare. Bitul CCP1IF este setat pe 1 la egalitate intre intrari și pinul CCP1 reseteaza Timer1.
11xx = Modulul CCP funcționeaza în regim de PWM.
Cand cele două module CCP sunt folosite ca unitați PWM, vor avea aceiași frecvență deoarece folosesc același timer: Timer 2. De asemena cele două module, atunci când sunt utilizate ca unitați de comparare, pot fi configurate să reseteze timer1 sau timer 3 în funcție de baza de timp folosită.
III.1.5.1. Modul Captură
In acest mod Timer 1 sau Timer 3, în funcție de setare, sunt citiți în momentul în care apare un eveniment pe pinul RC2. Prin eveniment se întelege unul din urmatoarele:
fiecare front descrescător
fiecare front crescător
fiecare al 4-lea front crescător
fiecare al 16-lea front crescător
Dacă apare un evenimet iar valoarea din registrele de numărare al Timer1 sau Timer 3 nu este citită, primul eveniment se pierde. La reset pinul RC2 este configurat ca ieșire și orice scriere în el poate genera o captura. Pentru ca modulul CCP să funcționeze în modul captură, timerul folosit trebuie să fie setat ca timer sau ca un counter sincronizat.
Prescalerul este resetat automat când se trece de la un mod de captură la altul, modulul CCP este oprit sau operează în alt mod. De asemena, cand se schimba modul de capură o întrerupere falsă poate apărea, de aceea bitul CCP1IE din registrul PIE1 ar trebui ținut pe 0 în timpul unei astfel de operații iar bitul CCP1IF setat pe 0 dupa această operație.
III.1.5.2. Modul Comparare
În modul Comparare, valoarea registrului de 16 biți CCPR1L este comparată continuu cu valoarea perechii de registre TMR1 sau TMR3. Când se produce o potrivire, pinul RB2/CCP1 este :
pus pe ‘1’
pus pe ‘0’
rămâne neschimbat
este schimbat dintr-o stare logică în alta
Acțiunea asupra pinului este bazată pe valoarea biților de control CCP1M3:CCP1M0 (CCP1CON<3:0>). În același timp este setat bitul de flag CCP1IF.
Modulele de numarare selectate, Timer1 sau Timer 3, trebuie sa lucreze in modul timer sau counter sincronizat. Modul comparare poate sa genereze asa numitul “special event triger” care va reseta continutul registrului de numarare al timerului cu care lucreaza. Resetarea se face atunci cand apare conditie de egalitate si se genereaza intrerupere. La selectarea generarii triger-ului de eveniment special pinul aferent modulului CCP isi va pastra starea logica.
III.1.5.3. Modul PWM
In modul PWM – Modulatie prin lațimea pulsului (Pulse Width Modulation), pinul CCP va genera un semnal PWM a cărui rezoluție poate ajunge până la 10 biți.
O ieșire PWM are o bază de timp (perioada) și un timp în care ieșirea stă în ‘1’ (ciclul util). Frecvența pentru PWM este inversul perioadei (1/perioada).
Perioada PWM este specificată prin scrierea în registrul PR2. Ea poate fi calculată cu formula urmatoare :
Perioada PWM = [(PR2)+1]*4*TOSC*(valoarea prescaler-ului pentru TMR2)
Frecvența PWM este definită ca 1/[perioada PWM].
Cand TMR2 este egal cu PR2, se produc următoarele trei evenimente în următorul ciclu de incrementare :
TMR2 este resetat
Pinul CCP1 este setat (exceptie : dacă ciclul util PWM =0%, pinul CCP1 nu va fi setat)
Ciclul util PWM este memorat din CCPR1L in CCPR1H.
Postscaler-ul pentru Timer2 nu este folosit la determinarea frecventei PWM. Acesta poate fi folosit pentru a avea o rata automata de modificare la o frecventa diferita de cea a iesirii PWM.
Ciclul util PWM este specificat prin scrierea în registrul CCPR1L și a biților CCP1CON<5:4>. Este disponibilă o rezoluție de până la 10 biți : CCPR1L conține cei mai semnificativi 8 biți și CCP1CON<5:4> conține cei mai puțin semnificativi 2 biți. Această valoare pe 10 biți este reprezentată de CCPR1L:CCP1CON<5:4>. Ecuația urmatoare este folosita pentru a calcula ciclul util PWM în timp :
Ciclul util PWM = (CCPR1L:CCP1CON<5:4>)*TOSC*(valoarea prescaler-ului pentru TMR2)
CCPR1L și CCP1CON<5:4> pot fi scrise oricând, dar valoarea ciclului util nu este memorarată în CCPR1H decât dupâ o potrivire între PR2 și TMR2 (de exemplu cand perioada este completă). În modul PWM registrul CCPR1H poate fi doar citit.
Registrul CCPR1H și un latch intern pe 2 biți sunt folositi pentru a buffera dublu ciclul util PWM. Această buffer-are dublă este esentială pentru o funcționare PWM fără paraziti.
Cand CCPR1H și latch-ul pe 2 biți se potrivesc cu TMR2 concatenat cu un clock Q pe 2 biți sau cu 2 biți ai prescaler-ului pentru TMR2, pinul CCP1 este resetat.
Rezolutia maximă PWM (numărul de biți) pentru o frecventa PWM data este :
log(FOSC / FPWM) / log(2) biți.
Daca valoarea ciclului util PWM este mai mare decat perioada PWM, pinul CCP1 nu va fi resetat.
Pasii următori trebuie urmați la configurarea modulului CCP pentru funcționarea în modul PWM:
Setare perioadă PWM prin scrierea în registrul PR2.
Setare ciclul util PWM prin scrierea în registrul CCPR1L și a biților CCP1CON<5:4>.
Configurare pinul CCP1 ca ieșire prin resetarea bitului TRISB<3>.
Setare valoare prescaler pentru TMR2 și validare Timer2 prin scrierea în T2CON.
Configurare modulul CCP1 pentru funcționare în modul PWM.
Cateva exemple configurare a registrelor modulului PWM pentru a obține diferite frecvente la o viteza de 40Mhz, sunt prezentate în tabelul ce urmează:
Registrele asociate modulului CCP1 functionand în modul PWM sunt urmatoarele:
Legenda : x=necunoscut; u=nemodificat; -=neimplementat, citit ca ‘0’. Celulele hasurate nu sunt folosite de PWM si de Timer2.
III.1.6. Modulul port serial sincron master(MSSP)
Acest modul este folosit pentru comunicațiile seriale între procesor și celellalte periferice. Comunicațiile sunt de tip serial sincron și sunt de două tipuri: I2C și SPI(Serial Peripheral Interface). În modul I2C sunt suportate modurile master, slave și multi-master.
Registrele folosite la configurarea acestui modul sunt SSPCON1 și SSPCON2. Pe lângă acestea modulul dispune și de un registru de stare SSPSTAT. Cei mai semnificativi 2 biți ai acestui registru pot fi scriși și sunt folosiți când modulul lucrează ca SPI.
III.1.6.1. Modul SPI
Modul SPI permite trimiterea și primirea sincronă simultană a 8 biți de dată. Modulul SPI poate să lucreze atât în mod master cât și slave. Comunicațiile pentru modul SPI se realizeaza cu ajutorul celor 3 pini: data seriala iesire(pin RC5), dată serială intrare(pin RC4) și clock(pin RC3). Mai poate exista un al patrulea pin care va fi folosit în modul slave(pin RA5) care precizează dispozitivul slave selectat.
În modul SPI sunt folosite 4 registre: unul de stare(SSPSTAT), unul de control(SSPCON1), un buffer de recepție/transmisie(SSPBUF) și un registru de shiftare care nu este accesibil direct(SSPSR). Registrul SSPSR este folosit la shiftarea datelor în și dinspre exterior. SSPBUF este registrul din care se vor citi datele primite de pe magistrala și se vor scrie date ce vor fi trimise pe magistrală. Impreună cu registrul de shiftare, SSPBUF asigură o dublă bufferare în operațiile de recepție.În momentul în care registrul de shiftare citește un octet de pe magistrală, îl transferă în registrul SSPBUF și setează bitul de întrerupere SSPIF.
La inițializarea modulului SPI este necesară configurarea biților din SSPCON1 și a celor 2 biți mai semnificativi din registrul de stare. Ei setează functionalități cum ar fi:
Selectarea modului master sau slave, faza de citire a eșantioanelor(la mijloc sau la sfarsitul timpului de 1 bit), frontul clock-ului la care data va fi trimisă pe magistrala sau rata clock-ului.
Registrul SSPBUF dispune de un flag BF(buffer full) care ne spune cand putem citi data din registru. De asemena modulul dispune de un bit de detecție a coliziunii (WOL) de scriere care ne asigură că data citita este corectă. Acest bit trebuie resetat de către utilizator.
În figura urmatoare se prezintă o conexiune tipică între 2 procesoare. Procesorul 1 care este master initiază un transfer de date trimițând pe magistrală semnalul de clock după care începe să trimită date pe linia SDO. Dacă configurările celor două procesoare sunt aceleași. datele trimise de un procesor sunt aceleași cu datele primite de al doilea procesor în sensul timpului
III.1.6.2. Modul I2C
Modulul MSSP în modul I2C implementează toate funcțiile pentru master și slave. De asemenea se generează întrerupere hard la START și STOP pentru a verifica disponibilitatea magistralei în modul multi master.
Pe lângă comunicația clasică, modulul I2C implementează și adresarea pe 7 sau 10 biți. Doi pini sunt folosiți pentru comunicație: pinul de dată serială (pin RC4) și pinul de clock serial (pinul RC3). Pentru modul de funcționare I2C, modulul MSSP folosește 6 registre: două de control(SSPCON1 și SSPCON2), registrul de stare(SSPSTAT), registrul de emisie/recepție(SSPBUF), registrul de shiftare(SSPSR) și registrul de adrese(SSPADD).
Registrul de transmisie/recepție și registrul de shiftare asigură ca și la funcționarea SPI, dubla bufferare la citire a datelor. Astfel, imediat ce o dată a fost primită, un alt octet poate sa înceapă a fi receptionat. Registrele de configurare asigură inițializarea device-ului și funcționarea sa în parametriii doriți de utilizator. Biții acestor registre setează funcții cum ar fi: modul de funcționare – master sau slave, detecția coliziunii la scriere, detectia erorii de overflow( atunci cand se primeste un octet dar cel precedent nu a fost încă citit din registrul de transmisie/recepție), repetarea startului, setarea diferitelor flaguri precum și activarea și dezactivarea modulului.
Registrul de adrese SSPADD contine adresa procesorului când acesta lucrează în modul slave.
III.1.7. Modulul Convertor Analog-Digital
La procesorul 18F452 modulul convertorului analog-digital are 8 intrări analogice care încarcă un condensator cu rol de eșantionare și reținere a valorii citite. Modulul convertește semnalul de intrare și genereaza apoi prin aproximari succesive un număr pe 10 biți.
Convertorul analog-digital folosește 4 registre : 2 de configurare(ADCON1 și ADCON0) și două registre din care se va citi valoarea obținută în urma conversiei (ADRESH si ADRESL).
Registrele de configurare vor fi prezentate în cele ce urmează :
Cei mai semnificativi 2 biți ai registrului configurează clock-ul pe care modulul îl va folosi.Urmatorii trei biți realizează selectia canalului de pe care se va face achizitia de date. Bitul Go/Done este un bit care realizează două funcții: pornirea conversiei care se face prin setarea bitului pe “1” logic și finalizarea conversiei care este semnalata prin punerea de catre procesor a bitului în starea “0” logic.
Cel mai semnificativ bit al registrului precizează alinierea rezultatului: la stânga(registrul ADRESL va contine în partea sa high cei mai putin semnificativi 2 biți ai conversiei), sau la dreapta(registrul ADRESH va contine în partea sa low cei mai semnificativi 2 biti ai conversiei). Bitul ADCS alături de cei mai semnificativi 2 biti ai registrului ADCON0 realizeaza selectarea clock-ului pe care modulul îl va folosi la conversie. Primii 4 biți ai registrului ADCON1(PCFG3 – PCFG0), realizează configurarea pinilor folosiți de convertorul analog-digital în funcție de necesitătile aplicatiei. Pinii pot fi configurați ca intrări analogice pentru modul sau ca pini generali de intrare/ieșire. Un caz aparte îl constituie pinii AN3 si AN2 care pe lângă configurările anterioare mai pot fi setați ca fiind intrări de tensiuni de referintă pozitivă respectiv negativă.
Modelul unei intrări analogice este dat în figura următoare:
Pentru ca modulul convertor A/D să-și atingă acuretațea specifică, condensatorul de reținere (Chold) trebuie să fie lăsat să se încarce complet până la nivelul de tensiune al canalului de intrare. Impedanta sursei (Rs) și impedanta switch-ului de eșantionare intern (Rss) afectează direct timpul necesar încărcării condensatorului Chold. Impedanta Rss variază cu nivelul de tensiune Vdd . Impedanta maximă recomandată pentru sursele analogice este de 10k. Pe masură ce impedanța este micsorată, și timpul de achiziție va fi redus. Dupa ce canalul de intrare analogic este selectat, achizitia trebuie facută înainte ca conversia să inceapă .
Pentru a calcula timpul minim de achiziție , poate fi folosită formula prezentată mai jos. Aceasta ecuatie presupune ca este folosita o eroare de 1/2 LSb (1024 pași pentru A/D). Eroarea 1/2 Lsb este eroarea maximă permisă pentru ca A/D să-și atingă rezolutia specifică.
Timpul de conversie pentru un bit este notat cu Tad. Convertorul analog-digital are nevoie de 12 perioade Tad pentru a face o conversie pe 10 biți. Utilizatorul poate selecta clockul de conversie soft. Pentru a genera un rezultat corect utilizatorul trebuie să asigure convertorului analog digital un timp minim Tad de 1,6 micro secunde. Tabelul următor prezintă cateva exemple de configurare corectă a registrelor astfel încât sa fie respectat acel timp de 1,6 micro secunde:
Figura urmatoare prezinta cum se realizează operația de conversie:
Dacă bitul Go/DONE este resetat în timpul unei conversii, aceasta se va opri însă rezultatul parțial nu va fi transferat în registrele ADRESH și ADRESL. Dupa terminarea unei conversii, utilizatorul mai trebuie să aștepte o perioadă de 2 Tad pentru a începe o nouă conversie
III.1.8. Registre cu funcții speciale
Procesorul PIC 18F452, la fel ca si celelalte procesoare din gama sa are nevoie de anumite setări inițiale pentru a putea rula programe. La acest procesor întâlnim 13 registre cu functii speciale, prezentate în tabelul ce urmează:
Legendă : x=necunoscut; u=nemodificat; -=neimplementat, citit ca ‘0’.
Bitul OSCEN din registrul CONFIG1H setează opțiunea procesorului de a folosi mai multe surse de clock. Această opțiune este utilă atunci când procesorul intră în starea “sleep”, unde sursa de clock externă poate fi schimbată cu cea internă pentru un consum redus de energie. Din același registru fac parte și biții FOSC2 – FOSC0 cu ajutorul cărora se poate selecta sursa de clock.
Cu ajutorul bitilor BORV1 și BORV0 din registrul CONFIG2L se stabilește limita de tensiune la care intră în funcție modulul de brown-out reset. Valorile tensiunilor variază între 2,5V și 4,5V. În același registru găsim și bitul BOREN care activează sau dezactivează modulul de brown-out reset dar și PWRTEN care permite procesorului să iasă din starea de sleep cu ajutorul timerului.
Registrul CONFIG2H oferă posibilitatea activarii sau dezactivarii modulului watch-dog timer precum și stabilirea postscalerului timerului care va fi folosit de acest modul.
Registrul CONFIG3H conține un singur bit util și anume CCP2MX. Prin setarea acestui bit pinul de ieșire al modulului CCP2 este RC1. Prin resetarea bitului, pinul de ieșire al modulului CCP2 va fi RB3.
In registrul CONFIG4L găsim bitul DEBUG care permite activarea procedurii de debug. Daca setăm acest bit, pinii RB6 și RB7 vor fi folosiți ca pini de uz general. Resetarea acestui bit va conduce la asignarea pinilor RB6 și RB7 exclusiv procedurii de debug. Bitul LVP activează sau dezactivează posibilitatea programării procesorului la tensiuni mici. Bitul STVREN permite stivei să genereze procedura de reset a procesorului în cazul în care este plină sau goală.
Intreg registrul CONFIG5L este dedicat protejării zonei de cod. Cei 4 biți permit protejarea celor 4 zone de cod din memoria flash. Registrul CONFIG5H permite protejarea zonei de date din epromul intern și a zonei de încărcare a programului.
Registrele CONFIG6H și CONFIG6L permit utilizatorului să protejeze împotriva scrierii, zonele de date și cod în memoriile interne ale procesorului.
Bitii din registrele CONFIG7H și CONFIG7L activează sau dezactivează posibilitatea citirii datelor de o instrucțiune din altă zona de memorie.
Registrele DEVID1 și DEVID2 permit identificarea procesorului. Cei mai semnificativi 3 biți ai primului registru precizează tipul procesorului. Pentru PIC 18F452 codul este 001. Conținutul registrului DEVID1, fără cei mai semnificativi 3 biți, reprezintă versiunea de revizie a procesorului. Conținutul registrului DEVID2 este un serial number cu ajutorul căruia procesorul poate fi recunoscut în sistem. Acest serial number poate fi foarte util în aplicatii unde se ține seama de securitate.
III.2. Procesorul PIC 16F648
III.2.1. Arhitectură
Procesorul 16F648A[12] face parte din gama procesoarelor care lucrează pe 8 biți, și este construit într-o tehnologie care minimizează consumul de energie, făcând acaest processor ideal pentru aplicatiile care necesită portabilitate. Procesorul permite viteze de operare de până la 20 Mhz, însă se pot folosi și oscilatoarele interne de 48KHz și 4 Mhz ideale în aplicațiile mici în care spațiul este o problemă sau unde viteza procesorului poate varia ușor. Procesorul permite utilizarea întreruperilor externe, una de sine stătătoare în sensul ca are propriul vector de întrerupere, și 4 de tipul interrupt on change care împart același vector de întreruperi. Funcția de interrupt on change se activează de fiecare dată când pe unul din cei 4 pini se semnalează o schimbare a nivelului logic. 16F648A dispune și de un EEPROM intern de 256 de octeti ce are o durată de viata de până la 1 milion de scrieri și elimină prezența unui eprom extern în aplicațiile care necesită salvări minimale de date.
Arhitectura de principiu a procesorului 16F648 este dată în figura ce urmează:
Ca arhitectură, procesorul 16F648 foloseste arhitectura Harvard în care programul și datele sunt accesate de pe magistrale separate din memorii separate. Această arhitectură face ca procesorul să ruleze mai rapid decât pe o arhitectura Von Newman unde programul și data sunt aduse din aceiași memorie. Opcode-urile au dimensiunea de 14 biți iar pipeline-ul în două stadii suprapune aducerea din memorie și execuția instrucțiunilor.
16F648 dispune de o unitate ALU pe 8 biți capabil să facă adunări, scăderi, shiftări și operații logice. Pe lângă unitatea ALU există și W register(working register) care are o lungime de 8 biți, nu este adresabil și este folosit de ALU în operațiile pe care le face. În arhitectura 16F648 intră și două tipuri de memorie: cea nevolatilă care este EPROMUL și care menține datele chiar dacă procesorul a fost scos de sub tensiune, și memoria RAM care poate fi folosită pentru stocarea datelor dar care la scoaterea de sub tensiune este ștearsă.
În cele ce urmează se va face o prezentare a câtorva periferice ce intră în alcatuirea procesorului 16F648A.
III.2.2. Porturi de intrare/iesire
Pinii de intrare/ieșire pot fi considerați ca fiind periferice deoarece prin intermediul lor, procesorul comunică și controlează celelalte componente. Procesorul PIC 16F648 dispunde de 2 porturi, PORTA și PORTB, de uz general care pot fi configurate în funcție de necesitățile aplicației ca intrări sau ca ieșiri prin intermediul registrelor TRISx. Pinii acestor porturi pot fi multiplexați cu funcții alternative ce sunt date de celelalte periferice ale procesorului. De exemplu pinul RA2 poate să fie un pin de uz general sau o intrare în unul din cele două comparatoare ale procesorului sau ca ieșire, tensiune de referintă.
În funcție de operațiile pe care le îndeplinesc pinii pe lângă cele de uz general, schemele interne diferă de la caz la caz. În cele ce urmeaza se va prezenta o schemă de principiu pentru pinul RB0 care în afara faptului ca este un pin de uz general poate să genereze și întrerupere externă, sesizată de procesor prin intermediul flag-ului INTF:
Pinii din porturile de uz general sunt controlate prin intermediul a două registre TRISx și PORTx. Registrul TRISx este folosit pentru setarea unui bit din portul x ca intrare sau ca ieșire. Un bit este considerat intrare dacă pe poziția sa în registrul TRIS se afla 1. În cazul în care dorim setarea pinului ca ieșire în registrul TRIS pe poziția respectivă vom pune 0.
PORTx reprezintă latchul pentru portul respectiv. O citire din acest registru va prelua datele aflate pe pinii procesorului iar o scriere va schimba nivelele logice ale pinilor astfel încât pe aceștia să se gasească valorile înscrise în registru.
III.2.3. Modulele Timer
III.2.3.1. Timer 0
Modulul Timer 0 poate fi folosit atât ca un timer cât și ca un conter, lucrează pe 8 biți, are un prescaler programabil pe 8 biți și poate genera întreruperi.
Prescalerul Timer 0 este împărțit intre acesta și modulul Watchdog prin bitul PSA aflat în registrul OPTION_REG. De asemena sursa clockului poate fi selectată între frecvența oscilatorului /4 sau, dacă se dorește funcționarea Timer 0 ca un counter, impulsurile venite de la pinul RA4 al procesorului. Selectarea modulului counter se face prin setarea bitului T0CS. Bitul TOSE din registrul OPTION_REG va spune procesorului la ce tip de schimbare de nivel se va produce incrementarea Timer 0: tranziție low-high sau high-low.
Schema bloc este urmatoarea:
Prin setarea bitului TOIE(timer 0 interrupt enable) din registrul INTCON, modulul timer 0 poate genera întreruperi soft, întreruperi ce sunt semnalate de bitul TOIF când apare overflow. De mentionat este faptul că modulul Timer 0 nu poate scoate procesorul din starea Sleep deoarece este închis.
Registrele folosite de modulul Timer 0 sunt: TMR0 – registrul în care se incarcă valoarea inițială a timerului, OPTION_REG în care se află setarile acestui modul cum ar fi prescalerul și sursa clockului. Pe lângă aceste registre în funcție de necesități dacă avem nevoie de întreruperi vom folosi și registrul INTCON. Dacă dorim folosirea modulului Timer 0 ca un counter vom folosi și registrul TRISA pentru a selecta direcția pinului RA4 care poate fi folosit ca sursă de clock.
III.2.3.2. Timer 1
Modulul Timer1 este un counter/timer ce operează pe 16 biți în sensul crescător al incrementării, poate opera pe baza unui clock extern și poate genera întrerupere la depasirea de 0xFFFF la 0x0000. Schema de principiu este urmatoarea:
Prin bitul TMR1CS din registrul T1CON se selectează sursa clockului: frecvența oscilatorului/4, frecventa tranziției low-high a pinului RB7 când T1OSCEN este setat pe 1 sau frecvența tranziției high-low a pinului RB6 cand T1OSCEN este setat pe 0 . Cu ajutorul biților T1CKPS<1:0> aflați în registrul T1CON se poate selecta unul din prescalarele disponibile acestui timer. Bitul T1OSCEN are rolul de a opri sau porni oscilatorul intern cu scopul scaderii consumului de energie. Bitul TMR1ON din același registru controlează funcționarea acestui modul astfel încât el să poată fi utilizat doar atunci când este nevoie. Modulul Timer1 poate opera ca un counter în două moduri: sincron și asincron în functie de cum este setat bitul T1SYNC. Dacă modul counter sincron tranzitiile clockului extern vor fi sincronizate cu tranzitiile clockului intern al procesorului. Pentru realizarea sincronizării, se preiau sample-uri în stadiile Q2 și Q4 ale clockului intern. Din acest motiv pinii care asigură clockul extern al modulului trebuie să mențină un nivel logic pentru cel puțin 2 timpi ai clockului intern.
Timer1 poate genera întreruperi dacă bitul TMR1IE din registrul PIE1 este setat. Sezizarea întreruperii este realizată cu ajutorul bitului TMR1IF din registrul PIR1 care se va seta pe 1 când Timer1 va genera overflow de la 0xFFFF la 0x0000.
Registrele folosite de acest modul sunt: T1CON- folosit pentru configurarea acestui modul, TMR1H și TMR1L – registre în care se va incărca valoarea inițială de lungime 16 biti, și PIE1 si PIR1 care conțin bitii TMR1IE respectiv TMR1IF necesari în generarea de întreruperi.
III.2.3.3. Timer 2
Modulul Timer 2 este un timer ce operează pe 8 biți, cu o singură sursă de clock și anume: frecvența oscilatorului/4, conține un prescaler și un postscalar ce îi permite să ajungă la timpi de incrementare foarte mari și poate fi folosit de către modulul CCP/PWM. Arhitectura de principiu este prezentată în cele ce urmează:
Prescalerul și postscalerul, selectabili prin biții T2CKPS<1:0> respectiv TOUTPS<3:0> din registrul T2CON, sunt resetați la fiecare reset al procesorului sau când apare o scriere în unul din registrele T2CON sau TMR2.
Modulul Timer 2 conține un registru PR2 ce poate fi scris și citit, care la inițializare are valoarea 0XFF. Timer 2 se va incrementa de la valoarea scrisă în registrul TMR2 până în momentul când va apare o egalitate cu registrul PR2.
Modulul Timer 2 poate fi oprit sau pornit cu ajutorul bitului TMR2ON aflat în registrul T2CON fapt ce permite utilizarea sa doar atunci când este nevoie. Depășirea de la valoarea aflată în registrul PR2 la 0x00 se face prin setarea bitului TMR2IF aflat în registrul PIR1. Dacă bitului TMR2IE aflat în registrul PIE1 este setat, la overflow se va genera întrerupere.
Registrele folosite de către modulul Timer 2 sunt prezentate în tabelul de mai jos:
Legenda : x=necunoscut; u=nemodificat; -=neimplementat, citit ca ‘0’. Celulele hasurate nu sunt folosite de modulul Timer2.
III.2.4. Modulul de captură/comparare/PWM (CCP)
Deoarece PIC 16F648 este un procesor cu un număr relativ mic de pini, producătorii au introdus în arhitectura sa o singură unitate pentru generarea de PWM(pulse width modulation).
Fiecare modul CCP (Captură/Comparare/PWM) conține un registru de 16 biți, care poate funcționa ca registru de captură pe 16 biți, ca registru de comparare pe 16 biți sau ca registru PWM master/slave pentru ciclul util. Urmatorul tabel prezintă sursele de timer ale modurilor modulului CCP.
Modulul CCP are nevoie de registrul CCP1CON pentru a face setările minime inițiale:
Biții CCP1X și CCP1Y reprezintă cei mai putini semnificativi biți din registru de configurare a unității PWM și sunt nefolosiți de către celelalte module.
Cei mai putin semnificativi biți ai acestui registru determină modul de funcționare al modulului CCP:
0000 = Modulul CCP este oprit
0100 = Modulul CCP funcționează în regim de captură la fiecare front descrescător
0101 = Modulul CCP funcționează în regim de captură la fiecare front crescător
0110 = Modulul CCP funcționează în regim de captură la fiecare al 4-lea front crescător
0111 = Modulul CCP funcționează în regim de captură la fiecare al 16-lea front crescător
1000 = Modulul CCP funcționează în regim de comparator- bitul CCP1IF este setat pe 1 la egalitate intre intrari
1001 = Modulul CCP funcționează în regim de comparator- bitul CCP1IF este setat pe 0 la egalitate intre intrari
1010 = Modulul CCP funcționează în regim de comparator- bitul CCP1IF este setat pe 1 la egalitate între intrări, se generează întrerupere iar pinul CCP1 este neafectat
1011 = Modulul CCP funcționează în regim de comparator- bitul CCP1IF este setat pe 1 la egalitate între intrări și pinul CCP1 resetează Timer1
III.2.4.1. Modul Captură
In acest mod modulul CCP citește Timer 1 de fiecare dată când apare un eveniment la pinul RB3 al procesorului. Prin eveniment se înțelege unul din urmatoarele:
fiecare front descrescător
fiecare front crescător
fiecare al 4-lea front crescător
fiecare al 16-lea front crescător
Dacă apare un evenimet iar valoarea din registrele TMR1L și TMR1H nu este citită, primul eveniment se pierde.
Arhitectura de principiu pentru acest modul este urmatoarea:
Nota: La reset pinul RB3 este configurat ca iesire și orice scriere în el poate genera o captură.
Timer 1 trebuie să funcționeze în regimul de timer sau de counter sincronizat pentru ca modulul CCP să opereze ca o unitate de captură.
Prescalerul este resetat automat cand se trece de la un mod de captură la altul, modulul CCP este oprit sau operează în alt mod. De asemena, când se schimbă modul de captură o întrerupere falsă poate aparea de aceea bitul CCP1IE din registrul PIE1 ar trebui ținut pe 0 în timpul unei astfel de operații iar bitul CCP1IF setat pe 0 după această operatie.
III.2.4.2. Modul Comparare
În modul Comparare, valoarea registrului de 16 biți CCPR1L este comparată continuu cu valoarea perechii de registre TMR1. Când se produce o potrivire, pinul RB3/CCP1 este :
pus pe ‘1’
pus pe ‘0’
rămane neschimbat
Acțiunea asupra pinului este bazată pe valoarea biților de control CCP1M3:CCP1M0 (CCP1CON<3:0>). În acelasi timp este setat bitul de flag CCP1IF.
Timer 1 trebuie să ruleze în modulul timer sau counter sincron pentru ca modulul CCP să poată opera în regim de comparare. Când este selectată opțiunea de generare întrerupere pinul CCP1 nu este afectat în schimb o conexiune internă hard afectează Timer 1 in sensul resetării acestuia.
Registrele asociate modulelor de captură și comparare sunt prezentate în tabelul urmator:
Legenda : x=necunoscut; u=nemodificat; -=neimplementat, citit ca ‘0’. Celulele hasurate nu sunt folosite de Captura si de Timer1.
III.2.4.3. Modul PWM
In modul PWM – Modulație prin lățimea pulsului (Pulse Width Modulation), pinul CCP1 produce o ieșire PWM cu o rezoluție de până la 10 biți. De vreme ce pinul CCP1 este multiplexat cu latch-ul de date al portului PORTB, bitul TRISB<3> trebuie resetat pentru a configura pinul ca ieșire.
Resetarea registrului CCP1CON va forta latch-ul de iesire PWM al pinului CCP1 pe nivelul predefinit de ‘0’. Acesta nu este latch-ul I/O de date al portului PORTC.
Urmatoarea figură prezintă o diagramă bloc simplificată a modulului CCP în modul PWM:
O ieșire PWM are o baza de timp (perioada) și un timp în care ieșirea sta în ‘1’ (ciclul util). Frecvența pentru PWM este inversul perioadei (1/perioada).
Perioada PWM este specificata prin scrierea în registrul PR2. Ea poate fi calculată cu formula urmatoare :
Perioada PWM = [(PR2)+1]*4*TOSC*(valoarea prescaler-ului pentru TMR2)
Frecventa PWM este definita ca 1/[perioada PWM].
Cand TMR2 este egal cu PR2, se produc următoarele trei evenimente în urmatorul ciclu de incrementare :
TMR2 este resetat
Pinul CCP1 este setat (excepție : dacă ciclul util PWM =0%, pinul CCP1 nu va fi setat)
Ciclul util PWM este memorat din CCPR1L in CCPR1H.
Postscaler-ul pentru Timer2 nu este folosit la determinarea frecventei PWM. Acesta poate fi folosit pentru a avea o rata automata de modificare la o frecvență diferită de cea a ieșirii PWM.
Ciclul util PWM este specificat prin scrierea în registrul CCPR1L și a biților CCP1CON<5:4>. Este disponibilă o rezoluție de pana la 10 biti : CCPR1L contine cei mai semnificativi 8 biți si CCP1CON<5:4> conține cei mai puțin semnificativi 2 biți. Aceasta valoare pe 10 biti este reprezentata de CCPR1L:CCP1CON<5:4>. Ecuatia urmatoare este folosita pentru a calcula ciclul util PWM in timp :
Ciclul util PWM = (CCPR1L:CCP1CON<5:4>)*TOSC*(valoarea prescaler-ului pentru TMR2)
CCPR1L si CCP1CON<5:4> pot fi scrise oricând, dar valoarea ciclului util nu este memorarată în CCPR1H decât după a potrivire între PR2 și TMR2 (de exemplu : când perioada este completă). În modul PWM registrul CCPR1H poate fi doar citit.
Registrul CCPR1H și un latch intern pe 2 biți sunt folosiți pentru a buffera dublu ciclul util PWM. Aceasta buffer-are dubla este esentiala pentru o functionare PWM fara paraziți.
Cand CCPR1H și latch-ul pe 2 biți se potrivesc cu TMR2 concatenat cu un clock Q pe 2 biți sau cu 2 biți ai prescaler-ului pentru TMR2, pinul CCP1 este resetat.
Rezolutia maxima PWM (numarul de biti) pentru o frecventa PWM data este :
log(FOSC / FPWM) / log(2) biti.
Daca valoarea ciclului util PWM este mai mare decât perioada PWM, pinul CCP1 nu va fi resetat.
Pasii următori trebuie urmați la configurarea modulului CCP pentru funcționarea în modul PWM:
Setare perioadă PWM prin scrierea în registrul PR2.
Setare ciclul util PWM prin scrierea în registrul CCPR1L și a biților CCP1CON<5:4>.
Configurare pinul CCP1 ca ieșire prin resetarea bitului TRISB<3>.
Setare valoare prescaler pentru TMR2 și validare Timer2 prin scrierea în T2CON.
Configurare modulul CCP1 pentru funcționare în modul PWM.
Cateva exemple configurare a registrelor modulului PWM pentru a obtine diferite frecvente la o viteza de 20Mhz, sunt prezentate in tabelul ce urmeaza:
Registrele asociate modulului CCP1 functionând în modul PWM sunt urmatoarele:
Legenda : x=necunoscut; u=nemodificat; -=neimplementat, citit ca ‘0’. Celulele hasurate nu sunt folosite de PWM si de Timer2.
III.2.5. Modulul Comparator
Modulul comparator conține două comparatoare anlogice a căror intrări sunt multiplexate pe pinii RA1 ->RA3. Modulul de referință de tensiune prezent în chipul de la Microchip poate fi de asemnea intrare pentru comparatoare. Modulul comparator este controlat de registrul CMCON care are urmatoarea configurație:
Biții C2INV și C1INVsetează modul în care comparatorul va genera ieșirea astfel:
– dacă C2INV=0 si C2 VIN+ > C2 VIN- atunci C2OUT=1
– dacă C2INV=0 si C2 VIN+ < C2 VIN- atunci C2OUT=0
– dacă C2INV=1 si C2 VIN+ < C2 VIN- atunci C2OUT=1
– dacă C2INV=1 si C2 VIN+ > C2 VIN- atunci C2OUT=0
Bitul CIS setează la ce pini vor fi conectate intrărire VIN- ale celor două comparatoare
Cei mai putin semnificativi biți ai registrului CMCON selectează modul de operare al comparatoarelor, moduri ce sunt prezentate în figura următoare:
Cand intrarea Vin+ este mai mică decât intrarea Vin-, ieșirea comparatorului are nivelul logic ‘0’. În momentul în care tensiunea de pe intrarea Vin+ depășește intrarea Vin- comparatorul își schimbă starea în ‘1’ logic. O schemă a operării comparatorului este prezentată în figura următoare:
Zonele închise la culoare reprezintă perioada de incertitudine a comparatorului.
Pe intrările comparatorului pot fi utilizate tensiuni de referintă ce pot fi interne sau externe. Referința de tensiune internă este disponibilă prin intermediul modulului referintă de tensiune ce va fi discutat în urmatoarea sectiune. Cele două comparatoare pot utiliza aceiași referintă de tensiune externă sau referințe de tensiune diferite în funcție de aplicație.
Ieșirea comparatoarelor poate fi citită direct din registrul CMCON. De asemenea ieșirile comparatoarelor pot fi multiplexate cu pinii RA3 și RA4.
O arhitectură de principiu a pinilor care asigură intrările analogice a comparatoareleor este dată în figura următoare:
Întreruperile generate de comparatoare sunt sesizate prin intermediul bitului CMIF din registrul PIR1. Însă pentru a funcționa acestea trebuie sa fie activate prin setarea bitului CMIE din registrul PIE1. Întreruperile vor fi generate de fiecare dată când la ieșirea comparatoarelor are loc o schimbare a nivelelor logice. Pentru a elibera întreruperea utilizatorul trebuie să reseteze bitul CMIF sau să scrie/citească registrul CMCON. De observat este faptul că modulele comparatoarele funcționează când porcesorul este în starea sleep. Când comparatoarele generează o întrerupere procesorul își va relua activitatea normala. De menționat că în starea sleep cele două comparatoare vor consuma curent însă cu ajutorul opțiunii de oprire a unuia din comparatoare, nivelul curentului poate sa scadă.
Registrele asociate modulului comparator sunt prezentate în tabelul ce urmează:
Legenda : x=necunoscut; u=nemodificat; -=neimplementat, citit ca ‘0’. Celulele hasurate nu sunt folosite de Comparator
III.2.6. Modulul referința de tensiune
Modulul referință de tensiune este folosit de obicei în conjuncție cu modulul comparator. Intrările modulului comparator nu necesită curent mare de intrare, de aceea capabilitatea de comanda a referinței de tensiune este limitată.
Referința de tensiune este o rețea de 16 trepte formate din rezistoare care furnizează o tensiune de referință selectabilă. Scala de rezistențe este segmentată pentru a furniza două game de valori VREF și are o functie de oprire (power-down) pentru a conserva energia când referinta nu este folosită.
Registrul VRCON controlează funcționarea referinței, după cum este prezentat în figura următoare. În fiecare gamă, cei 16 pași sunt monoton crescători (fiecare creștere a codului va genera o ieșire crescută).
Registrul VRCON :
bitul 7 VREN: VREF activ
1=circuitul VREF pornit
0= circuitul VREF oprit
bitul 6 VROE: activare iesire VREF
1= VREF este conectat intern la VREF a modulului Comparator. Acest nivel de tensiune este si iesire la pinul VREF
0= VREF nu este conectat la modulul Comparator. Tensiunea este deconectata de a pinul VREF
bitul 5 VRR : selectia gamei VREF
1= de la 0V pana la 0.75*VDD, cu pas de VDD/24
0= de la 0.25*VDD pana la 0.75*VDD, cu un pas de VDD/32
bitul 4 Neimplementat : citit ca ‘0’
bitii 3:0 VR3:VR0 – selectia valorii VREF in gama 0<=VR3:VR0<=15
Cand VRR=1:
VREF = (VR<3:0>/24)*VDD
Cand VRR=0:
VREF = 1/4*VDD + (VR3:VR0 /32)VDD
Referința de tensiune poate furniza la ieșire 16 nivele distincte de tensiune pentru fiecare gamă.
Ecuatiile folosite pentru a calcula ieșirea referinței de tensiune sunt:
Dacă VRR=1 : VREF = (VR3:VR0/24)*VDD
Dacă VRR=0 : VREF = (1/4 * VDD) + (VR3:VR0/32)*VDD
Timpul de setare pentru referința de tensiune trebuie considerat la schimbarea ieșirii VREF.
III.2.7. Modulul USART
USART-ul(UNIVERSAL SYNCHRONOUS ASYNCHRONOUS RECEIVER
TRANSMITTER) mai este cunoscut și ca Interfata Serialã de Comunicație sau SCI. USART-ul poate fi configurat ca un sistem full duplex asincron care poate comunica cu dispozitive periferice cum ar fi terminale pc, sau ca un sistem half duplex sincron care poate comunica cu dispozitive periferice cum ar fi circuitele integrate A/D sau D/A , EEPROM-uri seriale, etc.
USART-ul poate fi configurat în urmãtoarele moduri:
– Asincron (full duplex)
– Sincron – Master (half duplex)
– Sincron – Slave (half duplex)
Bitul SPEN (RCSTA<7>) si bitii TRISB<2:1> trebuie setati pentru a putea configura pinii RB2/TX/CK and RB1/RX/DT pentru USART.
Modulul USART are și capacitatea de comunicare multi-procesor folosind detecția unei adrese pe 9 biti.
Pentru controlarea modului se folosesc 2 registre: TXSTA și RCSTA cu ajutorul carora se stabileste tipul comunicației și pornirea sau oprirea modulului. Configurația biților este prezentată în figurile următoare:
Registrul TXSTA:
Bit 7: pentru modul de operare asincron nu conteaza; pentru modul de operare sincron:1 procesorul este master si genereaza intern clock-ul comunicatiei; 0- procesorul este slave
Bit 6: 1 – transmisie pe 9 biti
0 – transmisie pe 8 biti
Bit 5: activează sau dezactivează modulul de transmisie
Bit 4: operare sincrona sau asincrona
Bit 2: utilizat in modul asincron si de termina daca transmisia este de viteza mare sau nu
Bit 1: status pentru registrul de transmisie
Bit 0: bitul 9 din secventa de transmisie – poate sa fie bit de paritate
Registrul RCSTA:
Bit 7: pornește sau oprește modulul serial
Bit 6: selecteaza transmisia pe 9 sau pe 8 biti
Bit 5: In modul sincron este folosit pentru a porni si a opri o singura receptie
Bit 4: Pornește sau oprește primirea continuă a datelor
Bit 3: În modul asincron pe 9 biti, porneste si opreste detectarea adreselor, pornirea si oprirea intreruperilor
Bit 2: pornește sau oprește detecția errorii de cadru
Bit 1: pornește sau oprește detecția errorii overrun
Bit 0: al 9-lea bit din secvență primită
Generatorul de baud rate al USART(BRG)
BRG-ul suportă atit modul sincron cât și cel asincron al USART-ului. Este un generator dedicat de baud rate, pe 8 biți. Registrul SPBRG controlează perioada unui timer pe 8 biți, care funcționeaza independent. În modul asincron bitul BRGH (TXSTA<2>) controleză și baud rate-ul. În modul sincron bitul BRGH este ignorat. Tabelul urmator arată formula de calcul a baud rate-ului pentru diferite moduri ale USART-ului care se aplică doar în modul master (clock intern).
Dându-se rata baud dorită și Fosc, cea mai apropiată valoare întreagă pentru registrul SPBRG poate fi calculată folosind formula din tabelul anterior, unde X este valoarea din registrul SPBRG (0 – 255). De aici, eroarea în rata baud poate fi determinata.
Poate fi avantajos să folosim rata baud inalta (BRGH=1) chiar pentru clock de baud mai lent. Aceasta deoarece ecuația Fosc/(16(X+1)) poate reduce eroarea baud rate în unele cazuri.
Scriind o nouă valoare în registru SPBRG, se va reseta timerul BRG. Acest lucru asigură că BRG nu asteaptă o depășire de timer înainte de a produce noul baud rate. În tabelul următor se pot regăsi registrele asociate generatorului de baud rate
Legenda : x=necunoscut; -=neimplementat, citit ca ‘0’. Celulele hasurate nu sunt folosite de BRG.
Data de pe pinul RB1/RX/DT este esantionată de trei ori de către un circuit de detecție a majorității pentru a determina daca pe pinul RX este prezent un nivel de ‘1’ sau de ‘0’.Figura următoare arată formele de undă pentru circuitul de eșantionare. Eșantionarea funcționează la fel indiferent de starea bitului BRGH , doar sursa clock-ului este diferită.
III.2.8. Registre cu funcții speciale
Toate procesoarele din gama Microchip folosesc aceste registre de configurare deoarece ele asigură un suport inițial pentru orice aplicație. Procesorul 16F648 are un singur registru de configurare cu urmatoarea structură:
Bit 13: CP (code protection): asigură protejarea zonei de memorie ce conține cod
Bit 8: CPD( data code protection): asigura protejarea zonei de memorie ce conține date
Bit 7: LVP(low voltage programming): există opțiunea programării procesorului la tensiune mică deoarece în mod normal pe pinul MCLR este nevoie de o tensiune de 12 V pentru a scrie programul.
Bit 6: BOREN(brown-out reset bit) folosit pentru a activa/dezactiva modulul de brown-out reset care în cazul scăderii tensiunii de alimentare sub un anumit prag pune procesorul în starea de reset
Bit 5: MCLRE(master clear enable) folosit pentru selectarea funcționării pinului RA5.
Daca acest bit este 1, pinul RA5 va avea funcția exclusivă de MCLR
Daca bitul este pus pe 0, pinul RA5 are funcționalitatea unui pin de intrare digitală în timp ce MCLR este legat intern la 5V
Bit 3: PWRTE(Power up timer enable) activează sau dezactivează opțiunea de pornire a procesorului cu un timer
Bit 2: WDTE(Watch dog timer enable) activează sau dezactivează modulul de watch dog care supervizează operarea procesorului
Bitii 4, 1-0: FOSC(oscillator selection): Prin setarea acestor biți se selectează tipul oscilatorului ce va fi folosit de procesor: Opțiunile permit folosirea oscilatorului intern cu sau fără ieșire pe unul din pinii procesorului, a oscilatoarelor care nu necesită curent prea mare(LP), a oscilatoarelor care merg la frecvențe mici până la 4 MHz(XT), a oscilatoarelor care merg la viteze mari(HS) sau a oscilatoarelor RC.
III.3. Transcieverul FTDI
Chipul de la FTDI se prezinta ca un instrumnt foarte folositor in multe aplicatii unde este nevoie de comunicatii cu pc-ul. Prin memoria externa care se poate atasa acestui chip, se pot crea drivere de USB dedicate pentru o anumita aplicatie, astfel incat la conectarea dispozitivului la un pc, acesta sa fie recunoscut de Windows. FT232BM are urmatoarea arhitectura:
Chipul de FTDI suportă ambele versiuni de USB 1.1 și 2.0 iar pentru serial viteze de până la 1M baud. În arhitectura chipului se poate observa un regulator intern de 3,3 volti ceea ce permite integrarea chipului în aplicații unde există restricții pe partea de alimentare.
FT232BM dispune și de un multiplicator de clock intern fapt ce permite viteze mari de lucru și implicit de transfer. Chipul dispune de 128 octeti buffer TX și 384 octeti buffer RX, ceea ce asigură continuitatea datelor și echilibrarea vitezei procesorului cu cea a calculatorului. Transcieverul USB prezent în arhitctura FT232BM asigură interfațarea fizică a chipului cu cablul USB iar transceverul serial (SIE) asigură conversia datelor de pe magistrala USB în date pentru protocolul serial și invers. SIE asigură de asemenea și codarea și decodarea datelor folosind bit stuffing, CRC15 sau CRC16.
În absența unui eprom extern FT232BM se comportă efectiv ca un emulator de protocol serial, windows-ul putând să primească și să trimită date ca și cum ar faceo pe un port serial normal. Cu ajutorul epromului, FT232BM se poate coporta ca un emulator de serial în cazul în care epromul nu este scris sau este defect sau ca un port USB în cazul în care în eprom a fost scris un serial number, un VID, un PID și un string de descriere.
Cap IV. Concluzii
În prezenta lucrare se incearcă rezolvarea unei probleme cu care se confruntă sistemul sanitar romanesc: pacientii nu au parte mereu de asistență necesară pentru a se reface.
Dispozitivul prezentat incearcă rezolvarea acestor probleme. Pe parcursul prezentării s-a discutat despre alegerea unor anumite componente sau realizarea design-ului într-un anumit mod pentru a reduce costurile de producție. Însă pentru a reduce costul de productie, nu s-a recurs la o implementare mai slabă din punct de vedere calitativ. De exemplu, costul dispozitivului central din camera de gardă a asistentelor este de aproximativ 40 euro.
De asemnea s-a dorit ca dispozitivul să fie cât mai compact în sensul obținerii unui produs care să se incadreze în decor și să nu creeze dificultăți în manipulare. Pentru eliminarea cablurilor s-a recurs la transmisii de tip wireless. Inițial produsul a fost destinat doar pentru folosirea comunicațiilor de tip wireless însă pentru obținerea unor costuri mai reduse s-a introdus și opțiunea folosirii telecomenzilor cu fir. Pentru folosirea acestora nu sunt necesare decât două fire: 5V și masă, tensiuni care nu pun în pericol viața pacienților.
În versiunile urmatoare cele două dispozitive, cel de salon și cel pentru camera de gardă a asistentelor, vor fi dotate cu module pentru reincarcarea bateriilor. Pentru această optiune se va implementa un sistem cu mai multe surse de tensiune controlate de procesor astfel încât la funcționarea pe baza de baterii anumite module sa poata fi închise automat cum ar fi buzzer-ul sau LCD-ul.
O propunere de imbunătățire a produsului vizează introducerea de senzori pentru monitorizarea respirației sau a temperaturii corpului și care la detectarea unui pericol să genereze cod de alarmă către dispozitivul central.
Cap V. Bibliografie
www.en.wikipedia.org/wiki/RFID
www.rfids.ro
www.rfidjournal.com
RFID Essentials – Bill Glover, Himanshu Bhatt
O'Reilly, 2006
http://csrc.nist.gov/publications/nistpubs/800-98/SP800-98_RFID-2007.pdf
Passive RFID Basics(AN680) – www.microchip.com
SC2262 datasheet
http://www.discovercircuits.com/K/keypad.htm
http://www.next.gr/other-circuits/keypad-circuits/
http://esd.cs.ucr.edu/labs/decode_key/decode_key.html
PIC16F648 datasheet – www.microchip.com
PIC18F452 datasheet – www.microchip.com
FT232BM datasheet– www.ftdichip.com
How to use intelligent L.C.D.s – Julian Ilett
AC – 162B datasheet – Technologies
RTX-MID-3V – Aurel Wireless
Dispozitive și circuite electronice –Mihail Florea
Editura “Gh Asachi” , 1999
http://www.discovercircuits.com/B/beepers.htm
http://www.next.gr/audio/beeper-buzzer/
24LC64 datasheet– www.microchip.com
Anexa 1. Coduri sursă folosite de dispozitivul central
Rutina de tratare a intreruperilor de modul serial, unitate captura si ceas de timp real:
void interrupt isr()
{
//daca exista intrerupere de comparator si intreruperea este activata se citesc date
//intreruperea de comparator receptioneaza datele de la receiver
if(CCP1IF&&CCP1IE)
{
CCP1IE=0;
CCP1IF = 0;
capture_interval=CCPR1H;
capture_interval<<=8;
capture_interval+=CCPR1L;
if (CCP1CON == 5) //daca am front crescator
{
if (capture_interval<0xA0) {valid_data=0;flag_gata=0;}
else if (capture_interval<0x255) {valid_data<<=1;flag_gata++;}
else
if(capture_interval<0x500) {valid_data<<=1;valid_data+=1;flag_gata++;}
else {valid_data=0;flag_gata=0; }
}
T3CON=0xC8; //se incarcă in timer o valoare care generează esșantionarea
TMR3 = 0; //clear counter
TMR3ON = 1;
if (CCP1CON == 4)
CCP1CON = 5;
else CCP1CON = 4;
CCP1IF = 0;
CCP1IE=1;
}
//intreruperea de timer 1 care genereaza real time clock
if (TMR1IF&&TMR1IE)
{
TMR1IF=0;
TMR1H=0x0C;
TMR1L=0x00;
sec++;
//se verifică starea alarmarii si daca există eveniment se pornește alarma
if (flag_alrm==1)
{
RB4=0;
CCP2CON=0x0C;
T2CON=0x00;
TMR2ON=1;
PR2=0x1F;
CCPR2L=number1;
flag_alrm=0;
}
else
{
TMR2ON=0; //timer2 ON
CCP2CON=0x00;
RB3=0;
RB4=1;
}
//baleere cereri netratate pentru ca două asistente să nu meargă la acelasi salon
if(((sec-(sec/10)*10)==0)&&(sec/2==60) )
{
sec=0;
//afisare pe display evenimente
for (k3k=ultima_poz_afisata;k3k<50;k3k++)
if (mem_process[k3k]!=0)
{
flag_alrm=1;
afis_cerere(k3k+1,mem_process[k3k]);
ultima_poz_afisata=k3k+1;
if (ultima_poz_afisata==50) ultima_poz_afisata=0;
break;
}
if (k3k==50) ultima_poz_afisata=0;
//sf afisare pe display evenimente
//actiunea de update al datei curente
min++;
if(min==60)
{
min=0;
hour++;
if(hour==24)
{
hour=0;
day++;
if(day==(days_per_month[current_month]+1))
{
day=1;
current_month++;
if(current_month==13)
{
current_month=1;
if(year_part2==99)
{
year_part2=0;
year_part1++;
}
else year_part2++;
}
}
}
}
//scrierea in memoria interna a datei curente
eeprom_write(0x00,hour);
eeprom_write(0x01,min);
eeprom_write(0x02,day);
eeprom_write(0x03,current_month);
eeprom_write(0x04,year_part1);
eeprom_write(0x05,year_part2);
}
// afisarea datei curente
afis_data();
//citirea tastaturii pt se vedea daca există cerere de intrare în meniu sau de update volum alarmare
read_tast();
if(vect_key[1]!=0)
{
if(number!=26) number++;
else number=26;
}
if(vect_key[7]!=0)
{
if(number!=0) number–;
else number=0;
}
// daca există cerere de update volum alarmare se afișează pe LCD nivelul volumului și se incrementează sau se descrementează
if((vect_key[7]!=0) ||(vect_key[1]!=0) )
{
TMR1ON=0;
ClearLCD();
DelayMs(2);
ComandOut(0x80);
for(t=0;t<13;t++)
CharOut(txt[t]);
tem=number;
number1=0x1F;
number1-=number;
volum=number1;
ComandOut(0xC0);
CharOut(convert_to_display1(tem)>>8);
CharOut(convert_to_display1(tem));
PWM2_alarmare(number1,90);
eeprom_write(0x30,number1);
sec++;
if (sec==120) sec==119;
DelayMs(250);
DelayMs(250);
ClearLCD();
DelayMs(2);
afis_data();
}
//daca s-a apasat butonul OK se asteaptă 5 secunde pentru a intra in meniu
if (vect_key[11]!=0)
{
while(contor_apasare<0xFF)
{
read_tast();
contor_apasare++;
if (vect_key[11]==0) break;
}
//daca s-a tinut 5 sec butonul OK apasat se intră in meniu
if(contor_apasare==0xFF)
{
PWM2_taste(0x00);RCIE=0;menu(); RCIE=1;CREN=0;CREN=1;
}
contor_apasare=0x00;
}
TMR1ON=1;
}
//tratare intrerupere de receptie seriala daca intreruperea este activata
if (RCIF&&RCIE)
{
RCIF=0;
// pornire transmisie seriala a evenimentelor
if (RCREG=='E')
{
stop_to_send=0;
send_datas();
}
if (RCREG=='H') stop_to_send=1;// oprirea transmisiei evenimentelor
}
}
Rutina citire tastatura
void read_tast(void)
{
unsigned char i=0;
unsigned char ok=0;
pDirlin4 =1;
pDirlin3 =1;
pDirlin2 =1;
pDirlin1 =1;
plin1=0;plin2=0;plin3=0;plin4=0;
for (i=0;i<12;i++) vect_key[i]=0;
i=0;
pcol1=0;
if(plin1==0) {vect_key[0]=1;ok=1;}
if(plin2==0) {vect_key[3]=4;ok=1;}
if(plin3==0) {vect_key[6]=7;ok=1;}
if(plin4==0) {vect_key[9]=10;ok=1;}
pcol1=1;
pcol2=0;
if(plin1==0) {vect_key[1]=2;ok=1;}
if(plin2==0) {vect_key[4]=5;ok=1;}
if(plin3==0) {vect_key[7]=8;ok=1;}
if(plin4==0) {vect_key[10]=11;ok=1;}
pcol2=1;
pcol3=0;
if(plin1==0) {vect_key[2]=3;ok=1;}
if(plin2==0) {vect_key[5]=6;ok=1;}
if(plin3==0) {vect_key[8]=9;ok=1;}
if(plin4==0) {vect_key[11]=12;ok=1;}
pcol3=1;
//daca s-a citit un buton valid mai testez de 30 de ori pentru o confirmare ca nu a fost un zgomot
if(ok==1)
{
for(i=0;i<30;i++)
{
pcol1=0;
if(plin1==0) {vect_key[0]=1;ok=1;}
else {vect_key[0]=0;ok=0;}
if(plin2==0) {vect_key[3]=4;ok=1;}
else {vect_key[3]=0;ok=0;}
if(plin3==0) {vect_key[6]=7;ok=1;}
else {vect_key[6]=0;ok=0;}
if(plin4==0) {vect_key[9]=10;ok=1;}
else {vect_key[9]=0;ok=0;}
pcol1=1;
pcol2=0;
if(plin1==0) {vect_key[1]=2;ok=1;}
else {vect_key[1]=0;ok=0;}
if(plin2==0) {vect_key[4]=5;ok=1;}
else {vect_key[4]=0;ok=0;}
if(plin3==0) {vect_key[7]=8;ok=1;}
else {vect_key[7]=0;ok=0;}
if(plin4==0) {vect_key[10]=11;ok=1;}
else {vect_key[10]=0;ok=0;}
pcol2=1;
pcol3=0;
if(plin1==0) {vect_key[2]=3;ok=1;}
else {vect_key[2]=0;ok=0;}
if(plin2==0) {vect_key[5]=6;ok=1;}
else {vect_key[5]=0;ok=0;}
if(plin3==0) {vect_key[8]=9;ok=1;}
else {vect_key[8]=0;ok=0;}
if(plin4==0) {vect_key[11]=12;ok=1;}
else {vect_key[11]=0;ok=0;}
pcol3=1;
}
}
pDirlin4 =0;
pDirlin3 =0;
pDirlin2 =0;
pDirlin1 =0;
}
Rutina afisare evenimente pe ecranul LCD
//cat timp nu s-a primit nici un mesaj de la wireless se asteaptă
while(flag_gata!=24);
//s-au primit date + se incepe prelucrarea lor
valid_data1=valid_data;
valid_data=0;
flag_gata=0;
//verificare daca data primita contine codul producatorului
if (valid_data1==ID_PRODUCER)//aici se astepta stringul cu salon si pat
{
//flag_gata=0;
//valid_data=0;
salon=0;
//daca s-a gasit codul producatorului la inceputul mesajului se incepe salvarea in variabile datele utile
while(flag_gata!=8);
salon=valid_data&0x000000FF;
flag_gata=0;
valid_data=0;
if ((salon!=0)&&(salon<64))
{
//daca exista salon valid atunci se asteapta ultimii 32 biti care pot sa reprezinte un pat sau o asistenta
while(flag_gata!=32);
flag_gata=0;
val_data[0]=valid_data;
valid_data=0;
if((val_data[0]>>8)==0)// cerere
{
pat=val_data[0];
//daca patul nu exista in vectorul de evenimente netratate afisez pe LCD cererea
if (mem_process[salon-1]==0)
{
GotoLCD(1,0);
CharOut('S');CharOut('a');CharOut('l');CharOut(':');
CharOut(convert_to_display1(salon)>>8);
CharOut(convert_to_display1(salon));
CharOut(' ');
CharOut('P');CharOut('a');CharOut('t');CharOut(':');
CharOut(convert_to_display1(pat)>>8);
CharOut(convert_to_display1(pat));
old_mem_process[salon-1]=1;
mem_process[salon-1]=pat;
//setare flag alarmare care va porni sonorul
flag_alrm=1;
GIE=0;
//salvare in memorie patul la adresa salonului
eeprom_write1(0x2F+salon,pat);
GIE=1;
}
//adaugare eveniment in memoria externa
WriteByteTo24C256(0xC06+(number_of_events*9), 0xFF);
t=1;
}
else //asistenta-evenimentul dispare de pe lcd si se memoreaza in eprom
{
if(mem_process[salon-1]!=0)
{
//daca asistenta a asezat RFID in salon se opreste sonorul
//se cauta in memoria externa id-ul asistentei
flag_alrm=0;
//testare daca nu exista nici o asistenta in baza de date
if(number_of_persons==0) t=100;
else
{
for(t=1;t<100;t++)
{
id_asist=ReadByteFrom24C256(t*20+16,&state);
id_asist<<=8;
id_asist+=ReadByteFrom24C256(t*20+17,&state);
id_asist<<=8;
id_asist+=ReadByteFrom24C256(t*20+18,&state);
id_asist<<=8;
id_asist+=ReadByteFrom24C256(t*20+19,&state);
if (id_asist==val_data[0]) break;
}
}
if(t==100)
WriteByteTo24C256(0xC06+(number_of_events*9),0xFF );
else {
//daca s-a gasit id-ul asistentei in memoria externa
//stergere din vectorul de alerte al pacientilor a salonul respectiv
// stergere alerta de pe LCD
WriteByteTo24C256(0xC06+(number_of_events*9),t );
nurse_event_adress=number_of_events;
mem_add[salon-1]=number_of_events;
GIE=0;
eeprom_write1(0x2F+salon,0x00);
eeprom_write1(0x70+2*(salon-1),mem_add[salon-1]>>8);
eeprom_write1(0x71+2*(salon-1),mem_add[salon-1]);
GIE=1;
old_mem_process[salon-1]=1;
mem_process[salon-1]=0;
GotoLCD(1,0);
for(k33k=0;k33k<16;k33k++)
CharOut(' ');
GIE=1;
}
}
else
{
t=100;
salon=0;
}
}
}
if ((salon!=0)&&(salon<64))
{
//daca salonul este valid si s-a mai primit o cerere din acelasi salon
// citire memorie si verificare. Daca maui exista un eveniment nu se mai salveaza inca o data
//evenimentul
ok_write=1;
if (number_of_events==0) ok_write=1;
else
for(trr=number_of_events-1;trr>mem_add[salon-1];trr–)
{
old_salon=ReadByteFrom24C256(0xC00+(trr*9), &status);
old_pat=ReadByteFrom24C256(0xC01+(trr*9), &status);
if(((salon==old_salon)&&(pat==old_pat))||(t==100)||(pat>35))
{ok_write=0;
old_pat=0;
old_salon=0;
break;
}
old_pat=0;
old_salon=0;
}
//la salvarea evenimentului se salveaza si data la care sa produs
//pentru o evaluare ulterioara a timpului de raspuns al asistentelor
if (ok_write==1)
{
WriteByteTo24C256(0xC00+(number_of_events*9), salon);
WriteByteTo24C256(0xC01+(number_of_events*9), pat);
WriteByteTo24C256(0xC02+(number_of_events*9), day);
WriteByteTo24C256(0xC03+(number_of_events*9), current_month);
WriteByteTo24C256(0xC04+(number_of_events*9), year_part1);
WriteByteTo24C256(0xC05+(number_of_events*9), year_part2);
WriteByteTo24C256(0xC07+(number_of_events*9), hour);
WriteByteTo24C256(0xC08+(number_of_events*9), min);
number_of_events++;
GIE=0;
eeprom_write1(0x08,(number_of_events>>8));
eeprom_write1(0x09,number_of_events);
GIE=1;
}
}
Rutina vizualizare evenimente
void view_evenimente(void)
{
unsigned char txt_even[]={'N','u',' ','e','x','i','s','t','a',' ','e','v','e','n','i','m','e','n','t','e'};
unsigned char t;
unsigned int iteratie=0;
unsigned char asist=0;
unsigned char state;
unsigned char ora,minut;
TMR1ON=0;
read_tast();
//cat tip tin apasat butonul OK se asteapta
while(vect_key[11]!=0)
{
read_tast();
}
read_tast();
//stergere date afisate pe LCD
ClearLCD();
DelayMs(2);
ComandOut(0x80);
//daca nu exista evenimente se afiseaza acest fapt
if(number_of_events==0)
{
for(t=0;t<10;t++)
CharOut(txt_even[t]);
ComandOut(0xC0);
for(t=10;t<20;t++)
CharOut(txt_even[t]);
}
else
{ //pentru prima intrare in aceasta functie se merge direct la afisarea pe LCD
goto evenimetu;
//dupa ce se trece de prima afisare se incepe testarea tastatura
//cat timp nu este cancel sau OK apasat se verifica celelalte butoane
while((vect_key[9]==0)&&(vect_key[11]==0))
{
read_tast();
if (vect_key[3]!=0)
{
if (iteratie!=0)
iteratie–;
}
if(vect_key[5]!=0)
{
if (iteratie!=(number_of_events-1))
iteratie++;
}
//daca s-a apasat butonul4(stanga) sau butonul 6(dreapta) se citeste din memoria externa
//afisez evenimentul citit pe LCD
if ((vect_key[3]!=0)||(vect_key[5]!=0))
{
DelayMs(250);
DelayMs(250);
evenimetu:
read_tast();
ClearLCD();
DelayMs(2);
ComandOut(0x80);
CharOut(convert_to_display1(ReadByteFrom24C257(0xC00+iteratie*9,&state))>>8);//salon
CharOut(convert_to_display1(ReadByteFrom24C257(0xC00+iteratie*9,&state)));//salon
CharOut('-');
CharOut(convert_to_display1(ReadByteFrom24C257(0xC01+iteratie*9,&state))>>8);//pat
CharOut(convert_to_display1(ReadByteFrom24C257(0xC01+iteratie*9,&state)));//pat
CharOut(' ');
CharOut(convert_to_display1(ReadByteFrom24C257(0xC02+iteratie*9,&state))>>8);//zi
CharOut(convert_to_display1(ReadByteFrom24C257(0xC02+iteratie*9,&state)));//zi
CharOut('/');
CharOut(convert_to_display1(ReadByteFrom24C257(0xC03+iteratie*9,&state))>>8);//luna
CharOut(convert_to_display1(ReadByteFrom24C257(0xC03+iteratie*9,&state)));//luna
CharOut('/');
CharOut(convert_to_display1(ReadByteFrom24C257(0xC04+iteratie*9,&state))>>8);//an_part1
CharOut(convert_to_display1(ReadByteFrom24C257(0xC04+iteratie*9,&state)));//an_part1
CharOut(convert_to_display1(ReadByteFrom24C257(0xC05+iteratie*9,&state))>>8);//an_part2
CharOut(convert_to_display1(ReadByteFrom24C257(0xC05+iteratie*9,&state)));//an_part2
ora=ReadByteFrom24C257(0xC07+iteratie*9,&state);
minut=ReadByteFrom24C257(0xC08+iteratie*9,&state);
ComandOut(0xC0);
asist=ReadByteFrom24C257(0xC06+iteratie*9,&state);
//daca in memoria externa in locul destinat asistentei se regaseste valoarea 0xFF se afiseaza //evenimentul ca fiind o cerere
//altfel se afiseaza numele asistentei care a raspuns la solicitarea
if(asist==0xFF)
CharOut('C');
else
for(t=0;t<10;t++)//afisez numa primele 10 caract din numele asist ca sa incapa loc si de ora
CharOut(ReadByteFrom24C257((asist*20)+t,&state));
CharOut(' ');
CharOut(convert_to_display1(ora)>>8);
CharOut(convert_to_display1(ora));
CharOut(':');
CharOut(convert_to_display1(minut)>>8);
CharOut(convert_to_display1(minut));
}
}//end while mare
}//end else number_of_events==0
DelayMs(250);
DelayMs(250);
DelayMs(250);
DelayMs(250);
//daca s-a apasat butonul cancel sau OK se asteapta pana acestea vor fi dezactivate
if (vect_key[9]!=0) while (vect_key[9]!=0) read_tast();
if (vect_key[11]!=0) while (vect_key[11]!=0) read_tast();
}
Rutina introducere asistenta:
void set_person(void)
{
unsigned char poz=0;//cursorului
unsigned char iteratie=0x40;
unsigned char stat;
unsigned char nume[16];
unsigned char t;
unsigned char txt[]={'I','n','t','r','o','d','.',' ','n','u','m','e','l','e',':'};
unsigned char txt_full[]={'M','e','m','o','r','i','e',' ','p','l','i','n','a','!','!'};
unsigned char txt_card[]={'A','s','t','e','p','t','a','r','e',' ','c','a','r','d',' ','a','s','i','s','t','e','n','t','a'};
unsigned char txt_ok[]={'I','n','r','e','g','i','s','t','r','a','r','e',' ','r','e','u','s','i','t','a'};
unsigned long cardul_temp=0;
TMR1ON=0;
read_tast();
for(t=0;t<16;t++)
nume[t]=' ';
ClearLCD();
DelayMs(5);
ComandOut(0x80);
for(t=0;t<15;t++)
CharOut(txt[t]);
while(vect_key[11]!=0)// asteptare dezactivarea tastei OK pentru a putea continua
{
read_tast();
}
DelayMs(250);
DelayMs(250);
while(vect_key[11]==0)// cat timp tasta OK nu este apasata se poate introduce caracter
{
read_tast();
//daca sunt memorate deja 100 de asistente in memorie se afiseaza pe LCD mesajul "Memorie plina"
if (number_of_persons==100)
{
ClearLCD();
DelayMs(2);
ComandOut(0x80);
for (t=0;t<15;t++)
CharOut(txt_full[t]);
}
else//daca memoria nu este plina se asteapta introducerea caracterelor
{
ComandOut(0xC0+poz);
//daca se apasa butonul 6(dreapta) se muta cursorul cu o pozitie
if(vect_key[5]!=0)
{
if(poz!=16) poz++;
else poz=16;//o sa am un bip scurt
iteratie=0x40;
}
//daca se apasa butonul 4(stanga) se muta cursorul cu o pozitie
if(vect_key[3]!=0)
{
if(poz!=0) poz–;
else poz=0;//o sa am un bip scurt
iteratie=0x40;
}
ComandOut(0xC0+poz);
//daca se apasa butonul 2(up) se creste litera(deplasare catre sfarsitul alfabetului)
if (vect_key[1]!=0)
{
iteratie++;
//daca nu s-a ajuns la litera z se poate continua la urmatoarea litera
//altfel de la litera Z se trece la litera A
if(iteratie!=0x5B)
{ nume[poz]=iteratie;
CharOut(iteratie);
}
else
{
iteratie=0x41;
nume[poz]=iteratie;
CharOut(iteratie);
}
} //end up
//daca se apasa butonul 2(up) se descreste litera(deplasare catre inceputul alfabetului)
if (vect_key[7]!=0)
{
iteratie–;
// daca s-a ajuns la litera A urmatoarea apasare pe buton va duce la litera Z
if((iteratie==0x3F)||(iteratie==0x40)) iteratie=0x5A;
nume[poz]=iteratie;
CharOut(iteratie);
} //end down
// daca se apasa butonul cancel se iese din meniul de introducere a asistentei
if(vect_key[9]!=0) break;
DelayMs(150);
}
read_tast();
}//end while
// daca s-a apasat pe butonul OK se iese din bucla while
//se asteapta introducerea cardului
for (t=0;t<16;t++)
stat=WriteByteTo24C257((((number_of_persons+1)*20)+t), nume[t]);
if(vect_key[9]!=0)
while(vect_key[9]!=0) read_tast();
else
{ while(vect_key[11]!=0)
{
read_tast();
}
ClearLCD();
DelayMs(2);
//afisare pe display a mesajul de asteptare a cardului
ComandOut(0x80);
for(t=0;t<15;t++)
CharOut(txt_card[t]);
ComandOut(0xC0);
for (t=15;t<24;t++)
CharOut(txt_card[t]);
CREN=0;CREN=1;
Number_of_persons++;
receive_nurse_key:
cardul=0;
cardul_temp=0;
//asteptare card prin citirea datelor de la modulul serial
while(ReadByteFromSerial()!=0xBB)
while(ReadByteFromSerial()!=0xAA);
for(t=0;t<3;t++)
{
tempi=ReadByteFromSerial();
cardul+=tempi;
cardul<<=8;
}
tempi=ReadByteFromSerial();
cardul+=tempi;
//daca s-a citit cardul trebuie sa existe confirmare ca s-a citit bine si se mai asteapta de 3 ori codul de card
while(ReadByteFromSerial()!=0xBB)
while(ReadByteFromSerial()!=0xAA);
for(t=0;t<3;t++)
{
tempi=ReadByteFromSerial();
cardul_temp+=tempi;
cardul_temp<<=8;
}
tempi=ReadByteFromSerial();
cardul_temp+=tempi;
//daca codurile primite de 4 ori nu sunt identice se revine la prima citire a cardului
//si se astepta din nou
if (cardul!=cardul_temp) goto receive_nurse_key;
//daca codurile citite sunt identice se memoreaza cardul in epromul extern
stat=WriteByteTo24C257(((number_of_persons*20)+16), cardul>>24);
stat=WriteByteTo24C257(((number_of_persons*20)+17), cardul>>16);
stat=WriteByteTo24C257(((number_of_persons*20)+18), cardul>>8);
stat=WriteByteTo24C257(((number_of_persons*20)+19), cardul);
//stergere ce era afisat pe LCD si afisare mesajul de confirmare a salvarii
ClearLCD();
DelayMs(2);
ComandOut(0x80);
for(t=0;t<13;t++)
CharOut(txt_ok[t]);
ComandOut(0xC0);
for(t=13;t<20;t++)
CharOut(txt_ok[t]);
DelayMs(250);
DelayMs(250);
DelayMs(250);
//asteptare sa nu mai fie apasat butonul de OK
while(vect_key[11]!=0)
{
read_tast();
}
//daca s-a introdus doar un card fara nume desi a fost memorat, la urmatoarea scriere se va suprascrie peste ultima pozitie
for(t=0;t<16;t++)
if (nume[t]!=' ') break;
if(t==16)
{
number_of_persons-=1;
eeprom_write(0x07,number_of_persons);
}
}
ClearLCD();
DelayMs(2);
TMR1ON=1;
}
Anexa 2. Coduri sursă folosite de dispozitivului de salon
Rutinele de citire a cardurilor RFID
unsigned char HaveNextCard(unsigned int timeout)
{
//unsigned char j;
unsigned char isvalid=0;
unsigned int time;
status &= ~DATA_READY;// initiere receptie-> variabila status ca spune cand sa primit un sir de biti
INTE = 1; //activare intreruperea externa pentru urmatoarea achizitie
cont = 0;
if (timeout==0) time=0xFF;// daca timeout este 0 se ramane in rutina pana la primirea unui card valid
else time=timeout;
while(cont<time)//cat timp nu sa terminat timpul de asteptare se incearca sa citesc RFID
{
cntFullLoop = 0;
while (++cntFullLoop!=0x17) continue;
if (status & DATA_READY)// s-a primit un sir de date de lungime valida
{
isvalid=ProcessDataStream();// procesare datele
if(isvalid)
{
lastCardId = cardId;
INTE=0;
//ledVerde = 1;ledRosu = 0;
return 1;
}
else// este un sir de date dar nu reprezinta cod de card valid
//asteptare un nou sir de date
{
status &= ~DATA_READY;
INTE = 1;
isvalid=0;
}
}
if(timeout==0) cont=0;// daca timeout este 0-> asteptare pana am card valid
cont++;
}
INTE=0;
return 0;
}
unsigned char ProcessDataStream(void)
{
unsigned int i;
unsigned char result = ParseStreamCRC5();// verificare codul de detectie a erorilor
if (result)//daca codul este bun-> impachetare datele intr-o singura variabila
{
for (i=0; i<5; i++)
{
if(i>0)
cardId = (cardId << 8) + hexCode[i];
}
}
return result;
}
unsigned int ParseStreamCRC5(void)
{
unsigned char i, j, k, i5, n, data, parity, bitData, colParity;
colParity = 0;
parity = 0;
n = 0;
j = 0;
k = 0;
i5 = 0;
data = 0;
for (i=9; i<64; i++)
{
j = i >> 3; //byte number
k = 7 – (i & 0x07); //bit number within byte
bitData = (proxy_data[j] & (1<<k)) ? 1 : 0;
parity ^= bitData;
i5++;
if (i5 % 5)
{
data <<= 1;
data += bitData;
}
else
{
if (n==10)
return (colParity ^ data)==0x00; //return colum parity status
//return 1;
else if (parity)
return 0; //row parity error
k = n >> 1;
if (n & 0x01)
hexCode[k] = (hexCode[k] << 4) | data;
else
hexCode[k] = data;
colParity ^= data;
n++;
data = 0;
}
}
return 0; //this is a dummy return; it shouldn't get here
}
…….
if(INTF&&INTE)// daca este intrerupere externa si intreruperea este activata
{
TMR0 = 0xD9;// setare timer si asteptare pana acesta da overflow
while(TMR0) continue;
bitstate = pData;
INTEDG = !pData;
if(cnt==8)//daca sunt 8 biti valizi se memoreaza in vectorul proxy_data si se trece la urmatoarea pozitie in vector pentru citirea urmatorilor 8 biti
{
if (k==0 && !(code==0xFF && bitstate))
cnt–;//just wait for START sequence (9bit of 1) FF byte and one extra 1 bit
else
{
proxy_data[k] = code;
if (proxy_data[k] != previous_data[k])
status &= ~DATA_STABILE;
k++;
if(k==8)
{
if (status & DATA_STABILE) //if we have two consecutive streams identical, then data is stabile
{
status |= DATA_READY;
INTE = 0; //disable external interrupt
INTF = 0;
code = 0;//cnt = 0;
return;
}
status |= DATA_STABILE;
}
previous_data[k-1] = proxy_data[k-1];
k %= 8;
code = 0;cnt = 0;
}
}
code = (code << 1) + bitstate;
cnt++;
INTF = 0;
}
………….
if(INTF&&INTE)// daca am intrerupere externa si intreruperea este activata
{
TMR0 = 0xD9;// setez timerul si astept pana acesta da overflow
while(TMR0) continue;
// bun data in variaila si schib frontul pe care va fi sezizata intreruperea
bitstate = pData;
INTEDG = !pData;
if(cnt==8)//daca am 8 biti valizi ii memorez in vectorul proxy_data si trec la urmatoarea pozitie in vector pentru citirea urmatorilor 8 biti
{
if (k==0 && !(code==0xFF && bitstate))
cnt–;//just wait for START sequence (9bit of 1) FF byte and one extra 1 bit
else
{
proxy_data[k] = code;
if (proxy_data[k] != previous_data[k])
status &= ~DATA_STABILE;
k++;
if(k==8)
{
if (status & DATA_STABILE) //if we have two consecutive streams identical, then data is stabile
{
status |= DATA_READY;
INTE = 0; //disable external interrupt
INTF = 0;
code = 0;//cnt = 0;
return;
}
status |= DATA_STABILE;
}
previous_data[k-1] = proxy_data[k-1];
k %= 8;
code = 0;cnt = 0;
}
}
code = (code << 1) + bitstate;
cnt++;
INTF = 0;
}
………..
Rutina de citire a telecomenzilor fara fir:
void get_prod_code(unsigned int timeout)
{
unsigned char conn;
unsigned int time,timeunu;
unsigned int cntlp;
//unsigned char time_temp;
if(timeout==0) timeunu=0xFF;// daca timeout=0 nu mai conteaza limita de timp-> asteptare o telecomanda
else timeunu=timeout;
data_teste=0;// variabila in care va contine codul telecomenazii
flag_gata=0;
cntlp=0;
conn=0;
time=0;
while((flag_gata!=1)&&(time<timeunu))//cat timp nu s-a primit cod valid se citesc datele receptionate
{
while(RECV==0)//inainte de o receptie valida va fi mereu 0 logic pe intrare
{/
if((data_teste!=0)&&(cntlp==0xAA)) {cntlp=0;break;
}
if (cntlp==0x6AA) {cntlp=0;goto end;//daca s-a depasit timpul alocat citirii telecomenzilor fara fir se iese din functie
}
cntlp++;
}
DelayUs(171);//255
if(RECV==1)// 1 logic pe intrare insemna ca exista o transmisie valida
{
DelayUs(255);
DelayUs(255);
if(RECV==1) //bit o in transmisie
{
data_teste<<=1;
conn++;
if (conn==24)
{
conn=0;
flag_gata=1;
}
}
else// bit 1 in transmisie
{
data_teste<<=1;
data_teste|=1;
conn++;
if (conn==24)
{
conn=0;
flag_gata=1;
}
}
DelayUs(250);
DelayUs(250);
if(RECV==1)//din protocolul de comunicatie rezulta ca daca un numar de usec este 1 pe intrare inseamna ca este eroare
{
data_teste=0;
conn=0;
flag_gata=0;
}
else{cntlp=0;
}
}//end if(RECV==1)
else//am eroare
{
data_teste=0;
conn=0;
flag_gata=0;
}
if(flag_gata==1) //daca saterminat receptia unui string valid se asteapta ca pinul de intrare sa semnaleze o noua transmisie
{ //time_temp=time;
while(RECV==0)
{
if (timeout==0) time=0;
else time=time+0x01;
if (time>=timeunu) break;
}
DelayUs(255);
DelayUs(250);
}
if (timeout==0) time=0;
else time++;
}//end while data!=cod producator
end:
cntlp=0;
}
Rutina trimitere coduri catre dispozitivul central
void Transmit_to_master(unsigned char pat,unsigned long asistenta,unsigned char mod)
{
unsigned char id_salon_tempor;
unsigned char lrt;
unsigned char trt;
unsigned char hkt=0;
unsigned char pac_card_send1;
unsigned long id_producer=0x4D4F53;
unsigned long temporary;
INTE=0;
// pentru a trimite codurile trebuie ca "linia sa fie libera"
//pentru aceasta cat timp am date pe modulul de receptie se asteapta
while(RECV==0)
{hkt++;
if (hkt==0xFF) break;
DelayUs(50);
}
if (hkt!=0xFF)
hkt=0;
while(RECV==1)
{hkt++;
if (hkt==0xFF) break;
DelayUs(100);
}
if (hkt!=0xFF)
for (hkt=0;hkt<3;hkt++)
{ data_teste=0;
get_prod_code(0xFF);
if ((data_teste&0x00FFFFFF)!=0) hkt=0;
}
}
//asteptarea a luat sfarsit si se incep trimiterea
// setare transciever pe transmisie
rx_to_tx();
//incepere transmisia cu bitii de sincronizare
for (hkt=0;hkt<2;hkt++)
{
temporary=id_producer;
id_salon_tempor=0x1A;
pac_card_send1=pat;
for(trt=0;trt<10;trt++)
{
RA3=1;
DelayUs(5);
RA3=0;
DelayUs(5);
}
DelayMs(2);
//trimitere codul de producator
for (trt=0;trt<24;trt++)
{
RA3=1;
if( (temporary&0x800000)==0)
{
DelayMs(1);
RA3=0;
DelayUs(250);
DelayUs(70);
}
else
{
DelayUs(250);
DelayUs(70);
RA3=0;
DelayMs(1);
}
temporary<<=1;
}
RA3=1;
DelayUs(250);
RA3=0;
DelayMs(2);
//trimitere id salon
for(trt=0;trt<8;trt++)
{ RA3=1;
if((id_salon_tempor&0x80)==0)
{
DelayMs(1);
RA3=0;
DelayUs(250);
DelayUs(70);
}
else
{
DelayUs(250);
DelayUs(70);
RA3=0;
DelayMs(1);
}
id_salon_tempor<<=1;
}//sf cod salon
RA3=1;
DelayUs(250);
RA3=0;
DelayMs(2);
if (mod==1)//transmitere cod pat
{
for(lrt=0;lrt<24;lrt++)//24 de 0;
{
RA3=1;
DelayMs(1);
RA3=0;
DelayUs(250);
DelayUs(70);
}
for(lrt=0;lrt<8;lrt++)//cod pat
{
RA3=1;
if((pac_card_send1&0x80)==0)
{
DelayMs(1);
RA3=0;
DelayUs(250);
DelayUs(70);
}
else
{
DelayUs(250);
DelayUs(70);
RA3=0;
DelayMs(1);
}
pac_card_send1<<=1;
}
RA3=1;
DelayUs(150);
RA3=0;
DelayMs(2);
}
else //transmitere cod nurse
{
temporary=asistenta;
for(lrt=0;lrt<32;lrt++)
{
RA3=1;
if((temporary&0x80000000)==0)
{
DelayMs(1);
RA3=0;
DelayUs(250);
DelayUs(70);
}
else
{
DelayUs(250);
DelayUs(70);
RA3=0;
DelayMs(1);
}
temporary<<=1;
}
}
RA3=1;
DelayUs(150);
RA3=0;
DelayMs(2);
}
//dupa terminarea transmisiei se asteapta revenirea trasncieverului la starea de receptie
tx_to_rx();
}
Anexa 3. Schema electrica dispozitiv salon
Cap V. Bibliografie
www.en.wikipedia.org/wiki/RFID
www.rfids.ro
www.rfidjournal.com
RFID Essentials – Bill Glover, Himanshu Bhatt
O'Reilly, 2006
http://csrc.nist.gov/publications/nistpubs/800-98/SP800-98_RFID-2007.pdf
Passive RFID Basics(AN680) – www.microchip.com
SC2262 datasheet
http://www.discovercircuits.com/K/keypad.htm
http://www.next.gr/other-circuits/keypad-circuits/
http://esd.cs.ucr.edu/labs/decode_key/decode_key.html
PIC16F648 datasheet – www.microchip.com
PIC18F452 datasheet – www.microchip.com
FT232BM datasheet– www.ftdichip.com
How to use intelligent L.C.D.s – Julian Ilett
AC – 162B datasheet – Technologies
RTX-MID-3V – Aurel Wireless
Dispozitive și circuite electronice –Mihail Florea
Editura “Gh Asachi” , 1999
http://www.discovercircuits.com/B/beepers.htm
http://www.next.gr/audio/beeper-buzzer/
24LC64 datasheet– www.microchip.com
Anexa 1. Coduri sursă folosite de dispozitivul central
Rutina de tratare a intreruperilor de modul serial, unitate captura si ceas de timp real:
void interrupt isr()
{
//daca exista intrerupere de comparator si intreruperea este activata se citesc date
//intreruperea de comparator receptioneaza datele de la receiver
if(CCP1IF&&CCP1IE)
{
CCP1IE=0;
CCP1IF = 0;
capture_interval=CCPR1H;
capture_interval<<=8;
capture_interval+=CCPR1L;
if (CCP1CON == 5) //daca am front crescator
{
if (capture_interval<0xA0) {valid_data=0;flag_gata=0;}
else if (capture_interval<0x255) {valid_data<<=1;flag_gata++;}
else
if(capture_interval<0x500) {valid_data<<=1;valid_data+=1;flag_gata++;}
else {valid_data=0;flag_gata=0; }
}
T3CON=0xC8; //se incarcă in timer o valoare care generează esșantionarea
TMR3 = 0; //clear counter
TMR3ON = 1;
if (CCP1CON == 4)
CCP1CON = 5;
else CCP1CON = 4;
CCP1IF = 0;
CCP1IE=1;
}
//intreruperea de timer 1 care genereaza real time clock
if (TMR1IF&&TMR1IE)
{
TMR1IF=0;
TMR1H=0x0C;
TMR1L=0x00;
sec++;
//se verifică starea alarmarii si daca există eveniment se pornește alarma
if (flag_alrm==1)
{
RB4=0;
CCP2CON=0x0C;
T2CON=0x00;
TMR2ON=1;
PR2=0x1F;
CCPR2L=number1;
flag_alrm=0;
}
else
{
TMR2ON=0; //timer2 ON
CCP2CON=0x00;
RB3=0;
RB4=1;
}
//baleere cereri netratate pentru ca două asistente să nu meargă la acelasi salon
if(((sec-(sec/10)*10)==0)&&(sec/2==60) )
{
sec=0;
//afisare pe display evenimente
for (k3k=ultima_poz_afisata;k3k<50;k3k++)
if (mem_process[k3k]!=0)
{
flag_alrm=1;
afis_cerere(k3k+1,mem_process[k3k]);
ultima_poz_afisata=k3k+1;
if (ultima_poz_afisata==50) ultima_poz_afisata=0;
break;
}
if (k3k==50) ultima_poz_afisata=0;
//sf afisare pe display evenimente
//actiunea de update al datei curente
min++;
if(min==60)
{
min=0;
hour++;
if(hour==24)
{
hour=0;
day++;
if(day==(days_per_month[current_month]+1))
{
day=1;
current_month++;
if(current_month==13)
{
current_month=1;
if(year_part2==99)
{
year_part2=0;
year_part1++;
}
else year_part2++;
}
}
}
}
//scrierea in memoria interna a datei curente
eeprom_write(0x00,hour);
eeprom_write(0x01,min);
eeprom_write(0x02,day);
eeprom_write(0x03,current_month);
eeprom_write(0x04,year_part1);
eeprom_write(0x05,year_part2);
}
// afisarea datei curente
afis_data();
//citirea tastaturii pt se vedea daca există cerere de intrare în meniu sau de update volum alarmare
read_tast();
if(vect_key[1]!=0)
{
if(number!=26) number++;
else number=26;
}
if(vect_key[7]!=0)
{
if(number!=0) number–;
else number=0;
}
// daca există cerere de update volum alarmare se afișează pe LCD nivelul volumului și se incrementează sau se descrementează
if((vect_key[7]!=0) ||(vect_key[1]!=0) )
{
TMR1ON=0;
ClearLCD();
DelayMs(2);
ComandOut(0x80);
for(t=0;t<13;t++)
CharOut(txt[t]);
tem=number;
number1=0x1F;
number1-=number;
volum=number1;
ComandOut(0xC0);
CharOut(convert_to_display1(tem)>>8);
CharOut(convert_to_display1(tem));
PWM2_alarmare(number1,90);
eeprom_write(0x30,number1);
sec++;
if (sec==120) sec==119;
DelayMs(250);
DelayMs(250);
ClearLCD();
DelayMs(2);
afis_data();
}
//daca s-a apasat butonul OK se asteaptă 5 secunde pentru a intra in meniu
if (vect_key[11]!=0)
{
while(contor_apasare<0xFF)
{
read_tast();
contor_apasare++;
if (vect_key[11]==0) break;
}
//daca s-a tinut 5 sec butonul OK apasat se intră in meniu
if(contor_apasare==0xFF)
{
PWM2_taste(0x00);RCIE=0;menu(); RCIE=1;CREN=0;CREN=1;
}
contor_apasare=0x00;
}
TMR1ON=1;
}
//tratare intrerupere de receptie seriala daca intreruperea este activata
if (RCIF&&RCIE)
{
RCIF=0;
// pornire transmisie seriala a evenimentelor
if (RCREG=='E')
{
stop_to_send=0;
send_datas();
}
if (RCREG=='H') stop_to_send=1;// oprirea transmisiei evenimentelor
}
}
Rutina citire tastatura
void read_tast(void)
{
unsigned char i=0;
unsigned char ok=0;
pDirlin4 =1;
pDirlin3 =1;
pDirlin2 =1;
pDirlin1 =1;
plin1=0;plin2=0;plin3=0;plin4=0;
for (i=0;i<12;i++) vect_key[i]=0;
i=0;
pcol1=0;
if(plin1==0) {vect_key[0]=1;ok=1;}
if(plin2==0) {vect_key[3]=4;ok=1;}
if(plin3==0) {vect_key[6]=7;ok=1;}
if(plin4==0) {vect_key[9]=10;ok=1;}
pcol1=1;
pcol2=0;
if(plin1==0) {vect_key[1]=2;ok=1;}
if(plin2==0) {vect_key[4]=5;ok=1;}
if(plin3==0) {vect_key[7]=8;ok=1;}
if(plin4==0) {vect_key[10]=11;ok=1;}
pcol2=1;
pcol3=0;
if(plin1==0) {vect_key[2]=3;ok=1;}
if(plin2==0) {vect_key[5]=6;ok=1;}
if(plin3==0) {vect_key[8]=9;ok=1;}
if(plin4==0) {vect_key[11]=12;ok=1;}
pcol3=1;
//daca s-a citit un buton valid mai testez de 30 de ori pentru o confirmare ca nu a fost un zgomot
if(ok==1)
{
for(i=0;i<30;i++)
{
pcol1=0;
if(plin1==0) {vect_key[0]=1;ok=1;}
else {vect_key[0]=0;ok=0;}
if(plin2==0) {vect_key[3]=4;ok=1;}
else {vect_key[3]=0;ok=0;}
if(plin3==0) {vect_key[6]=7;ok=1;}
else {vect_key[6]=0;ok=0;}
if(plin4==0) {vect_key[9]=10;ok=1;}
else {vect_key[9]=0;ok=0;}
pcol1=1;
pcol2=0;
if(plin1==0) {vect_key[1]=2;ok=1;}
else {vect_key[1]=0;ok=0;}
if(plin2==0) {vect_key[4]=5;ok=1;}
else {vect_key[4]=0;ok=0;}
if(plin3==0) {vect_key[7]=8;ok=1;}
else {vect_key[7]=0;ok=0;}
if(plin4==0) {vect_key[10]=11;ok=1;}
else {vect_key[10]=0;ok=0;}
pcol2=1;
pcol3=0;
if(plin1==0) {vect_key[2]=3;ok=1;}
else {vect_key[2]=0;ok=0;}
if(plin2==0) {vect_key[5]=6;ok=1;}
else {vect_key[5]=0;ok=0;}
if(plin3==0) {vect_key[8]=9;ok=1;}
else {vect_key[8]=0;ok=0;}
if(plin4==0) {vect_key[11]=12;ok=1;}
else {vect_key[11]=0;ok=0;}
pcol3=1;
}
}
pDirlin4 =0;
pDirlin3 =0;
pDirlin2 =0;
pDirlin1 =0;
}
Rutina afisare evenimente pe ecranul LCD
//cat timp nu s-a primit nici un mesaj de la wireless se asteaptă
while(flag_gata!=24);
//s-au primit date + se incepe prelucrarea lor
valid_data1=valid_data;
valid_data=0;
flag_gata=0;
//verificare daca data primita contine codul producatorului
if (valid_data1==ID_PRODUCER)//aici se astepta stringul cu salon si pat
{
//flag_gata=0;
//valid_data=0;
salon=0;
//daca s-a gasit codul producatorului la inceputul mesajului se incepe salvarea in variabile datele utile
while(flag_gata!=8);
salon=valid_data&0x000000FF;
flag_gata=0;
valid_data=0;
if ((salon!=0)&&(salon<64))
{
//daca exista salon valid atunci se asteapta ultimii 32 biti care pot sa reprezinte un pat sau o asistenta
while(flag_gata!=32);
flag_gata=0;
val_data[0]=valid_data;
valid_data=0;
if((val_data[0]>>8)==0)// cerere
{
pat=val_data[0];
//daca patul nu exista in vectorul de evenimente netratate afisez pe LCD cererea
if (mem_process[salon-1]==0)
{
GotoLCD(1,0);
CharOut('S');CharOut('a');CharOut('l');CharOut(':');
CharOut(convert_to_display1(salon)>>8);
CharOut(convert_to_display1(salon));
CharOut(' ');
CharOut('P');CharOut('a');CharOut('t');CharOut(':');
CharOut(convert_to_display1(pat)>>8);
CharOut(convert_to_display1(pat));
old_mem_process[salon-1]=1;
mem_process[salon-1]=pat;
//setare flag alarmare care va porni sonorul
flag_alrm=1;
GIE=0;
//salvare in memorie patul la adresa salonului
eeprom_write1(0x2F+salon,pat);
GIE=1;
}
//adaugare eveniment in memoria externa
WriteByteTo24C256(0xC06+(number_of_events*9), 0xFF);
t=1;
}
else //asistenta-evenimentul dispare de pe lcd si se memoreaza in eprom
{
if(mem_process[salon-1]!=0)
{
//daca asistenta a asezat RFID in salon se opreste sonorul
//se cauta in memoria externa id-ul asistentei
flag_alrm=0;
//testare daca nu exista nici o asistenta in baza de date
if(number_of_persons==0) t=100;
else
{
for(t=1;t<100;t++)
{
id_asist=ReadByteFrom24C256(t*20+16,&state);
id_asist<<=8;
id_asist+=ReadByteFrom24C256(t*20+17,&state);
id_asist<<=8;
id_asist+=ReadByteFrom24C256(t*20+18,&state);
id_asist<<=8;
id_asist+=ReadByteFrom24C256(t*20+19,&state);
if (id_asist==val_data[0]) break;
}
}
if(t==100)
WriteByteTo24C256(0xC06+(number_of_events*9),0xFF );
else {
//daca s-a gasit id-ul asistentei in memoria externa
//stergere din vectorul de alerte al pacientilor a salonul respectiv
// stergere alerta de pe LCD
WriteByteTo24C256(0xC06+(number_of_events*9),t );
nurse_event_adress=number_of_events;
mem_add[salon-1]=number_of_events;
GIE=0;
eeprom_write1(0x2F+salon,0x00);
eeprom_write1(0x70+2*(salon-1),mem_add[salon-1]>>8);
eeprom_write1(0x71+2*(salon-1),mem_add[salon-1]);
GIE=1;
old_mem_process[salon-1]=1;
mem_process[salon-1]=0;
GotoLCD(1,0);
for(k33k=0;k33k<16;k33k++)
CharOut(' ');
GIE=1;
}
}
else
{
t=100;
salon=0;
}
}
}
if ((salon!=0)&&(salon<64))
{
//daca salonul este valid si s-a mai primit o cerere din acelasi salon
// citire memorie si verificare. Daca maui exista un eveniment nu se mai salveaza inca o data
//evenimentul
ok_write=1;
if (number_of_events==0) ok_write=1;
else
for(trr=number_of_events-1;trr>mem_add[salon-1];trr–)
{
old_salon=ReadByteFrom24C256(0xC00+(trr*9), &status);
old_pat=ReadByteFrom24C256(0xC01+(trr*9), &status);
if(((salon==old_salon)&&(pat==old_pat))||(t==100)||(pat>35))
{ok_write=0;
old_pat=0;
old_salon=0;
break;
}
old_pat=0;
old_salon=0;
}
//la salvarea evenimentului se salveaza si data la care sa produs
//pentru o evaluare ulterioara a timpului de raspuns al asistentelor
if (ok_write==1)
{
WriteByteTo24C256(0xC00+(number_of_events*9), salon);
WriteByteTo24C256(0xC01+(number_of_events*9), pat);
WriteByteTo24C256(0xC02+(number_of_events*9), day);
WriteByteTo24C256(0xC03+(number_of_events*9), current_month);
WriteByteTo24C256(0xC04+(number_of_events*9), year_part1);
WriteByteTo24C256(0xC05+(number_of_events*9), year_part2);
WriteByteTo24C256(0xC07+(number_of_events*9), hour);
WriteByteTo24C256(0xC08+(number_of_events*9), min);
number_of_events++;
GIE=0;
eeprom_write1(0x08,(number_of_events>>8));
eeprom_write1(0x09,number_of_events);
GIE=1;
}
}
Rutina vizualizare evenimente
void view_evenimente(void)
{
unsigned char txt_even[]={'N','u',' ','e','x','i','s','t','a',' ','e','v','e','n','i','m','e','n','t','e'};
unsigned char t;
unsigned int iteratie=0;
unsigned char asist=0;
unsigned char state;
unsigned char ora,minut;
TMR1ON=0;
read_tast();
//cat tip tin apasat butonul OK se asteapta
while(vect_key[11]!=0)
{
read_tast();
}
read_tast();
//stergere date afisate pe LCD
ClearLCD();
DelayMs(2);
ComandOut(0x80);
//daca nu exista evenimente se afiseaza acest fapt
if(number_of_events==0)
{
for(t=0;t<10;t++)
CharOut(txt_even[t]);
ComandOut(0xC0);
for(t=10;t<20;t++)
CharOut(txt_even[t]);
}
else
{ //pentru prima intrare in aceasta functie se merge direct la afisarea pe LCD
goto evenimetu;
//dupa ce se trece de prima afisare se incepe testarea tastatura
//cat timp nu este cancel sau OK apasat se verifica celelalte butoane
while((vect_key[9]==0)&&(vect_key[11]==0))
{
read_tast();
if (vect_key[3]!=0)
{
if (iteratie!=0)
iteratie–;
}
if(vect_key[5]!=0)
{
if (iteratie!=(number_of_events-1))
iteratie++;
}
//daca s-a apasat butonul4(stanga) sau butonul 6(dreapta) se citeste din memoria externa
//afisez evenimentul citit pe LCD
if ((vect_key[3]!=0)||(vect_key[5]!=0))
{
DelayMs(250);
DelayMs(250);
evenimetu:
read_tast();
ClearLCD();
DelayMs(2);
ComandOut(0x80);
CharOut(convert_to_display1(ReadByteFrom24C257(0xC00+iteratie*9,&state))>>8);//salon
CharOut(convert_to_display1(ReadByteFrom24C257(0xC00+iteratie*9,&state)));//salon
CharOut('-');
CharOut(convert_to_display1(ReadByteFrom24C257(0xC01+iteratie*9,&state))>>8);//pat
CharOut(convert_to_display1(ReadByteFrom24C257(0xC01+iteratie*9,&state)));//pat
CharOut(' ');
CharOut(convert_to_display1(ReadByteFrom24C257(0xC02+iteratie*9,&state))>>8);//zi
CharOut(convert_to_display1(ReadByteFrom24C257(0xC02+iteratie*9,&state)));//zi
CharOut('/');
CharOut(convert_to_display1(ReadByteFrom24C257(0xC03+iteratie*9,&state))>>8);//luna
CharOut(convert_to_display1(ReadByteFrom24C257(0xC03+iteratie*9,&state)));//luna
CharOut('/');
CharOut(convert_to_display1(ReadByteFrom24C257(0xC04+iteratie*9,&state))>>8);//an_part1
CharOut(convert_to_display1(ReadByteFrom24C257(0xC04+iteratie*9,&state)));//an_part1
CharOut(convert_to_display1(ReadByteFrom24C257(0xC05+iteratie*9,&state))>>8);//an_part2
CharOut(convert_to_display1(ReadByteFrom24C257(0xC05+iteratie*9,&state)));//an_part2
ora=ReadByteFrom24C257(0xC07+iteratie*9,&state);
minut=ReadByteFrom24C257(0xC08+iteratie*9,&state);
ComandOut(0xC0);
asist=ReadByteFrom24C257(0xC06+iteratie*9,&state);
//daca in memoria externa in locul destinat asistentei se regaseste valoarea 0xFF se afiseaza //evenimentul ca fiind o cerere
//altfel se afiseaza numele asistentei care a raspuns la solicitarea
if(asist==0xFF)
CharOut('C');
else
for(t=0;t<10;t++)//afisez numa primele 10 caract din numele asist ca sa incapa loc si de ora
CharOut(ReadByteFrom24C257((asist*20)+t,&state));
CharOut(' ');
CharOut(convert_to_display1(ora)>>8);
CharOut(convert_to_display1(ora));
CharOut(':');
CharOut(convert_to_display1(minut)>>8);
CharOut(convert_to_display1(minut));
}
}//end while mare
}//end else number_of_events==0
DelayMs(250);
DelayMs(250);
DelayMs(250);
DelayMs(250);
//daca s-a apasat butonul cancel sau OK se asteapta pana acestea vor fi dezactivate
if (vect_key[9]!=0) while (vect_key[9]!=0) read_tast();
if (vect_key[11]!=0) while (vect_key[11]!=0) read_tast();
}
Rutina introducere asistenta:
void set_person(void)
{
unsigned char poz=0;//cursorului
unsigned char iteratie=0x40;
unsigned char stat;
unsigned char nume[16];
unsigned char t;
unsigned char txt[]={'I','n','t','r','o','d','.',' ','n','u','m','e','l','e',':'};
unsigned char txt_full[]={'M','e','m','o','r','i','e',' ','p','l','i','n','a','!','!'};
unsigned char txt_card[]={'A','s','t','e','p','t','a','r','e',' ','c','a','r','d',' ','a','s','i','s','t','e','n','t','a'};
unsigned char txt_ok[]={'I','n','r','e','g','i','s','t','r','a','r','e',' ','r','e','u','s','i','t','a'};
unsigned long cardul_temp=0;
TMR1ON=0;
read_tast();
for(t=0;t<16;t++)
nume[t]=' ';
ClearLCD();
DelayMs(5);
ComandOut(0x80);
for(t=0;t<15;t++)
CharOut(txt[t]);
while(vect_key[11]!=0)// asteptare dezactivarea tastei OK pentru a putea continua
{
read_tast();
}
DelayMs(250);
DelayMs(250);
while(vect_key[11]==0)// cat timp tasta OK nu este apasata se poate introduce caracter
{
read_tast();
//daca sunt memorate deja 100 de asistente in memorie se afiseaza pe LCD mesajul "Memorie plina"
if (number_of_persons==100)
{
ClearLCD();
DelayMs(2);
ComandOut(0x80);
for (t=0;t<15;t++)
CharOut(txt_full[t]);
}
else//daca memoria nu este plina se asteapta introducerea caracterelor
{
ComandOut(0xC0+poz);
//daca se apasa butonul 6(dreapta) se muta cursorul cu o pozitie
if(vect_key[5]!=0)
{
if(poz!=16) poz++;
else poz=16;//o sa am un bip scurt
iteratie=0x40;
}
//daca se apasa butonul 4(stanga) se muta cursorul cu o pozitie
if(vect_key[3]!=0)
{
if(poz!=0) poz–;
else poz=0;//o sa am un bip scurt
iteratie=0x40;
}
ComandOut(0xC0+poz);
//daca se apasa butonul 2(up) se creste litera(deplasare catre sfarsitul alfabetului)
if (vect_key[1]!=0)
{
iteratie++;
//daca nu s-a ajuns la litera z se poate continua la urmatoarea litera
//altfel de la litera Z se trece la litera A
if(iteratie!=0x5B)
{ nume[poz]=iteratie;
CharOut(iteratie);
}
else
{
iteratie=0x41;
nume[poz]=iteratie;
CharOut(iteratie);
}
} //end up
//daca se apasa butonul 2(up) se descreste litera(deplasare catre inceputul alfabetului)
if (vect_key[7]!=0)
{
iteratie–;
// daca s-a ajuns la litera A urmatoarea apasare pe buton va duce la litera Z
if((iteratie==0x3F)||(iteratie==0x40)) iteratie=0x5A;
nume[poz]=iteratie;
CharOut(iteratie);
} //end down
// daca se apasa butonul cancel se iese din meniul de introducere a asistentei
if(vect_key[9]!=0) break;
DelayMs(150);
}
read_tast();
}//end while
// daca s-a apasat pe butonul OK se iese din bucla while
//se asteapta introducerea cardului
for (t=0;t<16;t++)
stat=WriteByteTo24C257((((number_of_persons+1)*20)+t), nume[t]);
if(vect_key[9]!=0)
while(vect_key[9]!=0) read_tast();
else
{ while(vect_key[11]!=0)
{
read_tast();
}
ClearLCD();
DelayMs(2);
//afisare pe display a mesajul de asteptare a cardului
ComandOut(0x80);
for(t=0;t<15;t++)
CharOut(txt_card[t]);
ComandOut(0xC0);
for (t=15;t<24;t++)
CharOut(txt_card[t]);
CREN=0;CREN=1;
Number_of_persons++;
receive_nurse_key:
cardul=0;
cardul_temp=0;
//asteptare card prin citirea datelor de la modulul serial
while(ReadByteFromSerial()!=0xBB)
while(ReadByteFromSerial()!=0xAA);
for(t=0;t<3;t++)
{
tempi=ReadByteFromSerial();
cardul+=tempi;
cardul<<=8;
}
tempi=ReadByteFromSerial();
cardul+=tempi;
//daca s-a citit cardul trebuie sa existe confirmare ca s-a citit bine si se mai asteapta de 3 ori codul de card
while(ReadByteFromSerial()!=0xBB)
while(ReadByteFromSerial()!=0xAA);
for(t=0;t<3;t++)
{
tempi=ReadByteFromSerial();
cardul_temp+=tempi;
cardul_temp<<=8;
}
tempi=ReadByteFromSerial();
cardul_temp+=tempi;
//daca codurile primite de 4 ori nu sunt identice se revine la prima citire a cardului
//si se astepta din nou
if (cardul!=cardul_temp) goto receive_nurse_key;
//daca codurile citite sunt identice se memoreaza cardul in epromul extern
stat=WriteByteTo24C257(((number_of_persons*20)+16), cardul>>24);
stat=WriteByteTo24C257(((number_of_persons*20)+17), cardul>>16);
stat=WriteByteTo24C257(((number_of_persons*20)+18), cardul>>8);
stat=WriteByteTo24C257(((number_of_persons*20)+19), cardul);
//stergere ce era afisat pe LCD si afisare mesajul de confirmare a salvarii
ClearLCD();
DelayMs(2);
ComandOut(0x80);
for(t=0;t<13;t++)
CharOut(txt_ok[t]);
ComandOut(0xC0);
for(t=13;t<20;t++)
CharOut(txt_ok[t]);
DelayMs(250);
DelayMs(250);
DelayMs(250);
//asteptare sa nu mai fie apasat butonul de OK
while(vect_key[11]!=0)
{
read_tast();
}
//daca s-a introdus doar un card fara nume desi a fost memorat, la urmatoarea scriere se va suprascrie peste ultima pozitie
for(t=0;t<16;t++)
if (nume[t]!=' ') break;
if(t==16)
{
number_of_persons-=1;
eeprom_write(0x07,number_of_persons);
}
}
ClearLCD();
DelayMs(2);
TMR1ON=1;
}
Anexa 2. Coduri sursă folosite de dispozitivului de salon
Rutinele de citire a cardurilor RFID
unsigned char HaveNextCard(unsigned int timeout)
{
//unsigned char j;
unsigned char isvalid=0;
unsigned int time;
status &= ~DATA_READY;// initiere receptie-> variabila status ca spune cand sa primit un sir de biti
INTE = 1; //activare intreruperea externa pentru urmatoarea achizitie
cont = 0;
if (timeout==0) time=0xFF;// daca timeout este 0 se ramane in rutina pana la primirea unui card valid
else time=timeout;
while(cont<time)//cat timp nu sa terminat timpul de asteptare se incearca sa citesc RFID
{
cntFullLoop = 0;
while (++cntFullLoop!=0x17) continue;
if (status & DATA_READY)// s-a primit un sir de date de lungime valida
{
isvalid=ProcessDataStream();// procesare datele
if(isvalid)
{
lastCardId = cardId;
INTE=0;
//ledVerde = 1;ledRosu = 0;
return 1;
}
else// este un sir de date dar nu reprezinta cod de card valid
//asteptare un nou sir de date
{
status &= ~DATA_READY;
INTE = 1;
isvalid=0;
}
}
if(timeout==0) cont=0;// daca timeout este 0-> asteptare pana am card valid
cont++;
}
INTE=0;
return 0;
}
unsigned char ProcessDataStream(void)
{
unsigned int i;
unsigned char result = ParseStreamCRC5();// verificare codul de detectie a erorilor
if (result)//daca codul este bun-> impachetare datele intr-o singura variabila
{
for (i=0; i<5; i++)
{
if(i>0)
cardId = (cardId << 8) + hexCode[i];
}
}
return result;
}
unsigned int ParseStreamCRC5(void)
{
unsigned char i, j, k, i5, n, data, parity, bitData, colParity;
colParity = 0;
parity = 0;
n = 0;
j = 0;
k = 0;
i5 = 0;
data = 0;
for (i=9; i<64; i++)
{
j = i >> 3; //byte number
k = 7 – (i & 0x07); //bit number within byte
bitData = (proxy_data[j] & (1<<k)) ? 1 : 0;
parity ^= bitData;
i5++;
if (i5 % 5)
{
data <<= 1;
data += bitData;
}
else
{
if (n==10)
return (colParity ^ data)==0x00; //return colum parity status
//return 1;
else if (parity)
return 0; //row parity error
k = n >> 1;
if (n & 0x01)
hexCode[k] = (hexCode[k] << 4) | data;
else
hexCode[k] = data;
colParity ^= data;
n++;
data = 0;
}
}
return 0; //this is a dummy return; it shouldn't get here
}
…….
if(INTF&&INTE)// daca este intrerupere externa si intreruperea este activata
{
TMR0 = 0xD9;// setare timer si asteptare pana acesta da overflow
while(TMR0) continue;
bitstate = pData;
INTEDG = !pData;
if(cnt==8)//daca sunt 8 biti valizi se memoreaza in vectorul proxy_data si se trece la urmatoarea pozitie in vector pentru citirea urmatorilor 8 biti
{
if (k==0 && !(code==0xFF && bitstate))
cnt–;//just wait for START sequence (9bit of 1) FF byte and one extra 1 bit
else
{
proxy_data[k] = code;
if (proxy_data[k] != previous_data[k])
status &= ~DATA_STABILE;
k++;
if(k==8)
{
if (status & DATA_STABILE) //if we have two consecutive streams identical, then data is stabile
{
status |= DATA_READY;
INTE = 0; //disable external interrupt
INTF = 0;
code = 0;//cnt = 0;
return;
}
status |= DATA_STABILE;
}
previous_data[k-1] = proxy_data[k-1];
k %= 8;
code = 0;cnt = 0;
}
}
code = (code << 1) + bitstate;
cnt++;
INTF = 0;
}
………….
if(INTF&&INTE)// daca am intrerupere externa si intreruperea este activata
{
TMR0 = 0xD9;// setez timerul si astept pana acesta da overflow
while(TMR0) continue;
// bun data in variaila si schib frontul pe care va fi sezizata intreruperea
bitstate = pData;
INTEDG = !pData;
if(cnt==8)//daca am 8 biti valizi ii memorez in vectorul proxy_data si trec la urmatoarea pozitie in vector pentru citirea urmatorilor 8 biti
{
if (k==0 && !(code==0xFF && bitstate))
cnt–;//just wait for START sequence (9bit of 1) FF byte and one extra 1 bit
else
{
proxy_data[k] = code;
if (proxy_data[k] != previous_data[k])
status &= ~DATA_STABILE;
k++;
if(k==8)
{
if (status & DATA_STABILE) //if we have two consecutive streams identical, then data is stabile
{
status |= DATA_READY;
INTE = 0; //disable external interrupt
INTF = 0;
code = 0;//cnt = 0;
return;
}
status |= DATA_STABILE;
}
previous_data[k-1] = proxy_data[k-1];
k %= 8;
code = 0;cnt = 0;
}
}
code = (code << 1) + bitstate;
cnt++;
INTF = 0;
}
………..
Rutina de citire a telecomenzilor fara fir:
void get_prod_code(unsigned int timeout)
{
unsigned char conn;
unsigned int time,timeunu;
unsigned int cntlp;
//unsigned char time_temp;
if(timeout==0) timeunu=0xFF;// daca timeout=0 nu mai conteaza limita de timp-> asteptare o telecomanda
else timeunu=timeout;
data_teste=0;// variabila in care va contine codul telecomenazii
flag_gata=0;
cntlp=0;
conn=0;
time=0;
while((flag_gata!=1)&&(time<timeunu))//cat timp nu s-a primit cod valid se citesc datele receptionate
{
while(RECV==0)//inainte de o receptie valida va fi mereu 0 logic pe intrare
{/
if((data_teste!=0)&&(cntlp==0xAA)) {cntlp=0;break;
}
if (cntlp==0x6AA) {cntlp=0;goto end;//daca s-a depasit timpul alocat citirii telecomenzilor fara fir se iese din functie
}
cntlp++;
}
DelayUs(171);//255
if(RECV==1)// 1 logic pe intrare insemna ca exista o transmisie valida
{
DelayUs(255);
DelayUs(255);
if(RECV==1) //bit o in transmisie
{
data_teste<<=1;
conn++;
if (conn==24)
{
conn=0;
flag_gata=1;
}
}
else// bit 1 in transmisie
{
data_teste<<=1;
data_teste|=1;
conn++;
if (conn==24)
{
conn=0;
flag_gata=1;
}
}
DelayUs(250);
DelayUs(250);
if(RECV==1)//din protocolul de comunicatie rezulta ca daca un numar de usec este 1 pe intrare inseamna ca este eroare
{
data_teste=0;
conn=0;
flag_gata=0;
}
else{cntlp=0;
}
}//end if(RECV==1)
else//am eroare
{
data_teste=0;
conn=0;
flag_gata=0;
}
if(flag_gata==1) //daca saterminat receptia unui string valid se asteapta ca pinul de intrare sa semnaleze o noua transmisie
{ //time_temp=time;
while(RECV==0)
{
if (timeout==0) time=0;
else time=time+0x01;
if (time>=timeunu) break;
}
DelayUs(255);
DelayUs(250);
}
if (timeout==0) time=0;
else time++;
}//end while data!=cod producator
end:
cntlp=0;
}
Rutina trimitere coduri catre dispozitivul central
void Transmit_to_master(unsigned char pat,unsigned long asistenta,unsigned char mod)
{
unsigned char id_salon_tempor;
unsigned char lrt;
unsigned char trt;
unsigned char hkt=0;
unsigned char pac_card_send1;
unsigned long id_producer=0x4D4F53;
unsigned long temporary;
INTE=0;
// pentru a trimite codurile trebuie ca "linia sa fie libera"
//pentru aceasta cat timp am date pe modulul de receptie se asteapta
while(RECV==0)
{hkt++;
if (hkt==0xFF) break;
DelayUs(50);
}
if (hkt!=0xFF)
hkt=0;
while(RECV==1)
{hkt++;
if (hkt==0xFF) break;
DelayUs(100);
}
if (hkt!=0xFF)
for (hkt=0;hkt<3;hkt++)
{ data_teste=0;
get_prod_code(0xFF);
if ((data_teste&0x00FFFFFF)!=0) hkt=0;
}
}
//asteptarea a luat sfarsit si se incep trimiterea
// setare transciever pe transmisie
rx_to_tx();
//incepere transmisia cu bitii de sincronizare
for (hkt=0;hkt<2;hkt++)
{
temporary=id_producer;
id_salon_tempor=0x1A;
pac_card_send1=pat;
for(trt=0;trt<10;trt++)
{
RA3=1;
DelayUs(5);
RA3=0;
DelayUs(5);
}
DelayMs(2);
//trimitere codul de producator
for (trt=0;trt<24;trt++)
{
RA3=1;
if( (temporary&0x800000)==0)
{
DelayMs(1);
RA3=0;
DelayUs(250);
DelayUs(70);
}
else
{
DelayUs(250);
DelayUs(70);
RA3=0;
DelayMs(1);
}
temporary<<=1;
}
RA3=1;
DelayUs(250);
RA3=0;
DelayMs(2);
//trimitere id salon
for(trt=0;trt<8;trt++)
{ RA3=1;
if((id_salon_tempor&0x80)==0)
{
DelayMs(1);
RA3=0;
DelayUs(250);
DelayUs(70);
}
else
{
DelayUs(250);
DelayUs(70);
RA3=0;
DelayMs(1);
}
id_salon_tempor<<=1;
}//sf cod salon
RA3=1;
DelayUs(250);
RA3=0;
DelayMs(2);
if (mod==1)//transmitere cod pat
{
for(lrt=0;lrt<24;lrt++)//24 de 0;
{
RA3=1;
DelayMs(1);
RA3=0;
DelayUs(250);
DelayUs(70);
}
for(lrt=0;lrt<8;lrt++)//cod pat
{
RA3=1;
if((pac_card_send1&0x80)==0)
{
DelayMs(1);
RA3=0;
DelayUs(250);
DelayUs(70);
}
else
{
DelayUs(250);
DelayUs(70);
RA3=0;
DelayMs(1);
}
pac_card_send1<<=1;
}
RA3=1;
DelayUs(150);
RA3=0;
DelayMs(2);
}
else //transmitere cod nurse
{
temporary=asistenta;
for(lrt=0;lrt<32;lrt++)
{
RA3=1;
if((temporary&0x80000000)==0)
{
DelayMs(1);
RA3=0;
DelayUs(250);
DelayUs(70);
}
else
{
DelayUs(250);
DelayUs(70);
RA3=0;
DelayMs(1);
}
temporary<<=1;
}
}
RA3=1;
DelayUs(150);
RA3=0;
DelayMs(2);
}
//dupa terminarea transmisiei se asteapta revenirea trasncieverului la starea de receptie
tx_to_rx();
}
Anexa 3. Schema electrica dispozitiv salon
Copyright Notice
© Licențiada.org respectă drepturile de proprietate intelectuală și așteaptă ca toți utilizatorii să facă același lucru. Dacă consideri că un conținut de pe site încalcă drepturile tale de autor, te rugăm să trimiți o notificare DMCA.
Acest articol: Sistem Alerta a Asistentelor In Spitale (ID: 163473)
Dacă considerați că acest conținut vă încalcă drepturile de autor, vă rugăm să depuneți o cerere pe pagina noastră Copyright Takedown.
