Incepand cu acest post vom incepe sa prezentam diverse experimente de la simplu spre complex, legate de utilizarea microcontrolerelor. De fiecare data vom utiliza acelasi microcontroller de tip 16F877A iar codul in limbaj de asamblare si schema electrica publicata va va da posibilitatea dumneavoastra de a repeta acasa experimentul cat si de a acumula intr-un mod cat mai placut, cat mai multe informatii legate de aceste dispozitive electronice.
Vom incepe cu modul de configurare a unui port pentru a deveni OUTPUT si de a il activa pentru a aprinde spre exemplu un LED.
Codul sursa, l-ati vazut ceva mai inainte in postul Primul cod in assembly
Il voi supune din nou atentiei dumneavoastra:

;**********************************************************************
;   This file is a basic code template for assembly code generation   *
;   on the PIC16F877A. This file contains the basic code              *
;   building blocks to build upon.                                    *
;                                                                     *
;   Refer to the MPASM User's Guide for additional information on     *
;   features of the assembler (Document DS33014).                     *
;                                                                     *
;   Refer to the respective PIC data sheet for additional             *
;   information on the instruction set.                               *
;                                                                     *
;**********************************************************************
;                                                                     *
;    Filename:	 led_01.asm                                           *
;    Date:                                                            *
;    File Version:                                                    *
;                                                                     *
;    Author:                                                          *
;    Company:                                                         *
;                                                                     *
;                                                                     *
;**********************************************************************
;                                                                     *
;    Files Required: P16F877A.INC                                     *
;                                                                     *
;**********************************************************************
;                                                                     *
;    Notes:                                                           *
;                                                                     *
;**********************************************************************
	list	p=16f877A	; list directive to define processor
	include <p16f877A.inc>  ; processor specific variable definitions

	__CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _HS_OSC & _WRT_OFF & _LVP_ON & _CPD_OFF

; '__CONFIG' directive is used to embed configuration data within .asm file.
; The lables following the directive are located in the respective .inc file.
; See respective data sheet for additional information on configuration word.
;***** VARIABLE DEFINITIONS
w_temp		EQU	0x7D		; variable used for context saving
status_temp	EQU	0x7E		; variable used for context saving
pclath_temp	EQU	0x7F		; variable used for context saving
;**********************************************************************

	ORG	0x000		     ; processor reset vector
  	goto	main                 ; go to beginning of program
main
	bsf     STATUS, RP0	     ;select bank 1
   	movlw 	b'11111110'	     ;load W with binary
	movwf	TRISB		     ;set PORTB,1 as output
	bcf	STATUS,	RP0	     ;select bank 0
	clrf	PORTB		     ;initializare PORTB
	bsf	PORTB,	0	     ;turn on RB0 only!
	end                          ;directive 'end of program'

