Proiectarea Unei Aplicatii Ecu

Cuprins

Introducere

În această lucrare am realizat partea de comandă pentru un lift la o parcare auto. Interfața este realizată pe un PC care preia comanda utilizatorului și o transferă unui controller C163, utilizând comunicația serială. Controllerul se ocupă cu execuția comenzii recepționate prim comanda celor 2 motoare pas cu pas. Interfața de pe PC este realizată în C++ Builder 6. Din aplicație aleg la ce nivel doresc să mut mașina, apăsând butonul corespunzător nivelului dorit. Interfața din C++ Builder 6 comunică cu microcontrollerul C163 prin intermediul interfeței seriale RS232. Microcontrollerul C163 trimite comenzile de la interfață la motoarele pas cu pas, care vor muta efectiv mașina de la nivelul actual la nivelul dorit. Liftul conține 2 motoare pas cu pas, un motor (notat M1) care mută rampa în sus și în jos, iar un motor (notat M2) care mută rampa în față(ieșire) și în spate(intrare).

În ceea ce privește comunicația între PC și microcontroller am ales să transmit informațiile grupate într-un pachet, deoarece comanda care trebuie să o trimit la controller poate fi mai mare decât un octet și am vrut să pot să verific și corectitudinea informaților transmise.

La M2 – motorul care mută rampa în față(ieșire) și în spate(intrare) am întâmpinat niste probleme, doarece când îl comandam, punea sursa în protecție, consumând curent mai mare, fapt care ducea la scaderea tensiuni de la 25 V la 5-6 V.

Mi-a plăcut faptul că la această temă am putut să lucrez cu un microcontroller pe care

l-am folosit și într-un proiect, la un curs opțional, având avantajul de a cunoaște microcontrollerul.

Personal mi-a placut din totdeuna ca teoria să fie pusă și in practică. Astfel cu ajutorul unei machete de laborator și cu ajutorul microcontrollerului C163, am reușit să pun în practică ideea de parcare auto pe mai multe nivele.

Parte teoretica

Controllerul C163

Rezumatul caracteristicilor de bază

C163 este un reprezentant îmbunătățit al familiei Siemens de microcontrollere pe 16-biți CMOS pe un singur chip. Combină performanța superioară CPU (până la 10 milioane de instructiuni pe secundă) cu funcționalitatea ridicată din partea perifericelor.

Prezentare generală a arhitecturi

Arhitectura C163 combină avantajele de la procesoarele RISC și CISC într-un mod foarte bine echilibrat. Suma caracteristicilor care sunt combinate rezultă într-un microcontroller de înaltă performanță, care este alegerea potrivită nu numai pentru aplicațiile de astăzi, dar și pentru provocările inginerie pe viitor. C163 integrează un nucleu CPU puternic și un set de unități periferice într-un singur cip, de asemenea, conectează unitățile într-un mod foarte eficient.

Concepte de bază CPU și Optimizări

Nucleul CPU constă în instrucțiuni pipeline pe patru nivele, o unitate aritmetico-logică pe 16 biți (ALU) și regiștri de funcții speciale. Se asigura hardware suplimentar pentru o unitate separată de inmulțire și împărțire, un generator mască de biți.

Pentru a satisface cererea pentru o mai mare performanță și flexibilitate, o serie de domenii au fost optimizate în nucleul procesorului. Blocurile funcționale din nucleul procesorului sunt controlate de semnale de instrucțiuni de decodificare logică. Acestea sunt rezumate mai jos, și sunt descrise în detaliu în secțiunile ce urmează:

1) Lățime mare de bandă pentru instrucțiuni / execuție rapidă

2) Funcție pe 8 biți și unitatea aritmetico-logică pe 16 biți

3) Procesare extinsă pe biți și control periferic

4) Performanță înaltă pentru prelucrarea instrucțiunilor de salt, apel și bucle

5) Formate de instrucțiuni consistente și optimizate

6) Structură de întreruperi cu priorități multiple programabile

Lățime mare de bandă pentru instrucțiuni / execuție rapidă

Având în vedere dispozițiile hardware, cele mai multe dintre instrucțiunile C163 pot fi executate într-un singur ciclu mașină, care necesită 100 ns la un ceas CPU de 20 MHz. De exemplu, shiftarea și rotirea instrucțiuni sunt întotdeauna procesate în cadrul unui ciclu mașină, independent de numărul de biți care trebuie shiftat.

Instrucțiunile de salt , înmulțire și împărțire în mod normal au nevoie de mai mult de un ciclu mașină. Aceste instrucțiuni, cu toate acestea, au fost de asemenea optimizate. De exemplu, instrucțiunile de salt au nevoie doar de un ciclu mașină suplimentar, atunci când se face un salt, și cele mai multe salturi făcute în bucle nu necesită cicluri mașină suplimentare deloc, din cauza așa numitului "Jump Cache". Durata ciclului de instrucțiune a fost redus dramatic prin utilizarea pipeline. Această tehnică permite CPU-ului să proceseze porțiuni din mai multe etape de instrucțiuni secvențial în paralel. Următoarele patru etape pipeline asigură echilibrarea optimă pentru CPU:

FETCH: În această etapă, o instrucțiune este adusă din ROM-ul intern sau RAM sau din memoria externă, în funcție de valoarea IP curentă.

DECODE: În această etapă, instrucțiunea adusă anterior este decodificată și operanzi necesari sunt aduși.

EXECUTE: În această etapă, operația specificată se face pe operanzi aduși anterior.

WRITE BACK: În această etapă, rezultatul este scris în locația specificată.

Dacă această tehnică nu ar fi fost utilizată, fiecare instrucțiune ar necesita patru cicluri mașină. Aceasta a crescut performanța, permitând unui număr mai mare de instrucțiuni și întreruperi să fie procesate.

Funcție pe 8 biți și unitatea aritmetico-logică pe 16 biți

Toate operațiile aritmetice și logice standard sunt realizate într-o unitate ALU pe 16 biți. În plus, pentru operațiunile pe octeți, semnalele sunt furnizate de biți șase și șapte ale rezultatului ALU pentru a seta corect fanioanele de condiție. Aritmetica de precizie multiplă este asigurată printr-un semnal "carry-in" pentru ALU din porțiunile calculate anterior de operația dorită.

Cele mai multe blocuri de execuție interne au fost optimizate pentru a efectua operații pe 8 biți sau 16 biți. După ce pipeline-ul a fost umplut, o instrucțiune este executată într-un ciclu mașină, cu excepția înmulțiri și împărțiri.

Un set de fanioane se actualizează automat în PSW după fiecare operație aritmetică, logică, shiftare, sau mișcare. Aceste fanioane permit salturi de condiții specifice. Aceste fanioane sunt, de asemenea, conservate în mod automat de către CPU la intrarea într-o rutină de întrerupere.

Procesare extinsă pe biți și control periferic

Un număr mare de instrucțiuni a fost dedicat procesări pe biți. Aceste instrucțiuni oferă un control eficient, îmbunătățind totodată manipularea datelor și testarea de periferice. Spre deosebire de alte microcontrollere, aceste instrucțiuni oferă acces direct la doi operanzi din spațiul adresabil pe biți fără a mai fi nevoie să îi mutăm în fanioane temporare.

Aceleași instrucțiuni logice disponibile pentru cuvinte și octeți sunt de asemenea suportate și de biți. Acest lucru permite utilizatorului să compare și să modifice un bit de control pentru un periferic într-o singură instrucțiune.

Performanță înaltă pentru prelucrarea instrucțiunilor de salt, apel și bucle

Datorită procentului ridicat de salt în aplicațiile pentru controller, instrucțiunile de salt au fost optimizate pentru a solicita un ciclu mașină în plus numai atunci când se face un salt. Acest lucru este pus în aplicare de către precalcularea adresei țintă în timpul decodificări instrucțiunii. Pentru a reduce timpul necesar execuției în buclă, au fost prevăzute trei îmbunătățiri:

– Prima soluție oferă execuția unui salt într-un ciclu mașină după prima iterație a unei bucle. Astfel, doar un singur ciclu mașină se pierde în timpul executării întregii bucle. Nu sunt necesare instrucțiuni speciale pentru a efectua bucle, și buclele sunt detectate automat în timpul executării instrucțiunilor de salt.

– A doua îmbunătățire permite buclei să detecteze sfârșitul unui tabel și evită folosirea a două instrucțiuni de comparare încorporate în bucle. Plasează cel mai mic număr negativ la sfârșitul tabelului specificat, și face saltul dacă nu a fost găsită această valoare sau valoarea de comparat. În caz contrar, bucla este terminată dacă oricare dintre condiți a fost îndeplinită. Condiția terminală poate fi apoi testată.

– A treia îmbunătățire a buclei oferă o soluție mai flexibilă decât descreșterea și trecerea peste instrucțiunea zero, care se găsește în alte microcontrolere. Prin utilizarea instrucțiuni de comparare și creștere sau descreștere, utilizatorul poate face comparați pentru orice valoare. Acest lucru permite contoarelor din buclă să acopere orice interval. Acest lucru este deosebit de avantajos în căutarea prin tabele.

Salvarea stări sistemului se face automat pe stiva internă a sistemului evitând utilizarea de instrucțiuni pentru a salva starea la intrare și la ieșire din intrerupere sau rutină trap. Instrucțiunile de apel împing valoarea indicatorului de instrucțiuni pe stiva sistemului, și necesită același timp de execuție ca și instrucțiunea de salt.

Instrucțiunile au fost, de asemenea prevăzute să suporte salturi indirecte și de apel. Suportă punerea în aplicare a multiplelor cazuri de salt în macrourile de asamblare si limbaje de nivel înalt.

Formate de instrucțiuni consistente și optimizate

Pentru a obține performanța optimă într-o construcție pipeline, un set de instrucțiuni a fost proiectat, care încorporează concepte din setul redus de instrucțiuni de calcul (RISC). Aceste concepte permit în primul rând o decodificare rapidă a instrucțiunilor și operanzilor în timp ce reduce blocajele pipeline. Aceste concepte, cu toate acestea, nu împiedică utilizarea instrucțiunilor complexe, care sunt cerute de utilizatori microcontroller-ului. Următoarele obiective au fost folosite pentru a proiecta setul de instrucțiuni:

– Furnizarea de instrucțiuni puternice, pentru a efectua operațiuni care necesită în prezent secvențe de instrucțiuni și sunt utilizate frecvent. Trebuie evitate transferurile în și din regiștri temporari, cum ar fi acumulatori și biți de transport. Să îndeplinească sarcini în paralel, cum ar fi salvarea stari la intrarea în rutina de întrerupere sau subrutină.

– Evită scheme de codare complexe, prin plasarea operanzilor în domenii coerente pentru fiecare instrucțiune. De asemenea, evita moduri de adresare complexe, care nu sunt utilizate în mod frecvent. Aceasta scade timpul de decodare al instrucțiunilor, simplificând de asemenea, dezvoltarea de compilatoare și asamblori.

Tipurile de operanzi posibili sunt: biți, octeți și cuvintele. Instrucțiunile specifice suportă conversia (extensia) biților în cuvinte. O varietate de moduri de adresare directe, indirecte sau imediate sunt furnizate pentru a specifica operanzii necesari.

Structură de întreruperi cu prioritați multiple programabile

Următoarele îmbunătățiri au fost incluse pentru a permite prelucrarea unui număr mare de surse de întrerupere:

– Controller periferic de evenimente (PEC): Acest controller este folosit pentru a executa o parte din cererile de întrerupere. Se evită intrarea și ieșirea din întreruperi sau rutine trap prin efectuarea unui singur ciclu de transfer de date (octet sau cuvânt) între oricare două locații din segment 0. Cu o creștere opțională, a sursei sau a indicatorului destinație PEC. Doar un singur ciclu este "furat" din activitatea curentă a procesorului pentru a efectua un serviciu PEC.

– Controller de întreruperi cu priorități multiple: acest controller permite ca toate întreruperile să fie plasate în orice ordine. Întreruperile pot fi de asemenea grupate, lucru care oferă utilizatorului posibilitatea de a preveni sarcini prioritare similare să se întrerupă reciproc. Pentru fiecare dintre posibilele surse de întrerupere există un registru de control separat, care conține un fanion pentru cererea de întrerupere, un fanion care validează întreruperea și un câmp de biți care specifică prioritatea întreruperi. Odată ce a fost admisă de către CPU, o rutină de întrerupere poate fi întreruptă doar de o cerere de întrerupere cu prioritate mai mare. Pentru procesarea standard de întreruperi, fiecare dintre posibilele surse de întrerupere au o locație vector dedicată.

– Seturi multiple de regiștri: Această funcție permite utilizatorului să specifice până la șaisprezece regiștri generali dispuși oriunde în memoria RAM internă. O singură instrucțiune mașină de un ciclu permite schimbarea seturilor de regiștri de la o sarcină la alta.

Resursele sistemului de pe chip

Controller-ul C163 asigură un număr de resurse de sistem puternice, implementate în jurul procesorului. Combinația CPU-ului și a acestor resurse rezultă în performanțe mari ale membrilor acestei famili de controllere.

Controller-ul periferic de evenimente (PEC) și controller-ul de întreruperi

Controller-ul periferic de evenimente răspunde la o cerere de întrerupere cu un singur transfer de date (cuvânt sau octet), care consumă doar un ciclu de instrucțiune și nu necesită salvarea și restabilirea stări mașinii. Fiecare sursă de întrerupere este prioritizată în fiecare ciclu mașină în blocul de control al întreruperilor. Dacă este selectat serviciu PEC, un transfer PEC este pornit. În cazul în care este solicitat serviciul CPU de întrerupere, nivelul actual de prioritate din registrul PSW este testat pentru a determina dacă întreruperea în curs de tratare este mai prioritară. Atunci când o întrerupere este recunoscută, starea curentă este salvată pe stiva internă a sistemului și CPU-ul face salt la adresa vectorului specificat de sistem pentru perifericul care a generat întreruperea.

PEC-urile conțin un set de SFRs care stochează valoarea de numărat și biți de control pentru opt canale de transfer de date. În plus, PEC folosește o zonă dedicată de RAM, care conține adresele sursă și destinație. PEC este controlat similar cu orice alt periferic prin SFRs conținând configurația dorită a fiecărui canal.

