Curs de instruire

Programul devine mai ușor de citit

Cu cât programul este mai mare, cu atât este mai greu să controlați și să aveți în vedere. Prin ruperea programului în părți finalizate funcțional, îl facem mai ușor de citit și mai logic. Toate funcțiile pentru lucrul cu afișajul vor fi concentrate într-un singur loc.


Posibilitatea reutilizării codului

Dacă doriți să utilizați afișajul lcd într-un alt dispozitiv, nu trebuie să rupem bucățile de cod din proiectul vechi. Am conectat doar biblioteca lcd_lib la noul proiect.


Posibilitatea compilării separate

Când programul devine mare, timpul de compilare crește. Chiar dacă facem o mică modificare a codului, compilatorul va împinge întregul fișier de la început până la sfârșit. Dacă programul este împărțit în module, puteți compila numai modulul în care s-au efectuat modificările.


Abilitatea de a lucra împreună la un proiect

Împărțirea programului în module permite mai multor programatori să lucreze la proiect simultan. De exemplu, un programator face programul principal, altele sunt angajate în biblioteci.

Variabilele globale ale unui modul nu vor fi vizibile în altul și invers. Pentru a utiliza o variabilă globală dintr-un alt modul, trebuie să scrieți cuvântul cheie extern înaintea acestuia.


cheie externă nesemnată pentru caractere = 0; // greșit. Va provoca o eroare!

Funcțiile declarate într-un singur modul vor fi disponibile în alte fișiere. Dar cu cuvinte cheie statice, regiunea de vizibilitate a unei funcții poate fi limitată de modulul în care este definită.

Încercarea de a utiliza această funcție într-un alt fișier va determina o eroare de compilare.

În programele anterioare, am folosit cuvântul cheie static. să declare o variabilă statică. Acum știi încă o aplicare a acestui cuvânt.

Teorie suficientă, vom continua.
Deschidem vechiul nostru proiect.
Creăm două fișiere în IARe - lcd_lib.h și lcd_lib.c.
Salvați fișierele din dosarul proiectului.
Adăugăm fișierul lcd_lib.c în proiectul nostru. (Faceți clic cu butonul din dreapta al mouse-ului pe spațiul de lucru și selectați Adăugare> Adăugare fișiere ...) din meniul deschis.
În lcd_lib.c, utilizați directiva include pentru a conecta fișierul antet -

În lcd_lib.h adăugăm linii

#ifndef LCD_LIB_H
#define LCD_LIB_H

#ifndef și #endif - directive de compilare condiționate. Pentru ce sunt? Să presupunem că avem un mare proiect, iar biblioteca noastră se conectează în mai multe locuri. Este posibil să existe o situație în care conținutul lcd_lib.h va fi inclus într-un fișier în mod repetat. Apoi, la compilarea proiectului, apare o eroare.

Pentru a evita acest lucru, o regulă pentru a încadra conținutul structurii fișierului antet de mai sus face. Când poticni Preprocessor pentru această înregistrare, se verifică dacă sunt sau nu constantă LCD_LIB_H este definită. În cazul în care nu este definit, acesta va determina sa (#define LCD_LIB_H) și va include conținutul unui fișier lcd_lib.h. Ei bine, în cazul în care este definită constanta, acesta nu va porni.


Acum avem un fel de achiziție și trebuie să-l umplem cu conținut.

lcd_lib.h este fișierul antet, partea de interfață a bibliotecii noastre. lcd_lib.c este fișierul de implementare. Pentru a fi mai clară, voi da un exemplu cu un televizor. De asemenea, are o interfață și o implementare. Interfața este butoanele de pe carcasa acesteia, cu care o putem activa, configura și selecta canale. O implementare este o colecție de plăci, componente și conexiuni între ele care asigură funcționarea televizorului. În calitate de utilizator final, nu mă interesează ceea ce este în interior, principalul lucru fiind că își îndeplinește funcțiile. Prin urmare, partea de interfață a televizorului nu trebuie să conțină detalii despre implementarea acestuia. Același lucru este valabil și pentru fișierul antet.

#include
#include

// portul la care este conectată magistrala de date LCD
#define PORT_DATA PORTD
#define PIN_DATA PIND
#define DDRX_DATA DDRD

// portul la care sunt conectate terminalele de control LCD
#define PORT_SIG PORTB
#define PIN_SIG PINB
#define DDRX_SIG DDRB

// Numerele de pin pe care sunt conectate bornele de control LCD
#define RS 5
#define RW 6
#define EN 7

Determinarea macro a frecvenței ceasului microcontrolerului

#define F_CPU 8000000

void LCD_Init (vid); // inițializarea porturilor și lcd
void LCD_WriteData (date despre caractere nesemnate); // imprimă un octet de date pe ecranul LCD
void LCD_WriteCom (date char nesemnate); // trimite comanda jkd

Observați că am redenumit numele tuturor funcțiilor. Acesta este unul dintre standardele de programare - pentru a adăuga un prefix numele funcțiilor cu numele fișierului bibliotecii. Biblioteca noastră este numită lcd_lib, așa că am adăugat LCD_ la numele funcțiilor. Această regulă simplă vă permite să determinați ce fișier conține implementarea funcției.

Macroane pentru lucrul cu biți și macro-uri pentru întârzieri în program

#define ClearBit (reg, bit) reg = (

(1<<(bit)))
#define SetBit (reg, bit) reg | = (1<<(bit))
#define _delay_us (ne) __delay_cycles ((F_CPU / 1,000,000) * (ne));
#define _delay_ms (ms) __delay_cycles ((F_CPU / 1000) * (ms));