list p=16f877A
Prima linie spune asamblorului pentru ce procesor trebuie sa faca asamblarea. Intotdeauna trebuie sa folositi directiva “list” la inceputul fisierului sursa.
Daca exista vreo diferenta intre aceasta directiva si setarile MPLAB atunci MPLAB va avertiza asupra acestui lucru si dv puteti corecta problema.
#include
Urmatoarea linie utilizeaza directiva “# include” care face apel la fisierul 16f877A.inc , aflat printre fisierele din directorul MPASM Suite, pentru a fi citit de catre asamblor.
Urmatoarea linie arata modul in care este configurat microcontrolerul:
__CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _HS_OSC & _WRT_OFF & _LVP_ON & _CPD_OFF
Aceasta linie trebuie sa fie scrisa intr-o singura linie in codul sursa.  Microcontrolerele au cateva “configuration words” adesea numite si “fuses”, care definesc un numar de aspecte de configurare a microcontrolerului. Aici:
_CP_OFF
Aceasta face sa fie dezactivata protectia la citire a codului. Protectia codului se face pentru a ascunde de competitori, informatiile continute intr-un MCU care este vandut . Daca se doreste acest lucru, atunci forma acestui fuse este sub forma:
_CP_ON
Atunci cand cineva doreste sa citeasca codul dintr-un MCU astfel protejat, va vedea doar Zero-uri.
_WDT_OFF
Inseamna Watchdog Timer OFF si asigura restartul automat al unui program care a esuat sau a trezi un MCU din “somn” atunci cand se afla in functionarea in consum redus.
Pentru perioada verificarilor si proiectarii aceasta functiune nu este utila si se prefera sa ramana disable.
_BODEN_OFF
Brown-out detection este disable. Functionarea MCU poate deveni nesigura atunci cand tensiunea de alimentare scade foarte mult. MCU are un circuit de detectie care il va reseta in situatii de
brown-out atunci cand este selectata varianta
_BODEN_OFF
_PWRTE_ON
Atunci cand este pornita alimentarea unui MCU acestuia ii trebuie ceva timp pana se stabilizeaza tensiunea de alimentare timp in care MCU este nesigur in functionare. Atunci cand este activata aceasta functiune, PIC-ul este tinut in reset pe o perioada de aproximativ 72 ms pana tensiunea atinge valori nominale. Este bine ca aceasta optiune sa ramana enable.
_HS_OSC  Stabileste ca semnalul de clock vine de la un oscilator cu quartz cu frecventa cuprinsa intre 4 si 20MHZ.
_WRT_OFF
_LVP_ON
_CPD_OFF
Protectia codului in Data memory (flash memory sau EEPROM) este pe off. Aceasta memorie nu isi pierde continutul la disparitia tensiunii de alimentare iar accesarea ei se face prin intermediul registrilor speciali. Daca specificam _CPD_ON, atunci EEPROM memory va fi proejata impotriva citirii de catre un programator. Dar EEPROM memory poate fi folosita pentru a pastra user data sau logged data, la care un utilizator trbuie sa aiba acces. Pentru a permite flexibilitate, memoria program si data (EEPROM) este protejata independent.
w_temp EQU 0x7D ; variable used for context saving
status_temp EQU 0x7E ; variable used for context saving
pclath_temp EQU 0x7F ; variable used for context saving
Urmatoarele trei linii reprezinta directive. Acestea inlocuiesc o valoare numerica cu un simbol. In acest fel, unor anumite locatii din memorie li se asigneaza un nume. In cazul nostru, pentru w_temp EQU 0x7D inseamna ca locatiei de memorie 07D, i se asigneaza numele w_temp. Aceste locatii sunt locatii definite temporar si sunt utilizate pentru salvari.
ORG 0x000 ; processor reset vector
ORG specifica de obicei locatia din program memory unde se afla plasata directiva respectiva. In acest caz vectorul de reset al procesorului se afla in locatia 0X00
goto main ; go to beginning of program
Instructiunea trimite la eticheta main, locul de inceput al programului.
main
Reprezinta locul de unde incepe executia propriu zisa a programului principal.
bsf STATUS, RP0 ; selectie bank 1
Asa cum stiti de acum instructiunile bcf si bsf sterg sau seteaza un bit din memorie. Operatiunea chiar daca pare simpla nu este pentru ca CPU va citi intregul byte, va opera modificarea si in final va rescrie intregul byte modificat, in locatia respectiva.
Aici, aceasta instructiune modifica valoarea bitului RP0 (bit5) din registrul STATUS care impreuna cu (RP1) bit 6 atrage dupa sine trecerea la registrii aflati in Bank1 de memorie.
movlw b’11111110′ ;  load W with binary
Sau cum ii spune si mnemonicul, move literal to W. Se incarca valoarea binara b’11111110′ in registrul W (working register)
movwf TRISB ; set PORTB,1 as output
Continutul registrului W este mutat in registrul f . In acest moment registrul are in el valoarea binara b’11111110′.In acest caz TRISB face ca pin port B0 al PORTB sa devina 0 (output) iar pin port B1-B7 sa devina 1 (input). In felul acesta am asignat un pin de microcontroler ca OUTPUT (iesire).
bcf STATUS, RP0 ; select bank 0
Este instructiunea complementara lui BSF prin care se face zero bitul RB0 (bit5). Aceasta face ca perechea RB5-RB6 sa formeze combinatia 00 corespunzatoare revenirii la registrii din bank1.
clrf PORTB ; initializare PORTB
Instructiunea face ca continutul registrului f in cazul nostru PORTB, sa fie sters ((bitii sai sa fie facuti zero) iar Z flag al registrului STATUS sa fie set.
Instructiunea este utila pentru a initializa complet continutul acestui registru.
bsf PORTB, 0 ; turn on RB0 only!
Este instructiunea complementara celei dinainte prin care se seteaza (se aduce in 1) bitul RB0 al registrului PORTB. Aceasta face ca sa aducem pe acest port, care stim ca este iesire, o tensiune corespunzatoare lui 1 logic, adica 5V.   Un LED conectat aici, desigur ca va lumina.
end ; directive ‘end of program’
Fiecare program trebuie sa fie incheiat prin utilizarea acestei directive. Numai la intalnirea acestei directive, asamblorul opreste compilarea.
Calculul rezistorului
Legat de modul de utilizare a pinilor microcontrolerului trebuie sa se stie ca si acestea suporta anumite valori limita, care nu este bine a fi depasite. Documentatia specifica toate astea in mod clar. Unul din parametri este curentul pe care un port configurat ca OUTPUT il poate furniza pentru situatia cand ele se afla cu nivel logic 1, sau il poate absorbi atunci cand se afla in nivel logic 0.
In ambele cazuri nu este deloc recomandata depasirea unui curent peste valoarea de 20mA.
Pentru situatiile cand este necesara comanda unor circuite de putere mai mare, se recurge la folosirea unor drivere corespunzatoare. Acestea pot fi transistoare, circuite integrate, relee s.a.
In cazul utilizarii unui LED pentru a evidentia starea pin portului B0 este suficienta limitarea curentului cu ajutorul unui rezistor avand valoarea de 220 Ohm.
Modul prin care ne-am decis aceasta cestei valoari se poate vede urmarind schema de mai sus:

In schema de mai jos avem doua porturi la care avem conectate LED-uri atat la +5V (Vdd) cat si la masa (Vss). In primul caz avem de a face cu situatia in care integratul absoarbe curent iar in cazul celui de al doilea port avem de a face cu o furnizare de curent prin dioda LED. Literatura foloseste pentru aceste doua cazuri termenii de Sink portrespectiv Source port
Stiind ca pentru ca un LED are nevoie de 1,9V si sa fie parcurs de aproximativ 10 mA pentru ca sa fie aprins (foaia de catalog), atunci facem cateva calculele inclusiv folosind legea lui Ohm:
Vr=Vdd-Vd= 5-1,9 =3,1V
Stim deci ca pe rezistor vor ramane 3,1 volti din cei 5 cu care se alimenteaza microcontrollerul.
cu pinul de OUTPUT aflat in 5 Volti. Aceasta ne ajuta sa aflam valoarea rezistorului de limitare a curentului:
R= Vr/Id =207 ohm. Cum aceasta nu este o valoare standardizata, vom alege una apropiata cai mare adica 220 Ohm.

Cu aceste ultime observatii nu ne ramane decat sa realizam montajul avand la indemana un PIC 16F877, un rezistor e 220 Ohm si un LED. Daca aveti construita placa de dezvoltare va este foarte simplu sa realizati montajul de mai jos  si dupa incarcarea fisierului, sa puteti verifica functionarea primului dumneavoastra  experiment:  Hello World!

LED_aplication

Acelasi efect se poate obtine inlocuind instructiunea:

       bsf	PORTB,	0	     ;turn on RB0 only!

cu intructiunile:

        movlw 	b'11111111'	     ;load W with binary 	
	movwf	TRISB		     ;set PORTB,1 as output

Prima intructiune incarca valoarea binara b’11111111′ in registrul W iar cea de a doua transfera continutul registrului W in registrul PORTB. Bitul B0 este 1 , deci acest bit port va avea valoarea 1 logic insemnand 5V pe OUTPUT, ce duce la aprinderea LED-ului montat la aceasta iesire.
|