Un contor individual de transfer PEC este implicit decrementat pentru fiecare serviciu PEC, excepție facând modul de transfer continuu. Când acest contor ajunge la zero, o întrerupere standard este realizată la locația vector legată de sursa corespunzătoare. Serviciile PEC sunt folosite, de exemplu, pentru a muta conținutul regiștrilor în / dintr-un tabel de memorie. C163 dispune de 8 canale PEC, fiecare dintre acestea oferă o astfel de capabilitate de transfer de date bazate pe întreruperi rapide.

Zonele de memorie

Spațiul de memorie al C163 este configurat într-o arhitectură Von Neumann, ceea ce înseamnă că memoria cod, memorie de date, regiștri și porturile IO sunt organizate în același spațiu de adrese liniar care acoperă până la 16 MBytes. Întregul spațiu de memorie poate fi accesat octet cu octet sau la nivel de cuvânt. Porțiuni particulare ale memoriei s-au făcut direct adresabile la nivel de bit.

RAM-ul intern pe 16 biți (IRAM) oferă acces rapid la regiștri generali (GPRS), date de utilizator (variabile) și stivă de sistem. RAM-ul intern poate fi de asemenea utilizat pentru cod. Marimea RAM-ului intern este de 1KByte la C163.

CPU dispune de un registru context alcatuit din până la 16 cuvinte și / sau octeți GPRS , care sunt situati fizic în zona RAM. Un registru indicator de context (CP) determină adresa de bază a setului de regiștri activ pentru a fi accesați de către CPU la un moment dat. Numărul seturilor de regiștri este limitat doar de spațiul disponibil din RAM-ul intern.

O stivă de sistem de până la 1024 de cuvinte este furnizată pentru a stoca date temporare. Stiva de sistem este de asemenea situată în zona RAM, și aceasta este accesată de către CPU prin registru indicator al stivei (SP) . Două SFRs separate, STKOV și STKUN, sunt implicit comparate cu valoarea indicatorului de stivă pentru fiecare acces la stivă, pentru detectarea eventoalelor depașiri ale limitelor stivei(cea superioară și cea inferioară).

Pentru stocare de cod cât și pentru stocarea de date se mai poate folosi un ROM intern (opțional). Această zonă de memorie este conectată la CPU prin intermediul unei magistrale pe 32 de biți. Astfel, două cuvinte de instrucțiuni pot fi preluate într-un singur ciclu mașină. Execuția programului din ROM-ul este cel mai rapid dintre toate alternativele posibile.

Pentru regiștri de funcții speciale sunt rezervați 1024 de octeți din spațiul de adrese. In mod normal regiștri de funcții speciale standard (SFR) utilizează 512 octeți, în timp ce regiștri de funcții speciale extinse (ESFR) utilizează ceilalți 512 octeți. SFR și ESFR sunt regiștri la nivel de cuvânt, care sunt utilizate pentru controlul și monitorizarea funcțiilor diferitelor unități de pe chip.

Generatorul de ceas oferă semnalul de ceas de bază care controlează toate activitățile hardware ale controller-ului.

C163 oferă un Oscilator Watchdog (OWD), care monitorizează semnalul de ceas generat de oscilatorul de pe chip în modul direct sau în modul prescalat.

Blocurile periferice de pe chip

Controllerul C163 separă în mod clar perifericele de nucleu. Această structură permite numărului maxim de operațiuni să fie efectuate în paralel și permite perifericelor să fie adăugate sau eliminate din membrii familiei fără modificări ale nucleului. Fiecare bloc funcțional prelucrează datele în mod independent și comunică informațiile pe magistrale comună. Perifericele sunt controlate de datele scrise în regiștri de funcții speciale corespunzătoare(SFRs).

Perifericele controllerului C163 sunt:

• Două blocuri timer de uz general (GPT1 și GPT2)

• O interfață serială asincronă / sincronă (ASC0)

• O interfață serială sincronă de mare viteză (SSP)

• Un timer Watchdog

• 7 porturi de intrare/ieșire cu un total de 77 linii de I/O

Interfețele periferice

Perifericele de pe chip au, în general, două tipuri de interfețe, o interfață cu CPU și o interfață pentru hardware-ul extern. Comunicarea între CPU și periferice se realizează prin regiștrii speciali de funcții (SFRs) și întreruperi. SFRs servesc pe post de regiștri de control / stare și de date pentru periferice. Cererile de întrerupere sunt generate de periferice pe baza unor evenimente specifice care apar în timpul funcționării lor.

Pentru interfațarea cu hardware-ul extern, se folosesc pini specifici ai porturilor paralele, când o funcție de intrare sau de ieșire a fost selectată pentru un periferic. În acest timp, pinii portului sunt controlați de periferic (atunci când sunt utilizați ca ieșiri) sau sunt controlați de hardware-ul extern care controlează perifericul (atunci când sunt utilizați ca intrări). Aceasta se numește funcție alternativă (de intrare sau de ieșire) a unui pin din port, în contrast cu funcția sa de uz general ca pin de IO.

Sincronizarea perifericelor

Funcționarea internă CPU și a perifericelor se bazează pe ceasul CPU (fCPU). Oscilatorul de pe chip derivă ceasul CPU din cristalul său sau de la semnalul de ceas extern. Semnalul de ceas, care se gasește la periferice este independent de semnalul de ceas care alimentează procesorul. În timpul modului de repaus semnalul de ceas al procesorului este oprit în timp ce perifericele își continuă funcționarea lor. SFRs perifericelor pot fi accesate de către CPU odată pe stare. Atunci când un SFR este scris de software și în același timp încearcă să fie modificat de către periferic, operațiunea software de scriere are prioritate.

Porturile Paralele

C163 oferă până la 77 de linii IO, care sunt organizate în șase porturi de intrare/ieșire și un port de intrare. Toate liniile de port sunt adresabile la nivel de bit, și toate linii de intrare/ieșire pot fi programabile ca intrări sau ca ieșiri prin intermediul regiștrilor de direcție. Porturile IO sunt porturi bidirecționale adevărate, care sunt trecute în stare de înaltă impedanță, când sunt configurate ca intrări. Driverele de ieșire a trei porturi IO pot fi configurată (pin cu pin) pentru operați de împingere/tragere sau pentru operația “open-drain” prin regiștri de control. În timpul resetări interne, toți pinii portului sunt configurați ca intrări.

Comunicația serială

Comunicația serială cu alte microcontrollere, procesoare, terminale sau componente periferice externe este asigurată de două interfețe seriale:

– interfața seriala asincronă/sincronă(ASC0)

– interfața serial sincronă de mare viteză (SSP în C163).

ASC0 suportă comunicare asincronă full-duplex de până la 625 de kBaud și comunicare sincronă semi-duplex de până la 2,5 MBaud la un ceas CPU de 20 MHz.

Un generator rată de transfer dedicat permite să selecteze toate ratele de transfer standard fără a mai fi nevoie de un reglaj oscilator suplimentar. Pentru transmisie, recepție și detecție de erori avem 4 vectori de întreruperi separați. În modul asincron, avem cadre de 8 sau 9 biți de date, care sunt transmise sau primite, precedate de un bit de start și terminate cu unul sau doi biți de stop. Pentru o comunicare multiprocesor, a fost inclus un mecanism pentru a distinge adresele de octeți cu date (date pe 8 biți, plus bitul de trezire).

În modul sincron, ASC0 transmite sau primește octeți (8 biți) sincron cu un ceas de shiftare, care este generat de ASC0. ASC0 shiftează mereu prima oara bitul cel mai puțin semnificativ. Se asigură și o obțiune cu feedback, care se folosește pentru testare.

A fost inclus hardware suplimentar pentru a detecta erorile, în scopul de a crește fiabilitatea transferurilor de date. Un bit de paritate poate fi generat automat pe transmisie sau poate să fie verificat pe recepție. Avem un circuit specializat pentru transferurile seriale care detectează cadrele de date care au lipsă biți de stop. O eroare de ritm va fi generată, în cazul în care ultimul caracter primit nu a fost citit din registrul tampon în momentul în care recepția unui nou caracter a fost terminată.

SSP (C163) suportă comunicația sincronă semi-duplex de până la 10 MBaud la un ceas CPU de 20 MHz. Poate fi configurată astfel încât să interacționeaze cu componentele periferice legate în serie. Pentru transmisie, recepție și detecție de erori este furnizat un vector de întreruperi general separat.

Unitațile de timer de uz general (GPT)

Unitățile GPT reprezintă o structură foarte flexibilă timer/numărător multifuncțională care poate fi utilizată în diferite sarcini, cum ar fi calendarul de evenimente și de numărare, impulsuri în lățime, măsurarea factorului de umplere, generarea de impulsuri.

Cele cinci timere pe 16-biți sunt organizate în două module separate, GPT1 și GPT2. Fiecare timer din fiecare modul poate opera independent într-un număr de moduri diferite, sau poate fi concatenat cu un alt timer din același modul.

Fiecare timer poate fi configurat individual pentru unul dintre cele trei moduri de operare de bază, care sunt: timer, timer poartă, și modul numărător. În modul timer, ceasul de intrare pentru un timer este derivat din ceasul CPU intern împărțit de către un prescalar programabil, în timp ce modul numărător permite ca timer-ul să primească semnal de tact extern prin intermediul lui TxIN.

Măsurarea factorului de umplere este susținută în modul timer poartă, în care funcționarea unui timer este controlată de nivelul "poarta" pe pinul extern de intrare TxIN.

Direcția de numărare (sus / jos) pentru fiecare timer este programabilă din software sau poate fi modificate dinamic de un semnal extern (TxEUD) pentru a facilita de exemplu urmărirea poziției.

Timerele nucleu T3(GPT1) și T6(GPT2) au ieșire de tip bistabil(TxOTL) care își schimbă starea lor pe fiecare revărsare/subîncărcare. Starea acestor regiștri poate fi redată pe pinii portului (TxOUT) sau pot fi utilizată intern pentru înlănțuirea timer-ului nucleu cu timer-ele auxiliare respective, rezultând un timer/numărător pe 32/33 de biți pentru a măsura perioade lungi de timp cu înaltă rezoluție.

Diversele funcții de reîncărcare sau de captură pot fi selectate pentru a reîncărca timerele sau captura conținutul timerului, care este declanșat de un semnal extern sau o tranziție selectabilă a lui TxOTL.

Rezoluția maximă a timerelor din modulul GPT1 este de 400 ns la un ceas CPU de 20 MHz. Modulul timer GPT2 asigura un control precis al evenimentelor și măsurarea timpului asigurând o rezoluția maximă de 200 ns la un ceas CPU de 20 MHz.

Timerul Watchdog

Timerul Watchdog reprezintă unul dintre mecanismele de siguranță care au fost implementate pentru a preveni controller-ul să funcționeze defectuos pentru perioade lungi de timp.

Timer-ul Watchdog este întotdeauna activat după o resetare a chipului, și poate fi dezactivat numai în intervalul de timp până la executarea instrucțiuni EINIT (sfârșitul initializări). Astfel, procedura de pornire a chipului este întotdeauna monitorizată. Software-ul trebuie să fie proiectat pentru a deservi Timer Watchdog înainte ca acesta să facă revărsare. În cazul în care, din cauze hardware sau eșecuri legate de software, software-ul nu reușește să facă acest lucru, timer-ul Watchdog face revărsare și generează o resetare hardware internă și trage pinul RSTOUT jos, cu scopul de a permite resetarea componentelor hardware externe.

Timerul Watchdog este un timer pe 16-biți, care primește semnal de ceas CPU împărțit cu 2 sau cu 128. Octetul mai semnificativ al registrului Watchdog poate fi setat la o valoare de reîncărcare prestabilită (stocată în WDTREL), pentru a permite variați viitoare ale intervalului de timp monitorizat. De fiecare dată când este deservit de software-ul aplicației, octetul ridicat al timer-ul Watchdog este reîncărcat. Astfel, intervalele de timp între 25 ms și 420 ms poate fi monitorizată la o frecvența de ceas CPU de 20 MHz.

Microcontroller-ul C163 are un numar de biți protejați de un mecanism hardware special care împiedică modificarea acestor biți de catre accesele software neintenționate.

Organizarea memoriei

Spațiul de memorie al microcontroller-ul C163 este configurat într-o arhitectură "Von Neumann". Acest lucru înseamnă că datele și codul sunt accesate în același spațiu liniar de adrese. Toate zonele de memorie separate fizic, inclusiv memoria ROM internă /Flash (în cazul în care există), RAM-ul intern, zonele regiștrilor de funcții speciale (SFRs și ESFRs), zonele de adresă ale perifericelor integrate XBUS (de exemplu modulul SSP) și memorie externă sunt mapate într-un spațiu de adrese comun.

C163 are un spatiu total de memorie adresabilă de 16 MBytes. Acest spatiu de adrese este grupat în 256 de segmente de 64 de KB fiecare, iar fiecare segment este din nou împărțită în patru pagini de date, fiecare având 16 KB.

ROM-ul intern

C163 poate rezerva o suprafață de adrese de dimensiuni variabile (în funcție de versiune) pentru ROM-ul programabil (organizat ca X * 32) sau memoria Flash. Cei mai puțini semnificativi 32 kbyte din memorie alcătuiesc "Zona ROM internă". Accesul la zona ROM internă la nivel global este activată sau dezactivată prin bitul ROMEN din registrul SYSCON.

Acest bit este setat în timpul resetări, în funcție de nivelul pinului EA, sau poate fi modificat prin software. Dacă este activat, zona ROM internă ocupă cei mai puțini semnificativi 32 kbyte din segmentul 0 sau segment 1. Această mapare ROM este controlată de bitul ROMS1 din registrul SYSCON.

ROM-ul intern/Flash pot fi folosite atât pentru cod (instrucțiuni) cât si pentru depozitare de date (constante, tabele, etc.).

ROM-ul intern nu este adresabil la nivel de bit.

Zona internă RAM și zona SFR