Definiția tuturor funcțiilor

// funcția de a scrie o comandă
void LCD_WriteCom (date de caractere nesemnate)
ClearBit (PORT_SIG, RS); // setarea RS la 0 - comenzi
PORT_DATA = date; // transmite datele către magistrala indicatorului
SetBit (PORT_SIG, EN); // setarea E la 1
_delay_us (2);
ClearBit (PORT_SIG, EN); // setarea E la 0 - înregistrarea din față
_delay_us (40);
>

// funcția înregistrării datelor
void LCD_WriteData (date caracterele nesemnate)
SetBit (PORT_SIG, RS); // setați RS la 1 - date
PORT_DATA = date; // transmite datele către magistrala indicatorului
SetBit (PORT_SIG, EN); // setarea E la 1
_delay_us (2);
ClearBit (PORT_SIG, EN); // setarea E la 0 - înregistrarea din față
_delay_us (40);
>

// funcția de inițializare
void LCD_Init (vid)
DDRX_DATA = 0xff;
PORT_DATA = 0xff;
DDRX_SIG = 0xff;
PORT_SIG | = (1< ClearBit (PORT_SIG, RW);

_delay_ms (40);
LCD_WriteCom (0x38); // 0b00111000 - magistrală pe 8 biți, 2 linii
LCD_WriteCom (0xf); // 0b00001111 - afișare, cursor, pâlpâire
LCD_WriteCom (0x1); // 0b00000001 - ștergerea afișajului
_delay_ms (2);
LCD_WriteCom (0x6); // 0b00000110 - cursorul se mută spre dreapta, nu există schimbare
>

În principiu, totul este gata.
Salvăm ambele fișiere.
Conectăm biblioteca noastră la fișierul principal.c.

Îndepărtăm din toate acestea inutile. Și adăugați ieșirea cuvântului "Test".
Asta ar trebui să se întâmple.

#include
#include "lcd_lib.h"

Compilam proiectul ... Am trecut fără erori. Sper că și tu faci.

Ei bine, aceasta este structura noului nostru proiect.

Curs de instruire

ioavr.h și lcd_lib.h sunt conectate explicit la fișierul principal.c (în textul programului). Restul fișierelor antet sunt în principal din fișierul ioavr.h. Poți să urci pe ea pentru a vedea asta.

Am conectat lcd_lib.h, ioavr.h, intinsics.h la lcd_lib.c. Restul a fost conectat prin intermediul ioavr.h.

P.S .:
Dacă lucrați în WINAVR și proiectul dvs. este alcătuit din mai multe fișiere, compilatorul trebuie să le precizeze manual. Acest lucru se face în Makefile - introduceți doar numele fișierelor printr-un spațiu.

# Listați fișierele sursă C aici. (Dependențele C sunt generate generate.)
SRC = $ (TARGET) .c lcd_lib.c

Doar o persoană care se uită la main.c nu va ști unde a venit acest modul sau modul * .c. * .h este conectat, există prototipuri de funcții și unde găsim implementarea însăși este neclară. (dacă nu vă uitați la structura copacului din stânga, în IAR'e). Aceasta este întreaga întrebare. De ce în antet nu se semnează și funcțiile prototipului

Includerea fișierului de implementare în main.c nu are sens. Aceasta nu mai este o diviziune în module. Dacă nu sunteți pentru prima dată folosind mediul de dezvoltare, atunci veți ști unde să căutați fișierele de implementare. Fișierele de implementare se află, de obicei, în directorul proiectului.

Eu folosesc AVRSTUDIO_5.1. Eu studiază SI după Asma. Și nu a înțeles cu privire la proiect să ia un fișier lcd_lib.c. Am intrat în fișierul #include "lcd_lib.h", acest fișier a fost preluat. Și lcd_lib.c nu este prezent. Desigur, atunci când apelez funcția void LCD_Init (void); există o eroare spunând că aceasta este? Fișierul lcd_lib.c a fost pus pur și simplu în directorul proiectului în sine. Deci, cum faceți acest fișier lcd_lib.c, de asemenea, în proiect?

Articole similare