Zona RAM/SFR este situată în pagina de date 3 și asigură accesul la RAM de pe chip (IRAM, organizate ca 1K * 16) și la două blocuri de 512 octeți din registre speciale de funcții (SFRs).

RAM intern servește pentru mai multe scopuri:

• Stivă de sistem (dimensiune programabilă)

• Seturi de regiștri generali(GPRS)

• Ca indicatori sursă și destinație pentru controller periferic de evenimente (PEC)

• pentru variabile și alte date

• pentru cod.

Stiva de sistem

Stiva de sistem poate fi definită în RAM-ul intern. Dimensiunea stivei de sistem este controlată de câmpul de biți STKSZ din registrul SYSCON.

Stiva de sistem este accesată prin registrul indicator de stivă (SP). Stiva crește în jos de la locați de adrese mari spre locati mai mici RAM. Numai accesele la nivel de cuvânt sunt suportate de stiva sistemului. Un registru revărsare de stivă (STKOV) și un registru subîncărcare de stivă (STKUN) sunt prevăzuți pentru a controla limita superioară și inferioară a zonei de stivă selectată.

Regiștri generali

Regiștri generali (GPRS) folosesc un bloc de 16 cuvinte consecutive, în memoria RAM internă. Registrul indicator de context (CP) determină adresa de bază a setului de regiștri activ. Acest set de regiștri poate fi alcătuit din 16 cuvinte (R0, R1, …, R15) și / sau 16 octeți (RL0, RH0, …, RL7, RH7). Cei șaisprezece octeți ai regiștrilor generali sunt mapați pe primele opt cuvinte GPRS.

Spre deosebire de stiva de sistem, un set de regiștri crește de la o locație de adresă inferioră spre o lacație de adresă superioară și ocupă un spațiu maxim de 32 Byte.

Funcțiile CPU, magistrala de adrese, porturi IO și perifericele de pe chip ale microcontroller-ului C163 sunt controlate prin intermediul unui număr de regiștri de funcții speciale. Aceste SFRs sunt aranjate în două zone de 512 octeți.

Spațiu de memorie externă

Microcontroller-ul C163 este capabil de a utiliza un spațiu de adrese de până la 16 MByte. Numai o parte din aceste adrese sunt ocupate de zona de memorie internă. Toate adresele care nu sunt utilizate pentru memoria (ROM sau RAM) sau pentru regiștri pot referi locații de memorie externe. Această memorie externă este accesată prin interfața externă de magistrală a lui C163.

Trecerea intre limitele de memorie

Zonele de memorie sunt bucați ale spațiului de adrese care reprezintă diferite tipuri de memorie. Aceste zone de memorie sunt zonele interne RAM / SFR, ROM intern (dacă există), X-Periferice (dacă sunt integrate) și memoria externă.

Accesarea locațiilor de date secvențiale ale unor domenii care aparțin diferitelor memori nu reprezintă nici o problema. Cu toate acestea, atunci când executăm cod, diferite zone de memorie trebuie să fie schimbate în mod explicit prin instrucțiuni de salt.

Segmentele sunt blocuri contigue de 64 de kByte fiecare. Acestea sunt referite prin indicatorul segment de cod CSP pentru aducerea de cod și printr-un număr de segment explicit pentru date.

În timpul aduceri de cod segmentele nu sunt modificate în mod automat, ci mai degrabă trebuie schimbate în mod explicit. Instrucțiunile JMPS, CALLS și RETS vor face acest lucru.

Paginile de date sunt blocuri contigue de 16 kByte fiecare. Acestea sunt referite prin indicatori de pagină de date DPP3, DPP2, DPP1 și DPP0. Fiecare registru DPP poate selecta una dintre posibilele 1024 de pagini de date. Registrul DPP care este utilizat pentru accesul curent este selectat prin intermediul celor doi biți superiori ai adresei de date pe 16 biți.

Unitatea centrala de procesare(CPU)

Atribuțiile de bază ale procesorului sunt să aducă și să decodifice instrucțiuni, să furnizeze operanzi unității aritmetico-logică (ALU), să efectueze operați asupra acestor operanzi în ALU, și pentru a stoca rezultatele calculate anterior. Deoarece procesorul este motorul principal al controllerului C163, acesta este afectat de anumite acțiuni ale subsistemului periferic.

Din moment ce un pipeline pe patru nivele este implementat în C163, până la patru instrucțiuni pot fi procesate în paralel. Cele mai multe instrucțiuni ale microcontrollerului C163 sunt executate într-un singur ciclu mașină din cauza acestui paralelism.

În timp ce accesele de memorie internă sunt în mod normal efectuate de către CPU, accesele perifericelor externe sau memoriei externe sunt efectuate de un anumit controller extern de magistrală (EBC), care este invocat în mod automat de către CPU ori de câte ori o adresă de cod sau de date se referă la spațiu de adrese externe. Dacă este posibil, procesorul continua să funcționeze în timp ce are loc un acces de memorie extern. În cazul în care date externe sunt necesare, dar nu sunt încă disponibile, sau în cazul în care un nou acces de memorie externă este solicitat de către CPU, înainte ca accesul precedent să fie finalizat, procesorul va fi ținut pe loc de catre EBC până când cererea poate fi satisfăcută.

Unitățile periferice ale microcontroller-ului C163 lucrează aproape independent de CPU, cu un generator de ceas separat. Datele și informațiile de control sunt schimbate între CPU și aceste periferice prin regiștri de funcții speciale (SFRs). Ori de câte ori perifericele au nevoie de o acțiune CPU, controller de întreruperi compară toate cererile de întrerupere ale perifericelor care solicită service și prioritizează una dintre ele. În cazul în care prioritatea operațiunii curente a procesorului este mai mică decât prioritatea cererii periferice selectate, va avea loc o întrerupere.

Practic, există două tipuri de întreruperi:

• întreruperile standard care forțează CPU să salveze starea programului curent și adresa de revenire pe stivă înainte să efectueze saltul la vector de întrerupere.

• Întreruperile PEC care "fură" doar un ciclu mașină din activitatea procesorului curent pentru a efectua un singur transfer de date prin intermediul controllerului periferic de evenimente (PEC).

Erorile de sistem detectate în timpul execuției programului (așa-numitele hardware traps ) sau o întrerupere externă nemascabil, sunt prelucrate ca întreruperi standard cu o prioritate foarte mare.

Spre deosebire de alte periferice, există o legătură strânsă între timerul watchdog și CPU. Dacă este activat, timerul watchdog așteaptă să fie deservit de către CPU într-o perioadă programabilă de timp, în caz contrar timerul watchdog va reseta chipul. Astfel, timerul watchdog poate preveni CPU din a execută cod eronat pentru o perioadă mare de timp. După resetare, timerul watchdog începe numărarea în mod automat, dar poate fi dezactivat prin intermediul softwareului, dacă se dorește.

Pe lângă funcționarea sa normală CPU-ul mai are și următoarele stări particulare:

• Starea de reset: Orice resetare (hardware, software, watchdog) forțează CPU într-o stare activă predefinită.

• starea de repaus: semnal de ceas pentru CPU este oprit, în timp ce ceasurile pentru

periferice continua să funcționeze.

• starea de Oprire: Toate ceasurile sunt oprite.

O tranziție în starea activă a procesorului este forțată de o întrerupere (dacă este în așteptare) sau printr-o resetare (dacă este în starea POWER DOWN/ Oprire).

Manipularea și protecția biților

C163 oferă mai multe mecanisme de manipulare a biților. Aceste mecanisme controlează fanioanele software din cadrul RAM-ului intern, controlează perifericele din chip, prin intermediul biților de control din SFR-uri sau funcții de control IO prin intermediul pinilor de port.

Instrucțiunile BSET, BCLR, BAND, BOR, BXOR, BMOV, BMOVN setează în mod explicit sau resetează anumiți biți. Instrucțiunile BFLDL și BFLDH permit manipularea a 8 biți dintr-un octet la un moment dat. Instrucțiunile JBC și SNEJ setează sau resetează bitul specificat când se face saltul.

Instrucțiunile JB și JNB (de asemenea, instrucțiuni de salt condiționat care se referă la fanioane) evaluează bitul specificat pentru a determina dacă saltul urmează să fie facut.

Toate instrucțiunile care manipulează biți unici sau grupuri de biți, utilizează pe plan intern o secvență de citire-modificare-scriere care accesează tot cuvântul, care conține bitul specificat.

Această metodă are mai multe consecințe:

• Biți pot fi modificați numai în zonele de adrese internă, adică în RAM și SFRs. Locațiile externe nu pot fi folosite cu instrucțiunile pe bit.

Zonele superioare de 256 octeți din SFR, zona ESFR și RAM intern sunt adresabile la nivel de bit , adică aceste biți din registri situate în secțiunile respective pot fi manipulate în mod direct, folosind instrucțiuni de bit. Celelalte SFRs trebuie accesate la nivel de octet / cuvântul.

• Abordarea citire-modificare-scriere poate fi critică cu biți controlați hardware. În aceste cazuri, hardwareul poate schimba anumiți biți în timp ce operațiunea de cititre-modificare-scriere este în curs, caz în care operația de scriere înapoi ar suprascrie noua valoare a bițiilor, generate de hardware. Soluțiile la această problemă sunt:

– protecția hardware implementat

– realizată prin programare specială.

Biți protejați nu pot fi modificați în timpul secvenței de citire-modificare-scriere, adică când hardwarul setează de exemplu. un steag cerere de întrerupere între citire și scriere a secvenței de citire-modificare-scriere. Logica de protecție hardware garantează că numai bitul dorit este afectat de operațiunea de scriere înapoi.

Regiștri CPU de funcții speciale

CPU necesită un set de regiștri de funcții speciale (SFRs) să mențină informațiile stări sistemului, pentru a controla configurația sistemului și a magistralei, pentru operațiunile de înmulțire și împărțire din ALU, segmentarea memoriei cod, paginare memoriei de date, precum și accesarea la regiștri generali și la stiva de sistem.

Registrul de configurare a sistemului – SYSCON

Acest registru adresabil la nivel de bit asigură configurarea generala a sistemului și funcții de control. Valoarea de resetare pentru registrul SYSCON depinde de starea pinilor din PORT0 în timpul resetări.

Starea Procesorului Word – PSW

Acest registru adresabil la nivel de bit reflectă starea actuală a microcontrolerului. Două grupuri de biți reprezintă starea curentă ALU, precum și starea de întrerupere actuală CPU. Un pin separat (USR0) din registrul PSW este furnizat ca un fanion de uz general pentru utilizator.

Stare de întrerupere CPU – IEN, ILVL

Dacă bitul de întrerupere este pornit, acesta activează la nivel global întreruperile (IEN = '1') sau dacă este oprit, le dezactivează la nivel global (IEN = "0") . Câmpul de patru biți al nivelului de întrerupere (ILVL) specifică prioritatea actuală a activității procesorului. Nivelul de întrerupere este actualizat de hardware la intrarea într-o rutină de tratare a întreruperi, dar poate fi modificat prin software, pentru a preveni alte întreruperi să fie recunoscut. În cazul în care o întrerupere de nivel "15" a fost atribuită CPU, aceasta are cea mai mare prioritate posibilă și funcționarea curentă a procesorului nu poate fi întreruptă decât prin hardware traps sau de întreruperile nemascabile externe.

După resetare, toate întreruperile sunt dezactivate la nivel global, iar cea mai mică prioritate (ILVL = 0) este atribuită ca activitate inițială CPU.

Indicatorul de instrucțiune – IP

Acest registru determină adresa de 16-biți a instrucțiunii care este preluată în prezent din segmentul de cod selectat de registru CSP. Registrul IP nu este mapat în spațiu de adrese al lui C163, astfel nu poate fi accesat direct de programator. IP poate, totuși, să fie modificat în mod indirect, prin intermediul stivei, cu ajutorul unei instrucțiuni de întoarcere. Registrul IP este implicit actualizat de CPU pentru instrucțiuni de salt și după operațiunile de aducere de instrcțiuni.

Indicatorul de segment – CSP

Acest registru care nu e adresabil la nivel de bit, selectează segmentul de cod folosit pentru a accesa instrucțiuni în momentul rulării. Cei mai mici 8 biți ai registrului CSP selectează un segment dintre cele 256 de segmente de 64 de KB fiecare, iar cei mai semnificativi 8 biți sunt rezervate pentru o utilizare viitoare.

Indicatori pagina de date – DPP0, DPP1, DPP2, DPP3

Acesți regiștri care nu sunt adresabili la nivel de bit, selectează până la patru pagini diferite de date ca fiind active simultan în momentul rulării. Cei mai puțin semnificativi 10 biți din fiecare registru DPP selectează una dintre cele 1024 de pagini de date de 16 kbyte posibile, iar cei mai semnificativi 6 biți sunt rezervați pentru o utilizare viitoare. Regiștri DPP pot să acceseze întregul spațiu de memorie în pagini de 16 KB fiecare.

Indicatorul de context – CP

Acest registru care nu e adresabil la nivel de bit este folosit pentru a selecta context-ul de regiștri actual. Acest lucru înseamnă că valoarea registrului CP determină adresa primului registru general (GPR) din cadrul setului de regiști curent.

Indicatorul de stivă – SP

Acest registru care nu e adresabil la nivel de bit este folosit să indice partea de sus a stivei interne de sistem(TOS). Registrul SP este decrementat de fiecare dată când datele trebuie să fie puse pe stiva, și este incrementat de fiecare dată când datele trebuie scoase de pe stivă. Astfel, stiva de sistem crește de la locați de memorie mari spre locații de memorie mai mici.

Intreruperile și funcțiile Trap

Arhitectura C163 suporta mai multe mecanisme de răspuns rapid și flexibil la cererile de servicii care pot fi generate din diverse surse interne sau externe ale microcontrollerului.

Aceste macanisme includ:

– Întreruperile normale de procesare

CPU-ul suspendă temporar execuția programului curent și face salt la rutina de serviciu, în scopul de a deservi un dispozitiv care solicită o întrerupere. Starea actuală a programului (IP, PSW și CSP dacă avem segmentarea activă) este salvată pe stivă internă de sistem. Un sistem cu 16 nivele de prioritate permite utilizatorului să specifice ordinea în care trebuie să fie executate întrerupere când există mai multe cereri simultate.

-Prelucrarea întreruperilor prin controller periferic de evenimente (PEC)

O alternativă mai rapidă decât sistemul normal de procesare a întreruperilor este controller periferic de evenimente(PEC). Declanșată de o cerere de întrerupere, PEC efectuează un singur transfer de cuvânt sau octet de date între oricare două locații din segment 0 (de la pagina de date 0 pâna la pagina 3) prin intermediul unuia dintre cele opt canale programabile de servicii PEC. În timpul unui transfer PEC, execuția normală a programului CPU este oprit pentru un ciclu de instrucțiuni. Nu trebuie salvată starea curentă a programului. Aceeași schemă de prioritizare care este utilizată pentru procesarea normală de întreruperi este folosită și de serviciul PEC. Transferurile PEC folosesc cele mai prioritare două niveluri de întreruperi.

– Funcțiile Trap

Funcțiile Trap sunt activate ca răspuns la condițiile speciale care apar în timpul executării instrucțiunilor. O funcție Trap poate fi cauzată extern, de o întrerupere nemascabilă de pe pinul NMI. Mai multe funcții Trap hardware sunt prevăzute pentru rezolvarea condițiilor eronate și excepțiilor care apar în timpul executării unei instrucțiuni. Hardware Trap au întotdeauna prioritate și provoacă o reacție imediată a sistemului. Funcția software Trap este invocată de către instrucțiunea TRAP, care generează o întrerupere software pentru un vector de întrerupere specificat. Pentru toate tipurile de Trap starea programul curent este salvată pe stiva de sistem.

Structura sistemului de întrerupere

Pentru a putea suporta tehnici modulare și coerente de design software, fiecare sursă de întrerupere sau solicitare PEC are un registru separat de control al întreruperi și un vector de întrerupere. Registrul de control conține fanionul cerere de întrerupere, bit-ul de activare al întreruperi și prioritatea întreruperi asociată sursei. Fiecare cerere sursă este activată de un eveniment specific, în funcție de modul de lucru selectat al dispozitivului respectiv. Singurele excepții sunt cele două canale seriale ale microcontroller-ului C163, în cazul în care o cerere de întrerupere generată de o eroare poate fi cauzată de tipuri diferite de erori.

Cu toate acestea, fanioanele de stare specifice, care identifică tipul de eroare, sunt implementate în regiștri de control ai canalelor seriale.

C163 oferă un sistem de vectori de întreruperi. În acest vector de sistem din spațiul de memorie avem rezervate locații specifice pentru funcțiile de resetare, trap și funcțiile de servisare. Ori de câte ori apare o solicitare, CPU face salt la locația care este asociată cu sursa respectivă de întrerupere.

Acest lucru permite identificarea directă a sursei care a cauzat cererea. Singurele excepții sunt hardware trap de clasă B, care au toate același vector de întrerupere. Fanioanele de stare din registrul trap flag (TFR) poate fi apoi folosit pentru a determina care excepție a provocat trapul. Pentru instrucțiunea specială software TRAP, adresa vector este specificată de câmpul operand al instrucțiunii, care este un număr trap de șapte biți.

Procesarea normală PEC și a întreruperilor

În timpul fiecărui ciclu de instrucțiuni una din toate sursele care necesită servis PEC sau întrerupere, este aleasă în funcție de prioritatea întreruperi. Această prioritate a întreruperi și a cereri PEC este programabilă în două niveluri. Fiecare sursă solicitantă poate fi atribuită unei nivel de prioritate specific. Un al doilea nivel (denumit "prioritate grup") permite specificarea unei ordini interne pentru cererile simultane de pe același nivel dar cu un grup diferit. La sfârșitul fiecărui ciclu de instrucțiune, o cerere sursă cu cea mai mare prioritate curentă va fi determinată de sistemul de întreruperi. Această solicitare va fi deservită, dacă prioritatea sa este mai mare decât prioritatea actuală a procesorului din registrul PSW.

Descrierea registrului întreruperi de sistem

Procesarea întreruperilor este controlată la nivel global de registrul PSW printr-un bit general de activare a întreruperilor(IEN) și câmpul de prioritate CPU (ILVL). În plus, diferitele surse de întrerupere sunt controlate individual de către regiștri lor specifici pentru întrerupere (…IC). Astfel, acceptarea cererilor de întrerupere CPU este determinată atât de regiștri de control ai întreruperilor și de PSW. Serviciile PEC sunt controlate de către registrul respectiv PECCx și indicatori sursă si destinație, care specifică sarcina respectivului canal de serviciu PEC.

Regiștri de control ai întreruperilor

Toți regiștri de control ai întreruperilor sunt organizați identic. Cei mai puțini semnificativi 8 biți din registrul de control al întreruperi conțin informații complete de stare ale sursei asociate întreruperi, care sunt necesare în timpul rundei de prioritizare. Cei mai semnificativi 8 biți ai registrului respectiv sunt rezervați. Toți regiștri de control ai întreruperi sunt adresabili la nivel de bit și toți biții pot fi citiți sau scriși prin software. Acest lucru permite fiecărei surse de întrerupere să fi programată sau modificată cu doar o singură instrucțiune.

Prioritizarea cererilor de întrerupere standard și PEC.

Cererile de întrerupere și PEC, din toate sursele de întrerupere pot fi activate astfel încât acestea sunt arbitrate și deservite (dacă vor câștiga), sau pot fi dezactivate, deci cererile lor nu sunt luate în considerare și nu deservite.

Activarea și dezactivarea cererilor de întrerupere se poate face prin intermediul a trei mecanisme:

– Biți de control permit ca fiecare sursă să fie comutată individual pe "ON" sau "OFF", așa că poate genera o cerere sau nu. Biții de control (xxIE) sunt situate în regiștri de control ai întreruperi respective. Toate cererile de întrerupere pot fi activate sau dezactivate, în general, prin bit-ul IEN din registrul PSW. Acest bit de control este "comutatorul principal".

Pentru ca o cerere specifică să poată fi arbitrată, atât bit-ul sursă respectiv xxIE cat și bit-ul IEN din registrul PSW trebuie să fie activi.

Nivelul de prioritate selectează automat un anumit grup de cereri de întrerupere, care va fi recunoscut, restul de cereri nefiind luate în seamă. Nivelul de prioritate al sursei care a câștigat arbitrajul este comparat cu nivelul actual CPU și sursa este deservită numai, în cazul în care nivelul său este mai mare decât nivelul CPU actual. Modificarea nivelului CPU la o anumită valoare prin software blocheaza toate cererile de același nivel sau de un nivel mai mic. O sursă de întrerupere căreia i se atribuie nivelul 0 va fi dezactivată și nu va fi deservită niciodată.

Instrucțiunile ATOMIC și EXTEND dezactivează automat toate cererile de întrerupere pe durata următoarelor 1-4 instrucțiuni. Acest lucru este util de exemplu pentru folosirea semafoarelor și nu are nevoie să reactiveze sistemul de întreruperi după secvența de instrucțiuni nedesparțite.

Managementul întreruperilor pe clase

O clasă de întreruperi cuprinde un set de surse de întrerupere, cu aceeași importanță, care au aceeași prioritate din punctul de vedere al sistemului. Întreruperile de aceeași clasă nu trebuie să se întrerupă reciproc. Microcontroller-ul C163 suportă această funcție cu două caracteristici:

– Clasele cu până la 4 membri pot utiliza aceeași prioritate de întrerupere (ILVL) cărora li se atribuie un nivel de grup dedicat (GLVL) pentru fiecare membru. Această funcționalitate este implementată și tratată automat de către controlerul de întrerupere.

– Clasele care au mai mult de 4 membri poate fi stabilite prin utilizarea unui număr de priorități adiacente de întrerupere (ILVL) și nivelurile respective de grup (4 pe ILVL). Fiecare rutina de tratare a întreruperi din această clasă stabilește nivelul procesorului la cea mai înaltă prioritate de întrerupere din cadrul clasei. Toate cererile de același nivel sau orice nivel inferior sunt blocate în prezent, adică nicio cerere din această clasă, nu va fi acceptată.

Salvarea starea curente înainte de intrarea în rutina de tratare a întreruperi.

Înainte ca o cerere de întrerupere care a fost arbitrată să fie deservită, de fapt, starea taskului curent este salvată automat pe stiva sistemului. Starea CPU (PSW) este salvată împreună cu locul, din care taskul întrerupt urmează să fie reluat după întoarcerea din rutina de tratare a întreruperi. Această locație de întoarcere este specificată de indicatorul de instrucțiuni (IP) și în cazul unui model de memorie segmentat și de indicatorul segment de cod (CSP). Bitul SGTDIS din registrul SYSCON, controlează cum este salvat locul de întoarcere.

Stiva de sistem primește PSW primul, urmat de IP (în veriunea în care segmentara nu este activă) sau urmat de CSP și apoi IP (segmentare activă). Această optimizează utilizarea stivei de sistem, în cazul în care segmentarea este dezactivată.

Câmpul de prioritate CPU (ILVL din PSW) este actualizat cu prioritatea cererii de întrerupere care urmează să fie deservită, astfel procesorul execută acum pe noul nivel.

Fanionul cereri de întrerupere a sursei care este deservit este eliminat. IP-ul este încărcat cu vectorului asociat cu sursa solicitantă (CSP este eliminat în cazul în care segmentare este activă) și prima instruirea din rutina de tratare a întreruperi este preluată din vectorul respectiv, care va face un salt la rutina de tratare. Indicii de pagini de date și indicatorul de context nu sunt afectate.

Când se iese din rutina de tratare a întreruperi (RETI este executat), informațiile de stare sunt aduse de pe stivă de sistem în ordine inversă, ținând cont de valoarea bitului SGTDIS.

Comutare de context

O rutină de tratare a întreruperi salvează de obicei, toți regiștri pe care îi utilizează pe stivă și îi aduce înapoi înainte de a reveni. Cu cât o rutină utilizează mai mulți regiștri, mai mult timp este pierdut cu salvarea și aducerea înapoi a aceștora. Microcontrollerul C163 permite schimbarea setului complet de regiștri CPU (GPRS), cu o singură instrucțiune, astfel rutină de tratare a întreruperi se execută în propriul context, separat.

Funcțiile Trap

Trapurile întrerup executarea curentă similar cu întreruperi standard. Cu toate acestea, funcțiile trap oferă posibilitatea de a ocoli sistemul de prioritizare a întreruperilor în cazurile în care este necesar o reacție imediată a sistemului. Funcțiile Trap nu sunt mascabile și au întotdeauna prioritate față de cererile de întrerupere pe orice nivel de prioritate.

C163 oferă două tipuri diferite de mecanisme de trap. Hardware trap sunt declanșate de evenimente care au loc în timpul execuției programului (de exemplu, accesul ilegal. sau opcode nedefinit), software trap sunt inițiate printr-o instrucțiune în fluxul de execuție curent.

Software Trap

Instrucțiunea TRAP este folosită pentru a produce un apel software pentru o rutină de tratare a întreruperi.

Executarea unei instrucțiuni TRAP produce un efect similar ca și în cazul în care ar fi avut loc o întrerupere la același vector. PSW, CSP (în modul segmentare), și IP sunt împinse pe stiva sistemului intern și un salt este făcut la locația vector specificată. Când segmentare este activată și trap este executată, CSP pentru rutina de tratare trap este setat la segmentul de codul 0. Nici un fanion al cererilor de întrerupere nu sunt afectate de instrucțiunea TRAP. Rutina de tratare a întrerupere apelată printr-o instrucțiune TRAP trebuie să fie încheiată cu un RETI (revenire din întrerupere).

Nivelul CPU din registrul PSW nu este modificat de instrucțiunea TRAP, deci rutina de tratare este executată pe acelasi nivel de prioritate pe care a fost invocată. Prin urmare, rutina de tratare introdusă de instrucțiunea TRAP poate fi întreruptă de alte trapuri sau întreruperi cu prioritate mai mare.

Trapurile hardware

Trapurile hardware sunt produse din cauza defectelor sau starilor de sistem specifice, care apar în timpul rulării unui program. Un hardware trap poate fi, de asemenea, declanșat în mod intenționat , de exemplu. să imite instrucțiuni suplimentare prin generarea unei trap pentru opcode ilegal. Microcontrollerul C163 distinge opt funcții trap hardware diferite. Când o condiție trap hardware a fost detectată, CPU-ul face salt la adresa vectorului trap pentru condiția trap respectivă. În funcție de condiția trap, instrucțiunea care a cauzat trapul este fie finalizată sau anulată (adică nu are nici un efect asupra stării sistemului), înainte să se intre în rutina de tratare a trapului.

Trapurile hardware nu sunt mascabile și au întotdeauna prioritate asupra oricărei alte activități CPU. Dacă sunt detectate mai multe condiții trap hardware în cadrul aceluiași ciclu de instrucțiuni, trapul cu cea mai mare prioritate este deservită.

PSW, CSP (în modul segmentare), iar IP sunt împinse pe stiva internă a sistemului și nivelul procesorului din registrul PSW este setat la cel mai înalt nivel de prioritate (de ex. nivelul 15), dezactivează toate întreruperile. CSP este setat la segmentul de cod zero, în cazul în care segmentare este activată. O rutina de tratare trap trebuie să se încheie cu o instrucțiune RETI.

Registul de fanioane care este adresabil la nivel de bit (TFR) permite rutinei de tratare trap să identifice tipul de trap care a provocat o excepție. Fiecare funcție trap este indicată printr-un fanion de cerere separat. Atunci când are loc un hardware trap, fanionul cerere corespunzătoare din registrul TFR este setat pe "1".

Funcțiile de resetare (hardware, software, watchdog) pot fi considerată ca un tip de trap. Funcțiile de resetare au cea mai mare prioritate a sistemului (prioritate trap III).

Trapurile de clasa A au a doua prioritate (prioritate trap II), pe al 3-lea rang sunt trapurile clasă B, deci un trap clasa A poate întrerupe un trap din clasele B. În cazul în care mai mult trapuri din clasă A au loc la un moment dat, ele sunt prioritizate intern, trapul NMI având cea mai mare prioritate și trapul de stivă underflow având cea mai mică prioritate.

Toate trapurile de clasă B au aceeași prioritate trap (prioritate trap I). Atunci când mai multe trapuri din clasa B ajung să fie active la un moment dat, fanioanele corespunzătoare din registrul TFR sunt setate și se intră în rutina de tratare a trapului. Deoarece toate trapurile din clasa B au același vector, prioritatea, în cazul în care apar simultan mai multe trapuri din clasă B este determinată de software, în rutina de tratare trap.

Dacă apare un trap clasa A, în timpul executării unei rutină de tratare trap de clasă B, trapul de clasa A va fi deservită imediat. În timpul executării unei rutine de tratare trap de clasă A, orice trap de clasă B, care apare, nu va fi deservită până când rutina de tratare trap de clasă A nu se termină cu o instrucțiune RETI. În acest caz, apariția trapurilor de clasă B sunt stocate în registrul TFR.

Porturile paralele

În scopul de a accepta sau de a genera semnale de control externe simple sau date paralele, C163 ofera până la 77 de linii IO paralele organizate în șapte porturi IO pe 8 biți, portul 0 care este compus din P0H și P0L, portul 1 care este compus P1H și P1L, portul 2, portul 4 și portul 6, un port de 15-bit IO (portul 3) și un port de intrare pe 6 biți – portul 5.

Aceste linii ale porturilor pot fi folosite ca lini generale de intrare/ieșire, controlate prin software sau pot fi utilizate implicit de perifericele integrate ale microcontrollerului C163 sau de controllerul de magistrală extern.

Toate liniile porturilor sunt adresabile la nivel de bit, și toate linii de intrare/ieșire sunt programabile ca intrări sau ca ieșiri prin regiștri de direcție (cu excepția portului 5, desigur).

Porturile IO sunt porturi bidirecționale adevărate, care sunt trecut în stare de înaltă impedanță, când sunt configurate ca intrări. Driverele de ieșire a trei porturi IO (2, 3, 6), pot fi configurate pin cu pin pentru funcționarea în modul push–pull sau funcționare în modul open-colector prin regiștri de control. Nivelul logic al unui pin este pus pe intrare o dată pe starea de timp, indiferent dacă portul este configurat pentru intrare sau ieșire.

O operație de scriere a unui pin din port configurat ca intrare, face ca valoarea să fie scrise în ieșire de port(latch), în timp ce o operație de citire returnează starea latch a pinului. O operație de citire-modificare-scriere, citește valoarea pinului, o modifică și o scrie înapoi la ieșire latch.

Scrierea unui pin configurat pentru ieșire (DPx.y = '1') face ca latchul de ieșire și pinul să aibă valoarea scrisă, deoarece registrul tampon de ieșire este activat. Citirea acestui pin returnează valoarea de latch de ieșire.

Dacă se utilizează o funcție alternativă de intrare pentru un pin, direcția pinului trebuie să fie programată pentru intrare (DPx.y = '0'), în cazul în care un dispozitiv extern controlează pin-ul. Direcția de intrare este implicită după resetare. Dacă nici un dispozitiv extern nu este conectat la pin, se poate seta direcția de ieșire.

În acest caz, pinul reflectă starea de ieșire a portului latch. Astfel, funcția alternativă de intrare citește valoarea stocată în ieșirea de port latch. Acest lucru poate fi utilizat în scopuri de testare pentru a permite unui declanșator software al funcției alternative de intrare să scrie în portul de ieșire latch.

Pe cele mai multe dintre liniile porturilor, softwareul utilizator este responsabil pentru stabilirea direcției corecte, atunci când se utilizează o funcție alternativă de intrare sau ieșire pentru un pin. Acest lucru se face prin setarea sau ștergerea bitului de control DPx.y din registrul de direcție a pinului înainte de activarea funcției alternative. Există linii de port, a căror direcția de linie a portului este comutată automat.

Unitățile de timer de uz general

Unitățile de timer GPT1 și GPT2 reprezintă structuri foarte flexibile de timere multifuncționale, care pot fi utilizate pentru sincronizare, numărarea de evenimente, generarea de puls, multiplicări de frecvență, precum și în alte scopuri. Ele includ cinci timere pe 16-biți, care sunt grupate în două blocuri timer GPT1 și GPT2.

Blocul timer GPT1

Blocul GPT1 conține 3 timere/contoare, cu o rezolutie maxima de 400 ns la un ceas CPU de 20 MHz, în timp ce blocul GPT2 conține 2 timere/contoare, cu o rezolutie maxima de 200 ns la un ceas CPU de 20 MHz și un registru pe 16-biți de Captură/reîncarcare (CAPREL). Fiecare timer din fiecare bloc poate funcționa independent într-un număr de moduri diferite, cum ar fi modul "poartă timer" sau modul contor, sau pot fi concatenat cu un alt timer din același bloc. Timerele auxiliare ale GPT1 poate fi opțional configurate ca regiștri de reîncărcare sau de captară pentru timerul de bază(T3). În blocul GPT2, registrul suplimentar CAPREL suportă operația de captură și reîncărcare cu funcționalitate extinsă.

Toate cele trei timere din blocul GPT1 (T2, T3, T4) pot rula în 3 moduri de bază, care sunt timer, timer poartă, și modul contor, acestea pot să numere în sus sau în jos. Fiecare timer are o funcție alternativă de intrare a datelor pe un pin din Portul 3, asociat cu acesta, care controlează poarta în modul "poartă timer", sau ca intrare de numărare în modul contor. Direcția de numărare (Sus/Jos) poate fi programată prin software sau poate fi modificată dinamic de un semnal la un pin de control extern de intrare. Fiecare revărsare/subîncărcare al timerului de bază T3 poate fi indicat ca o funcție alternativă de ieșire de dată pe pin. Timerele auxiliare T2 și T4 pot fi concatenate cu timerul de bază, sau pot fi folosite ca regiștri de captură sau reîncărcare pentru timerul de bază.

Concatenarea timerelor

Folosind bitul toggle T3OTL ca o sursă de ceas pentru un timer auxiliar în modul contor, concateneaza timer de bază T3 cu respectivul timer auxiliar. În funcție de ce tranziție este selectată pe T3OTL pentru a acționa ca ceas pentru timer auxiliar, această înlănțuire formează un timer/counter pe 32-biți sau pe 33-biți.

• Timer/Contor pe 32 de biți : Dacă se utilizează atât tranziția pozitivă cât și cea negativă a T3OTL ca ceas pentru timerul auxiliar, acest timer este tactat la fiecare revărsare/subîncărcare al timerului de bază T3. Astfel, cele două timere formează un timer de 32 de biți.

• Timer/Contor pe 33 de biți: Dacă este selectat fie tranziția pozitivă, fie cea negativ a T3OTL ca ceas pentru timerul auxiliar, acest timer este tactat la fiecare secundă revărsare/subîncărcare al timerului de bază T3. Această configurație formează un timer pe 33 de biți (16 biți timer de bază + T3OTL + 16 biți timer auxiliar).

Direcțiile de numărare a celor două timere concatenate nu trebuie să fie aceeași. Aceasta oferă o gamă largă de configurații diferite.

Conținutul curent al fiecărui timer poate fi citit sau modificat de către CPU prin accesarea regiștrilor de timer corespunzători T2, T3 sau T4 care se află în spațiul SFR, dar care nu sunt accesibili la nivel de bit.

Blocul timer GPT2

Blocul timer GPT2 suportă controlul evenimentelor de mare precizie, cu o rezolutie maxima de 200 ns la un ceas CPU de 20 MHz. Acesta include timerele T5,T6 și registru de captură și reîncarcare CAPREL pe 16 biți. Timerul T6 este timerul de bază, și T5 este timerul auxiliar în GPT2.

Interfața serială asincronă/sincronă

Interfața serială asincronă/sincronă ASC0 asigură comunicația serială între C163 și alte microcontrollere, microprocesoare sau periferice externe.

ASC0 suportă comunicarea asincronă full-duplex de până la 625 kBaud și comunicarea sincronă semiduplex de până la 2,5 MBaud la un ceas CPU de 20 MHz. În modul sincron, datele sunt transmise sau primite sincron cu fiecare shiftare de ceas, care este generată de microcontrollerul C163. În modul asincron, cu transferuri de date de 8 sau 9 biți, generare de paritate, iar numărul de biți de stop poate fi selectat. Paritatea, încadrarea și detectarea erorilor de ritm sunt prevăzute pentru creșterea fiabilități transferurilor de date. Pe transmisie și recepție de date avem doi regiștri tampon. Pentru o comunicare multiprocesor, un mecanism pentru a distinge octeți de adresele de octeți de date este inclus. Testarea este susținută de o opțiune de buclă înapoi. Un generator de rată de transfer pe 13-biți oferă un semnal serial de ceas separat pentru ASC0.

Modul de funcționare al interfeței seriale ASC0 este controlat de registru de control S0CON . Acest registru conține biți de control pentru modul de selectare și de verificare a erorilor, precum și fanioanele de stare pentru identificarea erorilor.

O transmisie este pornită de scrierea în registrul tampon S0TBUF (printr-o instrucțiune sau un transfer de date PEC). Numai numărul de biți de date, care este determinat de modul de lucru selectat va fi transmis, adică. biți scriși în pozițiile 9 până la 15 în registru S0TBUF sunt întotdeauna nesemnificativi. După ce o transmisie a fost finalizată, registrul tampon de transmisie este golit la 0000h.

Transmiterea datelor are doi registri tampon, deci un nou caracter poate fi scris în registrul tampon de transmisie, înainte ca transmiterea caracterul anterior să fie completă. Acest lucru permite transmiterea de caractere unul după altul, fără pauze.

Recepția datele este activată prin intermediul bitului de recepție S0REN. După ce am finalizat primirea unui caracter și a bitului de paritate(dacă modul de operare selectat, are și un bit de paritate), toate acestea se pot ciți din registrul tampon de primire S0RBUF. Biți din jumătatea superioară a S0RBUF care nu sunt valabili în modul de operare selectat, var fi citiți ca zerouri.

Recepția datelor are doi registri tampon, astfel încât recepția unui al doilea caracter poate începe înainte ca actualul caracter primit să fie citit din registru tampon de recepție. În toate modurile, detectarea erorilor de ritm poate fi selectată prin intermediul bitului S0OEN. Când este activată, fanionul stare de eroare S0OE și fanionul cerere de întrerupere pentu erori S0EIR vor fi setate atunci când registrul tampon de primire nu a fost citit la timp, înainte ca recepția celui de al doilea caracter să fie completă. Caracterul primit anterior din tamponul de primire este suprascris.

Opțiunea buclă înapoi (selectată de bitul S0LB) permite ca datele care sunt transmise acuma să fie primite simultan și în registrul tampon de recepție. Acest lucru permite testarea rutinelor de comunicație serială într-un stadiu incipient, fără a fi nevoie să asigurăm o conexiune la o rețea externă. În modul buclă înapoi funcțiile alternative de intrare/ieșire ale pinilor din portul 3 nu sunt necesare.

Transmisiile și recepțiile de date sunt posibile numai în cazul în care Bitul Generator rată de transfer S0R este setat pe "1". În caz contrar, interfața serială este inactivă.

Funcționare asincronă

Modul asincron suportă comunicație full-duplex, atunci când atât emițător cât și receptorul folosi același format pentru cadrul de date și aceeași rată de transfer. Datele sunt transmise pe pinul TXD0 / P3.10 și primite pe pinul RXD0 / P3.11. Aceste semnale sunt funcții alternative ale pinilor din portului 3.

Cadrele de date transmise sunt alcatuide din trei elemente de bază:

• bitul de start

• câmpul de date (8 sau 9 biți, LSB în primul rând, un bit de paritate în cazul în care este selecționat, un mod care are bit de paritate)

• bit de stop (1 sau 2 biți de stop)

Transmiterea datelor se face cu ajutorul a doi registri tampon. Atunci când transmițătorul este inactiv, datele de transmisie încărcate în S0TBUF sunt mutate imediat în registrul de transmisie pentru shiftare eliberând astfel S0TBUF pentru următorele datele care trebuie trimise. Acest lucru este indicat de fanionul cerere de întrerupere S0TBIR din registrului S0TBIC. S0TBUF poate fi acum încărcat cu următoarele date, în timp ce transmiterea anterioară este încă în desfășurare.

Fanionul cerere de întrerupere pentru transmisie S0TIR va fi setat înainte ca ultimul bit din cadru să fie transmis.

Recepție asincronă este inițiată de un semnal coborâtor(tranziție 1-la-0 ) pe pinul RXD0, cu condiția ca biți S0R și S0REN să fie setați. Datele de intrare primite pe pinul RXD0 sunt eșantionate de 16 ori față de rata de transfer selectată. Decizie se face pe eșantioanele 7, 8 și 9, acestea determinând valoarea efectivă a bitului. Această metodă evită rezultatele eronate care pot fi cauzate de către zgomot.

Atunci când bitul de start este eșantionat și valoarea detectată nu este "0", circuitul de primire este resetat și așteaptă următoarea tranziției 1-la-0 pe pinul RXD0. Dacă bitul de start se dovedește valid, circuitul de primire continuă eșantionarea și shiftează cadrule de date care registrul de primire shiftare.

Când ultimul bit de oprire a fost primit, conținutul registrul de primire shiftare este transferat în registul de primire tampon de date S0RBUF. În același timp, fanionul cerere de întrerupere S0RIR este setat după eșantionul 9 din ultimul bit de stop, indiferent dacă au fost primiți biți de stop valizi sau nu. Circuitul de primire așteaptă apoi pentru următorul bit de start (tranziție 1-la-0 ) la pin-ul intrare de date.

Recepția asincronă este oprită prin resetarea bitului S0REN, punerea valori "0". Un cadru care se primește în prezent este finalizat, inclusiv generarea cereri de întrerupere de primire și a cereri întrerupere de eroare, dacă este cazul. Biți de start care urmează după acest cadru nu vor mai fi recunoscuți.

Capabilitățile hardware de detectare a erorilor

Pentru a îmbunătăți siguranța schimbului serial de date, interfața serială ASC0 oferă fanion cerere de întrerupere pentru eroari, care indică prezența unei erori și trei fanioane de stare pentru erori în registrul S0CON, care indică care eroarea a fost detectată în timpul recepției. La finalizarea unei recepție, fanionul cerere de întrerupere pentru eroari S0EIR va fi setat simultan cu fanionul cerere de întrerupere pentru recepție S0RIR, în cazul în care una sau mai multe dintre următoarele condiții sunt îndeplinite:

• Dacă detectarea erorilor de încadrare este setată prin intermediul bitului S0FEN și oricare dintre biții de oprire nu sunt pe "1", fanionul de eroare pentru cadre S0FE este setat, indicând faptul că cererea de întrerupere pentru eroari se datorează unei erori de încadrare (numai în modul asincron).

• Dacă detectarea erorilor de paritate este setată prin intermediul bitului S0PEN în modurile în care se primiște un bit de paritate, iar verificarea parități pe biții de date primiți se dovedește falsă, fanionul de eroare pentru paritate S0PE este setat, indicând faptul că cererea de întrerupere pentru eroari se datorează unei erori de paritate (numai modul asincron).

• Dacă detectarea erorilor de ritm este setată prin intermediul bitului S0OEN și ultimul caracter primit nu a fost citit din registrul tampon de recepție de software sau de un transfer PEC în momentul în care recepția unui nou caracter este completă, fanionul de eroare pentru ritm S0OE este setat, indicând faptul că cererea de întrerupere pentru eroari se datorează unei erori de ritm (în modul asincron și în modul sincron).

Întreruperile de control ASC0

Patru regiștri de control adresabili la nivel de bit pentru întrerupere sunt furnizați pentru interfața serială ASC0. Registrul S0TIC controlează întreruperea de transmisie, S0TBIC controlează întreruperea de transmisie buffer, S0RIC controlează întrerupere pe recepție și S0EIC controlează întreruperea de eroarea pe interfața serială ASC0. Fiecare sursă de întrerupere are propriul vector de întrerupere. S0TINT este vectorul de întrerupere pe transmisie, S0TBINT este vectorul de întrerupere pe transmisie a registrului tampon, S0RINT este vector de întrerupere pe recepție, iar S0EINT este vectorul de întrerupere pentru erori.

Parte Practică

Structura aplicației ECU:

– Blocurile Funcționale:

Formatul pachetului

Pentru comunicația între PC și controller am ales să trimit informațiile grupate într-un pachet, deoarece comanda care trebuie să o trimit este mai mare decât un octet, cât se poate trimite o dată pe portul serial și doresc să verific corectitudinea informațiilor transmise astfel încât controlerul să nu recepționeze octeți incorecți pe care să îi și execute. Ideea de pachet este folosită la nivel software, deoarece la nivelul low level se va trimite fizic tot câte un octet la un moment dat pe portul serial. Pentru pachet am gândit urmatoarea structura:

typedef struct {

unsigned char cmd;

unsigned char data0;

unsigned char data1;

unsigned char csum;

}Pachet;

Unde câmpul ‚cmd’ l-am gândit că ar fi un fel de identificator de pachet, de fapt aici codific motorul pentru care se adresează comanda și tipul comenzi.

Pachetul este format dintr-un câmp cmd, din doua câmpuri de date data0 ,data1 și dintr-un câmp csum.

– Câmpul cmd are lungimea de un octet și conține comanda pentru motoarele pas cu pas.

cmd : – ‚1’ – Mișcare în sus

‚2’ – Mișcare în jos

– ‚4’ – Mișcare în față

‚5’ – Mișcare în spate

– Câmpurile de date data0 și data1 au fiecare lungimea de câte un octet și conțin numărul de pași care trebuie făcut de motoare.

-Câmpul csum are lungimea de un octet și conține suma valorilor din câmpurile cmd, data0 și data1, sumă de control realizată pe un octet (se păstrează doar partea mai puțin semnificativă dacă suma valorilor celor 3 câmpuri este mai mare de un octet) .

Inițializare controler

Inițializare porturi paralele

În aplicația care rulează pe controler am inițializat toate porturile folosite la începutul aplicației într-o funcție numită init a cărui conținut este prezentat mai jos.

void init (void)

{

//serial

P3 = P3 | 0x0C00;// transmisie și recepție

DP3 = DP3 | 0x0400;// bit transmisie = iesire

DP3 = DP3 & 0xF7FF;// bit recepție = intrare

P3 – este registrul de date al portului 3.

P3 = P3 | 0xC00 – aplicăm la ce avem în P3 o mască care are valoarea 0x0C00 și folosim operatorul pe biți „or” – operație care ne va seta bitul 10 și 11 pe 1 logic, adică activăm funcțiile alternative TxD0 și RxD0 din portul P3 care ne ajută în comunicația serială asincronă.

DP3 – este registrul de direcție al portului paralel P3. În acest registru specificăm dacă un pin din port este de intrare sau de ieșire deoarece toții pinii pot fi bidirecționali.

DP3 = DP3 | 0x0400 – aplicăm la ce avem in DP3 o mască care are valoarea 0x0400 și folosim operatorul pe biți „or” – operație care ne va seta bitul 10 pe 1 logic, adică TxD0 pe ieșire.

DP3 = DP3 & 0xF7FF – aplicăm la ce avem in DP3 o mască care are valoarea 0xF7FF și folosim operatorul pe biți „and” – operație care ne va seta bitul 11 pe 0 logic, adică RxD0 pe intrare.

Inițializare comunicație serială

S0BG = 0x0020;// 19200 baud

S0CON = 0x8011;//8 biti date fara paritate,1 bit stop

// S0REN=1(receiver enable)

S0RIC = 0x0057;// 01 0101 11

Rata de transfer a interfeței seriale este determinată de ceasul CPU, de valoarea de reîncarcare, de valoarea bitului S0BRS și de modul de operare (asincron sau sincron).

Viteza maxima a ratei de transfer care poate fi atinsă la transmisia asincronă când folosim un ceas CPU de 20 MHz este de 625 Kbaud (kilobiți pe secundă).

Am ales o rată de transfer de 19200 baud folosind tabelul din manualul controlerului prezentat în continuare.

Registrul S0BG este un registru cu funcție dubla – generator rată de transfer și registru de reîncărcare. Citirea lui S0BG returnează conținutul timerului, în timp ce scrierea lui S0BG actualizează întotdeauna registrul de reîncărcare.

O reîncarcare automată a timerului cu conținutul registrului de reîncărcare se efectuează de fiecare dată când S0BG este scris. Cu toate acestea, în cazul în care S0R = "0" la momentul în care se efectuează operațiunea de scriere a lui S0BG, timerul nu va fi reîncărcat până la primul ciclu de instrucțiune, după ce S0R = '1'.

Pentru funcționare în modul asincron, generatorul pentru rata de transfer oferă pe recepție o rata mai mare de 16 ori față de rata de transfer stabilită. Fiecare bit primit este verificat pe esantionul al 7-lea, 8-lea și 9-lea.

Am ales ca registrul de control S0CON să aibă valoarea 0x8011 – rezultând modul de control asincron cu 8 biți de date(S0M = 1), recepție activă(S0REN = 1) și bitul de pornire a generatorului ratei de transfer (S0R = 1) pentru interfața serială ASC0.

S0RIC = 0x0057 – am setat prioritatea pentru întrerupere pe recepție.

ILVL – nivelul de prioritate a întrerupere – 5

GLVL – Nivelul de grup – 3

Inițializare timer

T3CON = 0x0045; //registrul de control al timerului 3

T3IC = 0x0053; //0 1 0100 11

T3IR = 0; //fanion cerere întrerupere

Timer nucleu din GPT1 T3 este configurat și controlat prin intermediul registrului adresabil la nivel de bit T3CON.

T3I – selecția intrări pentru timerul 3

T3R – bitul de pornire pentru timerul 3

T3IC – Registrul de control a întreruperi pentru timerul 3

ILVL – nivelul de prioritate a întrerupere – 4

GLVL – Nivelul de grup – 3

Întreruperi

Pentru aplicația de pe controller am decis să folosesc două întreruperi. O întrerupere pentru timer și o întrerupere pentru recepția serială. Pe controller există un flag IEN prin intermediul căruia se poate activa sau bloca generarea tuturor întreruperilor.

IEN = 1; // sistemul de întrerupere este activ

// global prin punerea pe 1 a bitului

// IEN din registrul PSW

// întrerupere pentru recepție serială

S0RIC = 0x0057; //01 0101 11

// întrerupere de timer

T3IC = 0x0053; //01 0100 11

Direcție port paralel:

DP2 = 0xFF00; // registrul de control al direcției

// pentru portul 2

Am setat direcția pentru cei mai semnificativi 8 biți din portul P2 pe ieșire pentru a putea afișa pe leduri, prin intermediul registrului de direcție DP2.

Recepție pachet:

În întreruperea seriala este tratată transmiterea de comenzi de la computer la microcontroller astfel :

0x2B – Se găsește în tabelul cu surse de întrerupere care pot să ceară service. Acesta este numărul trap asociat sursei de întrerupere ASC0 recepție. Numărul trap indică locul vectorului unde se face „saltul”.

void receptie_int (void) interrupt 0x2B //rutina tratare

//intrerupere

//receptie seriala

{

unsigned char csum = 0;

switch(pozitie)

{

case 0:

pack.cmd = (unsigned char)S0RBUF;

pozitie = 1;

break;

case 1:

pack.data0 = (unsigned char)S0RBUF;

pozitie = 2;

break;

case 2:

pack.data1 = (unsigned char)S0RBUF;

pozitie = 3;

break;

case 3:

pack.csum = (unsigned char)S0RBUF;

csum = pack.cmd + pack.data0 + pack.data1;

if(csum == pack.csum)

flag_receptie = 1;

pozitie = 0;

break;

}

S0RIR=0;

}

Rutina void receptie_int este destinată să trateze întreruperea de recepția pe seriala ASC0 a microcontrollerului. De exemplu, trimitem de la PC o comandă de 1000 de pași. Prima dată se trimite comanda cu direcția aleasă pentru unul din cele doua motoare, care ajunge prin intermediul serialei RS232 în registrul de șiftare pe recepție și de aici în regisrul tampon de recepție al interfeței seriale ASC0 a microcontrollerului. Fanionul de întrerupere pe recepție este setat(S0RIR = 1), când mutăm cadrul în registrul tampon S0RBUF. Registrul S0RIC este cel care controlează întreruperea pe recepție. Asociat acestui registru avem vectorul S0RINT, datorită căruia se face saltul la rutina de tratare a întreruperi pe serială(void receptie_int). Atribuim valoarea din S0RBUF în pack.cmd și setăm pozitie = 1, S0RIR este setat pe 0 și se asteaptă urmatorul cadru. Același lucru se repetă și pentru data0, data1 și csum, diferind doar locul în care se copiază valoarea din S0RBUF. Acest lucru diferă datorită variabilei pozitie și a switchlui cu 4 cazuri din rutina void receptie_int. Cele 4 cazuri din switch sunt următoarele:

Cazul 0 – valoarea din S0RBUF este atribuită lui pack.cmd(cmd din pachet) și trecem în variabila pozitie valoarea 1.

Cazul 1 – valoarea din S0RBUF este atribuită lui pack.data0 (data0 din pachet) și trecem în variabila pozitie valoarea 2.

Cazul 2 – valoarea din S0RBUF este atribuită lui pack.data1 (data1 din pachet) și trecem în variabila pozitie valoarea 3.

Cazul 3 – valoarea din S0RBUF este atribuită lui pack.csum (csum din pachet) și este verificat dacă aceasta valoare din pack.csum este egala cu rezultatul din csum, care este egal cu suma dintre pack.cmd + pack.data0 + pack.data1. În cazul în care sunt egale, atribuim valoarea 1 în flag_receptie, după care atribuim 0 variabilei pozitie.

Tratare pachet:

După ce s-a recepționat un pachet valid, controllerul se va configura astfel încât să genereze comenzile necesare pentru motoare. Generarea comenzilor pentru motoare durează mai mult, deoarece trebuie timp ca aceste motoare să și răspundă. De exemplu dacă primim o comandă de la PC care ne cere să generăm 1000 de pași, va dura ceva până când motoarele vor efectua această comandă.

În main avem o bucla infinită, care are rolul de a verifica dacă pe recepție am primit un pachet valid. Acest lucru este verificat prin instrucțiunea if(flag_receptie). Dacă am primit un pachet valid se execută rutina de tratare_seriala, după care se atribuie valoarea 0 în flag_receptie .

while (1)

{

if(flag_receptie) // avem de tratat eveniment de

// receptie pachet

{

tratare_seriala();

flag_receptie = 0;

}

}

Rutina void tratare_seriala are rolul de a configura microcontrollerul să genereze comenzi pe care motoarele trebuie să le execute, pe baza pachetului valid primit. În rutina void tratare_seriala se verifică ce comandă a fost trimisă și pentru ce motor. Se mai memorează și câți pași trebuie făcuți de fiecare motor, într-o variabilă specifică acelui motor.

Numărul de pași care trebuie efectuați este dat de valoarea din pack.data0 și pack.data1.

void tratare_seriala()

{

if(pack.cmd == '1' || pack.cmd == '2')

{

// modificare contor M1

nr_pasi_m1 = (pack.data0 << 8) + pack.data1;

}

if(pack.cmd == '4' || pack.cmd == '5')

{

// modificare contor M2

nr_pasi_m2 = (pack.data0 << 8) + pack.data1;

}

car_rec = pack.cmd;

// Comandare motor 1

if (car_rec == '1')

{

M1 = 1;

}

else if (car_rec == '2')

{

M1 = 2;

}

else if (car_rec == '3')

{

M1 = 0;

}

// Comandare motor 2

else if (car_rec == '4')

{

M2 = 1;

}

else if (car_rec == '5')

{

M2 = 2;

}

else if (car_rec == '6')

{

M2 = 0;

}

// Comandare viteză timer

else if (car_rec == '7')

{

z = z – 1;

if (z < 0x0040)

z = 0x0040;

}

else if (car_rec == '8')

{

z = z + 1;

if (z > 0x0045)

z = 0x0045;

}

}

În rutina de tratare_seriala verificăm cu cât este egal pack.cmd. Dacă acesta este egal cu ‚1’ sau cu ‚2’ modificăm contorul motorului 1 prin atribuirea valori din pack.data0 și pack.data1 în nr_pasi_m1.

Dacă pack.cmd este egal cu ‚4’ sau ‚5’ modificăm contorul motorului 2 prin atribuirea valori din pack.data0 și pack.data1 în nr_pasi_m2.

Acum atribuim valoarea din pack.cmd în car_rec. Dacă valoarea din car_rec este egal cu ‚1’ atunci atribuim valoarea 1 lui M1, mutând motorul 1 în sus.

Dacă valoarea din car_rec este egal cu ‚2’ atunci atribuim valoarea 2 lui M1, mutând motorul 1 în jos.

Dacă valoarea din car_rec este egal cu ‚3’ atunci atribuim valoarea 0 lui M1, motorul 1 rămâne pe loc.

Dacă valoarea din car_rec este egal cu ‚4’ atunci atribuim valoarea 1 lui M2, mutând motorul 2 în față(ieșire).

Dacă valoarea din car_rec este egal cu ‚5’ atunci atribuim valoarea 2 lui M2, mutând motorul 2 în spate(intrare).

Dacă valoarea din car_rec este egal cu ‚6’ atunci atribuim valoarea 0 lui M2, motorul 2 rămâne pe loc.

Dacă valoarea din car_rec este egal cu ‚7’ atunci creștem viteza timerului, adică acesta va avea o perioadă mai mică de timp la care va genera o întrerupere, după ce va expira.

Dacă valoarea din car_rec este egal cu 8 atunci scădem viteza timerului, adică acesta va avea o perioadă mai mare de timp la care va genera o întrerupere, după ce va expira.

Cum am implementat comenziile

Comandă sus – mută motorul M1 în sus, trebuie să avem valoarea ‚1’ în pack.cmd.

Comandă jos – mută motorul M1 în jos, trebuie să avem valoarea ‚2’ în pack.cmd.

Comandă ieșire – mută motorul M2 în față(ieșire), trebuie să avem valoarea ‚4’ în pack.cmd.

Comandă intrare – mută motorul M2 în spate(intrare), trebuie să avem valoarea ‚5’ în pack.cmd.

Comandă creștere viteză – creștem viteza timerului, trebuie să avem valoarea ‚7’ în pack.cmd.

Comandă scădere viteză – scădem viteza timerului, trebuie să avem valoarea ‚8’ în pack.cmd.

Comandă sus :

if (M1==1 && nr_pasi_m1 > 0)

{

x = x | 0x05;

x = x ^ 0x02;

nr_pasi_m1–;

}

Dacă M1 este egal cu valoarea 1 și nr_pasi_m1 este mai mare ca 0 facem urmatoarele operații pentru a muta motorul M1 în sus:

x = x | 0x05 – aplicăm la valoarea care se afla în x o mască care are valoarea 0x05 și folosim operatorul „or” – operație care ne va seta bitul 0 și bitul 2 pe 1.

Motorul 1 este comandat cu ajutorul unui circuit integrat care folosește 3 biți.

Bitul 0 dacă are valoarea 0 va executa un pas, iar dacă are valoarea 1 va executa o jumatate de pas(micropășire).

Bitul 1 – este legat la CLK

Bitul 2 – daca are valoarea 1 va muta motorul 1 în direcția sus

x = x ^ 0x02 – aplicăm la valoarea care se afla în x o mască care are valoarea 0x02 și folosim operatorul „xor” – operație care va schimba valoare bitul 1, îl va nega.

nr_pasi_m1– – la fiecare trecere pe aici scădem numărul pașilor care trebuie făcuți, după care verificăm dacă if (M1==1 && nr_pasi_m1 > 0) mai este adevărat, dacă este, îl executăm iar și tot așa până când acesta nu mai este adevărat, din cauză că M1 nu mai este egal cu 1 sau din cauză că am epuizat numărul de pași din nr_pasi_m1.

Comandă jos:

else if (M1==2 && nr_pasi_m1 > 0)

{

x = x & 0x03;

x = x | 0x01;

x = x ^ 0x02;

nr_pasi_m1–;

}

Dacă M1 este egal cu valoarea 2 și nr_pasi_m1 mai mare ca 0 facem urmatoarele operații pentru a muta motorul M1 în jos:

x = x & 0x03 – aplicăm la valoarea care se afla în x o mască care are valoarea 0x03 și folosim operatorul „and” – operație care ne va reseta bitul 2, adică il va pune pe 0.

Bitul 2 – daca are valoarea 0 va muta motorul 1 în direcția jos

x = x | 0x01 – aplicăm la valoarea care se afla în x o mască care are valoarea 0x01 și folosim operatorul „or” – operație care ne va seta bitul 0 pe 1(în cazul în care acesta era pe 0).

x = x ^ 0x02 – aplicăm la valoarea care se afla în x o mască care are valoarea 0x02 și folosim operatorul „xor” – operație care va schimba valoare din bitul 1, îl va nega.

nr_pasi_m1– – la fiecare trecere pe aici scădem numărul pașilor care trebuie făcuți, după care verificăm dacă if (M1==2 && nr_pasi_m1 > 0) mai este adevărat, dacă este, îl executăm iar și tot așa până când acesta nu mai este adevărat, din cauză că M1 nu mai este egal cu 2 sau din cauză că am epuizat numărul de pași din nr_pasi_m1.

Comandă ieșire:

if ((M2==1) && (nr_pasi_m2 > 0))

{

y = val_y[stareM2];

stareM2++;

stareM2 %= 4;

nr_pasi_m2–;

}

Dacă M2 este egal cu valoarea 1 și nr_pasi_m2 este mai mare ca 0 facem urmatoarele operații pentru a muta motorul M2 în față(ieșire):

y = val_y[stareM2] – unde val_y[] = {0x30,0x60, 0xc0,0x90} este un vector cu patru elemente.

stareM2++ – este o variabilă care ține locul indexului din vector pe care îl incrementăm pentru fiecare pas făcut.

stareM2 %= 4 – cu valoarea din variabila stareM2 facem %4 pentru a ne plimba prin cele patru valori din vectorul val_y[].

nr_pasi_m2– – la fiecare trecere pe aici scădem numărul pașilor care trebuie făcuți, după care verificăm dacă if (M2==1 && nr_pasi_m2 > 0) mai este adevărat, dacă este, îl executăm iar și tot așa până când acesta nu mai este adevărat, din cauză că M2 nu mai este egal cu 1 sau din cauză că am epuizat numărul de pași din nr_pasi_m2.

Comandă intrare:

else if ((M2==2) && (nr_pasi_m2 > 0))

{

y = val_y[stareM2];

stareM2–;

if(stareM2 == 0xff)

stareM2 = 3;

nr_pasi_m2–;

}

Dacă M2 este egal cu valoarea 2 și nr_pasi_m2 este mai mare ca 0 facem urmatoarele operații pentru a muta motorul M2 în spate(intrare):

y = val_y[stareM2] – unde val_y[] = {0x30,0x60, 0xc0,0x90} este un vector cu patru elemente.

stareM2– – este o variabilă care tine locul indexului din vector pe care îl decrementăm pentru fiecare pas făcut.

if(stareM2 == 0xff)

stareM2 = 3 – dacă variabila stareM2 are valoarea egala cu 0xff atunci facem stareM2 egală cu 0x90.

nr_pasi_m2– – la fiecare trecere pe aici scădem numărul pașilor care trebuie facuți, după care verificăm dacă if (M2==2 && nr_pasi_m2 > 0) mai este adevărat, dacă este, îl executăm iar și tot așa până când acesta nu mai este adevărat, din cauză că M2 nu mai este egal cu 2 sau din cauză că am epuizat numărul de pași din nr_pasi_m2.

Comandă creștere viteză:

Această comandă crește viteza cu care se deplasează motoarele. O folosesc dacă vreau să cresc viteza de deplasare.

else if (car_rec == '7')

{

z = z – 1;

if (z < 0x0040)

z = 0x0040;

}

Dacă car_rec este egal cu valoarea 7 facem următoarele operații:

z = z – 1 – scădem 1 din valoarea care se află în z. După care se verifică dacă valoarea din z este mai mică decât 0x0040, caz în care atribuim valoarea 0x0040 lui z.

Când avem valoarea 0x0040 în z timerul generează o întrerupere la 26 ms.

Comandă scădere viteză:

Această comandă scade viteza cu care se deplasează motoarele. O folosesc dacă vreau să scad viteza de deplasare.

else if (car_rec == '8')

{

z = z + 1;

if (z > 0x0045)

z = 0x0045;

}

Dacă car_rec este egal cu valoarea 8 facem următoarele operații:

z = z + 1 – adunăm 1 la valoarea care se află în z. După care se verifică dacă valoarea din z este mai mare decât 0x0045, caz în care atribuim valoarea 0x0045 lui z.

Când avem valoarea 0x0045 în z timerul generează o întrerupere la 840 ms.

Listă comenzi:

Lista pe care am tratat-o și codificat-o este urmatoarea

– Comandă sus : 0x01

– Comandă jos: 0x02

– Comandă stai: 0x03

– Comandă ieșire: 0x04

– Comandă intrare: 0x05

– Comandă stai: 0x06

– Comandă creștere viteză: 0x07

– Comandă scădere viteză: 0x08

Întreruperea de timer

Avem nevoie de timer pentru a genera o întrerupere la un anumit interval de timp. Întervalul de timp la care timerul generează o întrerupere este configurabil din registrul de control al timerului, mai exact din campul TxI.

În întreruperea timer sunt tratate toate comenzile de la microntroller pentru

motoarele pas cu pas.

void timer0 (void) interrupt 0x23 // rutina tratare

// intrerupere timer

{

if (M1==1 && nr_pasi_m1 > 0)

{

x = x | 0x05;

x = x ^ 0x02;

nr_pasi_m1–;

}

else if (M1==2 && nr_pasi_m1 > 0)

{

x = x & 0x03;

x = x | 0x01;

x = x ^ 0x02;

nr_pasi_m1–;

}

if ((M2==1) && (nr_pasi_m2 > 0))

{

y = val_y[stareM2];

stareM2++;

stareM2 %= 4;

nr_pasi_m2–;

}

else if ((M2==2) && (nr_pasi_m2 > 0))

{

y = val_y[stareM2];

stareM2–;

if(stareM2 == 0xff)

stareM2 = 3;

nr_pasi_m2–;

}

// afisare pe leduri

P2 = (((y & 0xf0)+(x & 0x0f))<<8);

T3CON = z;

T3IR = 0;

}

P2 = (((x & 0x0f)+(y & 0xf0))<<8) – aplicăm la valoarea care se afla în x o mască care are valoarea 0x0F și folosim operatorul „and” – operație care ne va reseta primi 4 biți din stânga punândui pe 0 și care va pastra primi 4 biți din dreapta. (val1)

Aplicăm la valoarea care se afla în y o mască care are valoarea 0xF0 și folosim operatorul „and” – operație care ne va pastra primi 4 biți din stânga și care va reseta primi 4 biți din dreapta, punândui pe 0. (val2)

Adunăm val1 cu val2, iar rezultatul obținut îl șiftăm la stânga cu 8 poziți, înainte să îl atribuim lui P2. Deoarece P2 este un port pe 8 biți(de la bitul 8 la 15).

T3CON = z – atribuim valoarea din z registrului de control adresabil la nivel de bit al timerului 3 din blocul GPT1.

T3IR = 0 – punem fanionul cerere de întrerupere din T3IC pe 0.

Comandă motore și timer

Microcontrollerul din circuitul integrat al motorului pas cu pas L297 generează patru semnale de unitate de fază, pentru două faze bipolare și patru faze unipolare, pentru motoarele pas cu pas din aplicațiile cu microcontrollere. Motorul poate fi condus în modul jumătate pas, pas normal și "val" și circuitele chopper generatoare de PWM din chip permit schimbarea modului de control a curentului prin înfășurări. O caracteristică a acest dispozitiv este că necesită doar semnal de ceas, direcție și semnal pentru modul de intrare. Pentru că fazele sunt generate intern, povara programatorului și a microprocesor sunt reduse foarte mult. Montat în pachetele DIP20 și SO20, L297 poate fi utilizat cu driveurile de punte monolitice, cum ar fi L298N sau L293E, sau cu tranzistoare discrete și darlington.

Circuitul de control al motorului pas cu pas bipolar

L298 este un circuit integrat monolitic într-un pachet Multiwatt și PowerSO20. Este un driver de înaltă tensiune, de curent mare, punte dublă completă, proiectat să accepte un nivel standard de logica TTL și să conducă sarcina inductivă ca și cum ar fi un releu, solenoid, DC și Motoare pas cu pas. Două intrări sunt furnizate pentru a permite sau a bloca în mod independent dispozitivul de semnalele de intrare. Emitorii tranzistorilor mai mici de pe fiecare punte sunt conectați împreună și terminalul extern corespunzător poate fi folosit pentru conectarea unei rezistor extern de detectare. O intrare de alimentare suplimentară este prevăzută astfel încât logica să funcționeze la o tensiune mai mică.

ULN2003 este o matrice Darlington de înaltă tensiune, de curent mare, conținând șapte perechi de colectori deschiși Darlington cu emitori comuni. Fiecare canal are 500mA și poate rezista la curenți de vârf de 600mA. Diodele de suprimare sunt incluse pentru sarcina inductivă de conducere și intrările sunt fixate opus față de ieșiri pentru a simplifica schema plăci.

Acest dispozitiv versatil este util pentru conducerea unei game de sarcini, inclusiv solenoizi, relee, motoare de curent continuu, ecrane led, lămpi cu filamente, capete de imprimare termice și buffere de mare putere.

ULN2003a este furnizat în pachete cu 16 pini de pastic DIP cu suport din cupru pentru conexiune, pentru a reduce rezistența termică.

– Comandă motor – Comandă timer

Interfață C++ Builder 6

În C++ Builder 6 am facut urmatoarea interfață:

Pe interfață avem un ComboBox, cu ajutorul căruia selectăm COM-ul pe care o să comunicăm cu microcontrollerul prin intermediul interfeței serialei RS232.

Butonul „Deschide” – pornește comunicația dintre pc și microcontroller.

void __fastcall TFMain::btnOpenCOMClick(TObject *Sender)

{ DCB dcbSerialParams ;

m_hCommPort = CreateFile(cbSelectCOM->Text.c_str(),

GENERIC_WRITE|GENERIC_READ,//access ( read and write)

0, //(share) 0:cannot share the COM port

0, //security (None)

OPEN_EXISTING,// creation : open_existing

FILE_FLAG_OVERLAPPED,// we want overlapped operation

0// no templates file for COM port…

);

if(m_hCommPort==NULL){

ShowMessage("nu pot deschide port");

return;

}

if(m_hCommPort==INVALID_HANDLE_VALUE) {

ShowMessage("invalid handle value");

return;

}

if (!GetCommState(m_hCommPort, &dcbSerialParams))

{

ShowMessage("error getting serial port state");

}

dcbSerialParams.DCBlength = sizeof(dcbSerialParams);

dcbSerialParams.BaudRate = CBR_19200;

dcbSerialParams.ByteSize = 8;

dcbSerialParams.StopBits = ONESTOPBIT;

dcbSerialParams.Parity = NOPARITY;

dcbSerialParams.fBinary = TRUE;

if (!SetCommState(m_hCommPort, &dcbSerialParams))

{

ShowMessage(" error setting serial port state");

}

lHCom->Caption = (int)m_hCommPort;

if(firReceptie==NULL)

firReceptie = new Fir(false);

else

firReceptie->Resume();

btnOpenCOM->Enabled = false;

btnCloseCOM->Enabled = true;

}

Butonul „Inchide” – oprește comunicația dintre pc și microcontroller și închide interfața.

void __fastcall TFMain::btnCloseCOMClick(TObject *Sender)

{

CloseHandle(m_hCommPort);

m_hCommPort = (void*)-1;

firReceptie->Suspend();

lHCom->Caption = "inchis";

btnOpenCOM->Enabled = true;

btnCloseCOM->Enabled = false;

}

COM Handle – inițial este inchis, dar dupa ce deschidem comunicația, acesta iși schimba starea.

Avem în interfață definite următoarele constante pentru a fi mai ușor înțelegerea codului:

#define SUS 0x31

#define JOS 0X32

#define INTRARE 0x35

#define IESIRE 0x34

#define PARTER 0

#define ETAJ1 1460

#define ETAJ2 2950

#define ETAJ3 4450

#define MAXIM 4800

Avem doua câmpuri, ePasi0 și ePasi1, în care introducem numarul de pași pe care vrem să îi facă motoarele M1 și M2.

În ePasi0 punem numărul de pași pentru câmpul data0 din pachet, iar în ePasi1 punem numarul de pași pentru câmpul data1.

Butonul „Sus” – Mută M1 în sus cu numărul de pași din ePasi0 și ePasi1.

unsigned char sus[]={SUS,0x00,0x00,0x0};

void __fastcall TFMain::BtnSPSClick(TObject *Sender)

{

unsigned int x;

unsigned char v0;

unsigned char v1;

ePasi0->Text.LowerCase();

if( (x = HexToBin(ePasi0->Text.c_str(), &v0, 1))!=1)

{ShowMessage("eroare conversie " + IntToStr(x)); return;}

ePasi1->Text.LowerCase();

if( (x = HexToBin(ePasi1->Text.c_str(), &v1, 1))!=1)

{ShowMessage("eroare conversie " + IntToStr(x)); return;}

x= v0;

x = (x<<8) + v1;

if ((pasi+x) > MAXIM)

{

x = MAXIM – pasi;

pasi = MAXIM;

v1 = x / 256;

v0 = x % 256;

}

else

pasi += x;

sus[1]= v0;

sus[2]= v1;

sus[3] = sus[0]+sus[1]+sus[2];

TrimitePachet(sus,4); // suma control totala

}

Butonul „Jos” – Mută M1 în jos cu numărul de pași din ePasi0 și ePasi1.

unsigned char jos[]={JOS,0x00,0x00,0x0};

void __fastcall TFMain::BtnSPDClick(TObject *Sender)

{

int x;

unsigned char v0;

unsigned char v1;

ePasi0->Text.LowerCase();

if( (x = HexToBin(ePasi0->Text.c_str(), &v0, 1))!=1)

{ShowMessage("eroare conversie " + IntToStr(x)); return;}

ePasi1->Text.LowerCase();

if( (x = HexToBin(ePasi1->Text.c_str(), &v1, 1))!=1)

{ShowMessage("eroare conversie " + IntToStr(x)); return;}

x = v0;

x = (x << 8) + v1;

if ((pasi – x) < PARTER)

{

x = pasi;

pasi = PARTER;

v1 = x / 256;

v0 = x % 256;

}

else

pasi -= x;

jos[1]= v0;

jos[2]= v1;

jos[3] = jos[0]+jos[1]+jos[2];

TrimitePachet(jos,4); // suma control totala

}

Butonul „Iesire” – Mută M2 în față cu numărul de pași din ePasi0 și ePasi1.

unsigned char iesire[]={IESIRE,0x00,0x00,0x0};

void __fastcall TFMain::BtnSOSClick(TObject *Sender)

{

int x;

char v0;

char v1;

ePasi1->Text.LowerCase();

if( (x = HexToBin(ePasi0->Text.c_str(), &v0, 1))!=1)

{ShowMessage("eroare conversie " + IntToStr(x)); return;}

ePasi0->Text.LowerCase();

if( (x = HexToBin(ePasi1->Text.c_str(), &v1, 1))!=1)

{ShowMessage("eroare conversie " + IntToStr(x)); return;}

iesire[1]= v0;

iesire[2]= v1;

iesire[3] = iesire[0]+iesire[1]+iesire[2];

TrimitePachet(iesire,4); // suma control totala

}

Butonul „Intrare” – Mută M2 în spate cu numărul de pași din ePasi0 și ePasi1.

unsigned char intrare[]={INTRARE,0x00,0x00,0x0};

void __fastcall TFMain::BtnSODClick(TObject *Sender)

{

int x;

char v0;

char v1;

ePasi1->Text.LowerCase();

if( (x = HexToBin(ePasi0->Text.c_str(), &v0, 1))!=1)

{ShowMessage("eroare conversie " + IntToStr(x)); return;}

ePasi0->Text.LowerCase();

if( (x = HexToBin(ePasi1->Text.c_str(), &v1, 1))!=1)

{ShowMessage("eroare conversie " + IntToStr(x)); return;}

intrare[1]= v0;

intrare[2]= v1;

intrare[3] = intrare[0]+intrare[1]+intrare[2];

TrimitePachet(intrare,4); // suma control totala

}

Butonul „creste_viteza” – marește viteza cu care motoarele M1 și M2 execută pași.

unsigned char creste_viteza[] = {0x37, 0x00, 0x00, 0x37} ;

void __fastcall TFMain::Button1Click(TObject *Sender)

{ creste_viteza[3]=creste_viteza[0]+creste_viteza[1]+creste_viteza[2];

TrimitePachet( creste_viteza,4);// suma control totala

}

Butonul „scade_viteza” – micșorează viteza cu care motoarele M1 și M2 execută pași.

unsigned char scade_viteza[] ={0x38, 0x00, 0x00, 0x38} ;

void __fastcall TFMain::Button2Click(TObject *Sender)

{

scade_viteza[3]=scade_viteza[0]+scade_viteza[1]+scade_viteza[2];

TrimitePachet ( scade_viteza,4);// suma control totala

}

Butonul „Parter” – Aduce rampa la nivelul 0. Mai exact Parter este nivelul de start, setat de mine, calibrarea facând-o manual.

Butonul „Etaj 1” – Aduce rampa la nivelul 1. Mai exact duce rampa la 1460 de pași față de parter.

Butonul „Etaj 2” – Aduce rampa la nivelul 2. Mai exact duce rampa la 2950 de pași față de parter și la 1490 de pași față de nivelul 1.

Butonul „Etaj 3” – Aduce rampa la nivelul 3. Mai exact duce rampa la 4450 de pași față de parter, la 2990 de pași față de nivelul 1 și la 1500 de pași față de nivelul 2.

Butonul „Inchide” – termină aplicația.

Concluzii

– Am realizat o aplicație pentru microcontroller în Keil Vision 4. Aplicația din microcontroler comunică cu PC-ul pe portul serial, iar comenzile trimise sunt sub formă de pachet, deoarece comanda conține mai mulți octeți (numărul de pași care trebuie transmiși care este mai mare de un octet) și doresc să verific și corectitudinea informaților transmise.

– Am realizat și aplicația pentru pc în Borland C++ Builder 6. Prin intermediul portul serial – RS232, trimit comezi din interfață, microcontrolerului C163, care la randul lui comandă motoarele pas cu pas.

In main verificăm daca ”flag_receptie” a fost pus pe 1. Acest lucru îl facem prin interogare. Dacă a fost pus pe 1 facem”tratare_serială”, după care facem ”flag_receptie” = 0. Toate acestea fiind într-un while infinit.

Pe controller lucrez și prin întreruperi, validând întreruperile pentru serială și pentru timer. Întreruperea de serială are la ILVL 0101, adică nivelul priorități întreruperi este 5 și GLVL este 11, adică nivelul grupului este 3, iar întreruperea de timer are la ILVL 0100, adică nivelul priorități întreruperi este 4 și GLVL este 11, adică nivelul grupului este 3. Întreruperea de serială fiind mai prioritară.

Ca o îmbunătățire a aplicației ar mai trebui făcută o detecție a pozitiei rampei, deoarece la început nu se știe în ce poziție se află aceasta, ceea ce necesită o asezare manuală în poziția de pornire. Dacă la pornire se găsește la altă poziție acesta nu ar funcționa corect.

Cunoscându-se în ce poziție se află rampa la pornire, ar mai trebui făcută calibrarea automată, adică să poziționăm rampa la parter.

Bibliografie

– 16 Bit Microcontrollers C163/C165-User's Manual 10.96 Version 2.0 C163

– KitCON-163 / 165 Hardware-Manual, an apariție 1997

– Absolute.Beginners.Guide.to.C.2nd.Edition. Author: Greg Perry, an apariție 1994

– Programming Embedded Systems in C and C++, Author: Michael Barr, First Edition January 1999, ISBN: 1-56592-354-5

– http://orion.ipt.pt/~aulasi/aed/recursos/VCLBook.pdf

– http://www.st.com/web/en/resource/technical/document/datasheet/CD00000063.pdf

– http://www.st.com/web/en/resource/technical/document/datasheet/CD00000240.pdf

– http://www.ti.com/lit/ds/symlink/uln2003a.pdf

– https://www.fairchildsemi.com/datasheets/LM/LM7805.pdf

Similar Posts

  • Proiectarea Unui Dispozitiv de Sudura Aplicat pe Podeaua Unei Cabine

    CUPRINS CUPRINS 3 Rezumat 5 Summary 5 Capitolul I CONSIDERAȚII GENERALE PRIVIND PROCEDEUL DE SUDARE[1] 6 1.1. Noțiuni introductive 6 1.2. Clasificarea procedeelor de sudare 7 1.3. Clasificarea îmbinărilor sudate 9 1.4. Modul operator al procedeelor de sudare 11 1.5. Avantajele și dezavantajele construcțiilor sudate 11 1.6 SUDAREA MANUALĂ CU ARC ELECTRIC 12 CU ELECTROZI…

  • Modelare Si Simulare Sff

    Modelare si simulare SFF Sistemele flexibile de fabricație (Flexible manufacturing system-FMS) sunt sisteme de fabricație înalt automatizate și relațiile dintre componentele sistemului sunt foarte complexe.Calculul matematic pentru măsurarea performanței a acestor sisteme este foarte dificil de rezolvat,în special pentru sisteme mai colmplexe,de aceea se foloseste la scara globală metode de simulare a FMS pentru o…

  • Antena Microstrip

    CUPRINS Introducere – pagina 2 Structura antenei microstrip – pagina 4 Latimea de banda a patch-ului microstrip si eficienta suprafata-unda – pagina 9 Antena microstrip cu patch dreptunghiular – pagina 15 Polarizarea circulara – pagina 25 Tutorial Antena Microstrip HFSS – pagina 36 Realizarea practica a antenei microstrip – pagina 54 Introducere Antenele microstrip sunt…

  • Imbunatatirea Exercitarii Functiei de Coordonare

    Сuprіns Іntroduсеrе3 Сapіtolul І Tеhnісі sі Mеtodе Dесіzіonalе5 1.1 Dеfіnіrеa dесіzіеі.5 1.2 Tіpologіa dесіzііlor6 1.3 Dеfіnіrеa sі struсtura sіstеmuluі dесіzіonal7 Сapіtolul al ІІ lеa Sіstеmul dе Managеmеnt ls SС Arіan Motors SRL 2.1 Prеzеntarе Arіan Motors SRL 2.2 Іndісatorі есonomісі la Arіal Motors SRL 2.3 Managеmеntul la Arіan Motors 2.4. Analіza SWOT la Arіan Motors…

  • Stephen Hawking

    Stephen Hawking (n. 8 ianuarie 1942, Oxford/Anglia) este un fizician englez, teoretician al originii universului și unul dintre cei mai mari cosmologi contemporani, profesor la catedra de Matematică la Universitatea Cambridge, deținută cândva de Isaac Newton. Stephen Hawking s-a născut în ziua când se împlineau 300 de ani de la moartea lui Galileo Galilei. Și-a…

  • Accidentele Rutiere CU Biciclete

    1.CAP 1 GENERALITATI PRIVIND ACCIDENTELE RUTIERE CU BICICLETE 1.1 Notiuni privind accidentele rutiere in general Accidentul rutier poate fi definit ca un eveniment intâmplător și nepravăzut cu urmări periculoase care cauzează o defecțiune a mijloacelor de transport sau a altor bunuri, moartea sau vătămarea integritătii corporale a unor persoane, eveniment care apare in timpul circulației…