PIC-zelfstudie - van registers tot onderbrekingen

Probeer Ons Instrument Voor Het Oplossen Van Problemen





Voordat we ingaan op de minutieuze details van PIC-programmering, is het belangrijk om eerst een paar goede programmeermethoden te leren.

Inzicht in registers

Stel dat u op een willekeurig punt in het programma een (puntkomma) typt, dan wordt alles wat na deze puntkomma komt door de compiler genegeerd, totdat de wagen natuurlijk weer in de positie staat.



De bovenstaande functie stelt ons in staat om opmerkingen of opmerkingen toe te voegen, zodat ze geen onderdeel van het programma worden, maar het ons wel gemakkelijker maakt om het programma te identificeren met behulp van de opmerkingen ernaast. Opmerkingen plaatsen is een aanbevolen praktijk tijdens het programmeren van een IC.

Het volgende belangrijke in de cursus is om namen toe te kennen aan de verschillende constanten (je zou ze later uitgebreid leren). Dit maakt het ook eenvoudiger om te begrijpen waarnaar wordt geschreven, of met betrekking tot de betrokken waarden, in plaats van te verwarren met de opgenomen nummers.



Het bovenstaande moet worden gedaan in de vorm van echte namen voor onmiddellijke herkenning, bijvoorbeeld COUNT, het zou belangrijk zijn op te merken dat hier alle hoofdletters worden gebruikt om het onderscheid te maken en ook aangeven dat het een constante waarde is.


Zoals we kunnen zien, wordt het bovenstaande gedaan in de vorm van een doos gemaakt van puntkomma's, waardoor het er alleen maar schoner uitziet. Probeer daarnaast het programma ook op papier te documenteren, deze oefening zal helpen om de dingen stapsgewijs te begrijpen.

2. De registers.

Het register binnen een PIC is een gebied dat geschreven gegevens accepteert en waar ook uit gelezen kan worden. U kunt het vergelijken met een vel papier waarop u de inhoud kunt visualiseren en ook kunt toevoegen door erover te schrijven.

De onderstaande afbeelding toont een typische registerbestandmap die is ingebed in een PIC16F84. Het formaat is niet iets dat feitelijk in de PIC is ingesteld, het is gewoon om aan te geven hoe de bits in de chip kunnen worden gerangschikt en om enkele van de betrokken commando's te begrijpen.

U kunt zien dat het in feite is onderverdeeld in Bank 0 en Bank 1. Bank 1 is verantwoordelijk voor het besturen van de feitelijke werking van de PIC, het belt bijvoorbeeld de PIC welke bits op poort A zijn toegewezen als invoer en welke als uitvoer.

Bank 2 is alleen bedoeld om de informatie te manipuleren.

Laten we dit begrijpen aan de hand van het volgende voorbeeld:

Stel dat we een bit willen toewijzen op PortA hoog. Hiervoor zouden we eerst naar Bank 1 moeten gaan om de gespecificeerde bit of pin in te stellen op poort A in de vorm van een output. Hierna keren we terug naar Bank 0 en leveren we een logische 1 (bit 1) op die specifieke pin.

De meest voorkomende registers die we graag zouden willen gebruiken in Bank 1 zijn STATUS, TRISA en TRISB.

STATUS helpt ons om terug te keren naar Bank 0, TRISA stelt ons in staat om te kiezen welke pinnen op poort A uitgangen zijn en welke ingangen kunnen zijn, terwijl TRISB het gemakkelijker maakt om te kiezen tussen uitgang en ingangspin op poort B. Het SELECT-register in BANK 0 stelt de gebruiker in staat. om naar Bank 1 te gaan.

Laten we het hele concept samenvatten met de volgende beschrijving:

TOESTAND:

Om over te schakelen van Bank 0 naar Bank 1 voeren we het STATUS-register in. Dit wordt geïmplementeerd door bit # 5 van het STATUS-register in te stellen op 1. Om terug te keren naar Bank 0, wijzen we bit 5 van het STATUS-register toe aan 0. Het STATUS-register bevindt zich op adres 03h, hier betekent h tat het nummer kan in hexadecimaal zijn.

TRISA en TRISB:

Deze bevinden zich navenant op adres 85h en 86h. Voor het programmeren van een pin als een output of een input, leveren we gewoon een nul of een een aan het betreffende bit in het register. Dit kan nu op twee manieren worden gedaan, via binair of hex. Als iemand de parameter niet kan converteren, kan hij of zij een wetenschappelijke rekenmachine gebruiken om de waarden te implementeren.

Nu hebben we 5 pinnen op poort A, wat overeenkomt met 5 pinnen. Als we van plan zijn om een ​​van de pinnen als ingangen te bevestigen, leveren we een '1' aan het betreffende bit.

Als we een van de pinnen als uitgangen wilden toewijzen, zouden we de specifieke pin op '0' zetten. De bits zijn hulp die exact overeenkomt met de bits, of preciezer: bit 0 is RA0, bit 1 zou RA1 zijn, bit 2 = RA2 enzovoort. Laten we het op deze manier begrijpen:

Stel dat u RA0, RA3 en RA4 als uitgangen wilt vastleggen, terwijl RA1 / RA2 als i / ps wilt vastleggen, dan doet u dit door 00110 (06h) te sturen. Kijk of bit 0 naar rechts is, zoals hier aangegeven:

Poort A Pin RA4 RA3 RA2 RA1 RA0

Bitnummer 4 3 2 1 0

Binair 0 0 1 1 0

Hetzelfde geldt voor TRISB.

PORTA en PORTB

Om een ​​van de uitgangspennen hoog te houden, bieden we gewoon een '1' aan voor de respectievelijke bit in ons PORTA- of PORTB-register. Een identieke procedure kan ook worden gevolgd voor TRISA- en TRISB-registers. Voordat we naar ons eerste voorbeeldcodering gaan, laten we eerst eens kijken naar een coupe van meer registers, namelijk: w en f.

W en F

Het W-register is een gewoon register waarmee u elke gewenste waarde kunt toekennen. Zodra u een magnitude aan W toewijst, kunt u doorgaan door deze aan een andere waarde toe te voegen of door deze gewoon te verplaatsen. Met een andere toegewezen waarde worden de details eenvoudigweg overschreven op W.

Het F-register stuurt zijn schriftelijke aangelegenheid door naar een register. We zouden dit F-register nodig hebben om een ​​waarde toe te kennen aan een register, mogelijk boven de STATUS- of de TRISA-registers, aangezien deze ons niet toelaten om de waarden er rechtstreeks overheen te plaatsen. Een voorbeeldprogramma

Laten we de volgende voorbeeldcode eens bekijken, die ons laat zien hoe de bovenstaande instructie wordt geïmplementeerd en die ook getuige zijn van enkele instructies in de cursus.

Laten we beginnen met het repareren van poort A zoals hierboven besproken.

Hiervoor moeten we overschakelen van Bank 0 naar Bank1, dit wordt gedaan door het STATUS-register op adres 03h, bit 5 naar 1, in te stellen.

BSF 03 uur, 5

De BSF betekent bitset F. We gebruiken twee nummers na deze instructie: 03h, dat het STATUS-registeradres is, en het nummer 5 dat overeenkomt met het bitnummer.

Dus wat we zeggen is 'Zet bit 5 in adres 03h op 1'.

We zijn nu in Bank 1.

MOVLW 00110b

We plaatsen de binaire waarde 00110 (de letter b betekent dat het getal in binair is) in ons algemene register W. Ik had dit natuurlijk in hex kunnen doen, in welk geval onze instructie zou zijn:

MOVLW 06h

Ofwel werkt. De MOVLW betekent ‘Verplaats letterlijke waarde naar W’, wat in het Engels betekent: plaats de waarde die volgt direct in het W-register.

Nu moeten we deze waarde in ons TRISA-register plaatsen om de poort in te stellen:

MOVWF 85h

Deze instructie geeft aan 'Verplaats de inhoud van W naar het registeradres dat volgt', in dit geval verwijst het adres naar TRISA.

Ons TRISA-register draagt ​​op dit moment het cijfer 00110, of wordt grafisch weergegeven:

Poort A Pin RA4 RA3 RA2 RA1 RA0

Binair 0 0 1 1 0

Invoer / uitvoer O O I I O

Dus nu hebben we onze Port A-pinnen, we moeten terugkeren naar Bank 0 om een ​​van de info aan te passen.

BCF 03 uur, 5

Met deze instructie wordt het omgekeerde van BSF bereikt. Het impliceert 'Bit Clear F'. Het paar getallen dat correspondeert, is het adres van het register, hier het STATUS-register, evenals het bitcijfer, in dit geval bit vijf. Wat we op dit moment precies hebben voltooid, is bit vijf op onze

STATUS register naar 0

We zijn op dit punt teruggekeerd in Bank 0.
Het volgende is de code in één blok:

BSF 03h, 5 Ga naar Bank 1
MOVLW 06h Zet 00110 in W
MOVWF 85h Verplaats 00110 naar TRISA
BCF 03h, 5 Kom terug naar Bank 0

In de laatste instructie hebben we u de manier bevestigd om de IO-poortpinnen op de PIC vast te stellen als invoer of uitvoer.

Laat me u tijdens deze cursus helpen om gegevens naar de poorten te verzenden.

Gegevens naar poorten verzenden

In de volgende tutorial zullen we voltooien door een LED aan en uit te laten knipperen die bestaat uit een complete programmadetails en een duidelijk schakelschema, zodat je de PIC precies kunt zien presteren zoals we verwachten.

Probeer uw PIC niet samen te stellen en te programmeren met de onderstaande resultaten, aangezien het slechts illustraties zijn. In eerste instantie zullen we poort A bit 2 instellen als een uitvoer:

Dit kan herkenbaar zijn aan de vorige instructie. Het enige verschil zou kunnen zijn dat we elk bit van de pinnen op A als uitvoer hebben gerepareerd door 0h aan het tri-state register te leveren. Dus wat hij nu moet doen, is een LED inschakelen.

We bereiken dit door een van de pinnen (die met de LED eraan gekoppeld) hoog te plannen. Om het anders te zeggen, passen we een ‘1’ toe op de pin. Dit is precies hoe het wordt uitgevoerd (let op de opmerkingen voor een verduidelijking voor elke regel):

Daarom hebben we nu bereikt dat we de LED een keer aan en uit zetten. Wat we willen is dat de LED daarna continu aan gaat.

Dit bereiken we door het programma terug te halen bij de start. We bereiken dit door in eerste instantie een tag aan te maken aan het begin van ons programma, en daarna het programma te informeren om daar weer verder te gaan. We specificeren een tag vrij eenvoudig.

We voeren een term in, zeg START, en typen vervolgens de code:

Zoals is aangetoond, noemden we in eerste instantie de uitdrukking ‘Start’ direct aan het begin van het programma.

Vervolgens noemden we helemaal aan het einde van het programma duidelijk ‘ga naar Start’. De ‘ga naar’ -instructie voert precies uit wat het aangeeft.

Dit programma schakelt de LED consequent aan en uit wanneer we het circuit inschakelen, en neigt uit te schakelen zodra we elektriciteit verwijderen. Misschien moeten we ons programma nog een keer bekijken:

We hebben de opmerkingen zeker weggelaten, maar we kunnen nog steeds de instructies en de cijfers volgen.

Dit kan later een beetje verwarrend zijn als u probeert problemen met het programma op te lossen en tijdens het schrijven van de code alle adressen uit het hoofd leert.

Hoewel de commentaren alsnog geplaatst kunnen worden, kan het een beetje rommelig worden. Dit vereist het benoemen van de nummers en kan worden bereikt door een aanvullende instructie: 'equ' De instructie 'equ' suggereert dat sommige dingen gelijk kunnen zijn aan andere dingen.

Het is misschien geen instructie voor PIC, maar voor de assembler. Deze instructie vergemakkelijkt het toewijzen van een naam aan een registeradreslocatie, of een constante aan een programmeerterm.

We zullen een paar constanten voor ons programma vaststellen en ook zien hoe eenvoudig het is om het programma te lezen.

Sinds we de constante waarden hebben vastgesteld, kunnen we doorgaan door ze in ons programma in te stellen. De constante waarden moeten worden aangegeven voordat ze worden gebruikt.

Plaats ze daarom altijd aan het begin van het programma. We herschrijven het programma zonder de commentaren nogmaals, om de eerdere labeling met de laatste te vergelijken.

Wellicht merkt u op dat de constanten het programma iets gemakkelijker laten begrijpen, maar we zijn nog steeds zonder commentaar, geen zorgen, aangezien we nog niet klaar zijn.

Er kan een klein nadeel zijn van ons knipperende LED-programma.
Elke instructie heeft 1 klokreeks nodig om te voltooien. Als we een 4MHz-kristal gebruiken, vraagt ​​elke instructie om 1 / 4MHz of 1uS om te voltooien.

Omdat we slechts vijf instructies hebben gebruikt, zou de LED na 5uS activeren en vervolgens uit gaan. Dit kan voor mensen veel te snel zijn om op te merken, bovendien zal het lijken alsof de LED volledig brandt.

Wat we in plaats daarvan zouden moeten bereiken, is een remming creëren tussen het inschakelen van de LED en het uitschakelen van de LED. De theorie van de remming is dat we aftellen vanaf een eerdere hoeveelheid, dus als het nul wordt, stoppen we met tellen.

De nulwaarde geeft het einde van de vertraging aan en we blijven ons proces gedurende het hele programma doorwerken. Daarom moeten we allereerst een constante bepalen die we als onze teller kunnen gebruiken.

Laten we deze constante COUNT noemen. Daarna moeten we bepalen hoe belangrijk een getal is om te beginnen met tellen. Zeker, het grootste cijfer dat we zouden kunnen opnemen is 255, of FFh in hex., Zoals ik in de eerdere tutorial heb besproken, wijst de equ-instructie een uitdrukking toe aan een registersituatie.

Dit houdt in dat, ongeacht de hoeveelheid die we onze COUNT toewijzen, deze overeenkomt met de items van een register. Als we proberen de waarde FFh aan te duiden, krijgen we een foutmelding zodra we het programma hebben gecompileerd.

De reden hiervoor is de locatie FFh, dat we er daarom geen toegang toe kunnen krijgen. Hoe moeten we daarom een ​​echt getal aanduiden? Het vereist zeker een kleine hoeveelheid lateraal nadenken.

Als we bijvoorbeeld onze COUNT aan het adres 08h toewijzen, zou dit een objectieve basisregisterbestemming aangeven. Standaard zijn de ongerepte gebieden ingesteld op FFh. Als COUNT dus leidt tot 08h, zult u de waarde van FFh tegenkomen terwijl we voor het eerst opstarten. Desalniettemin, ik u, hoe kunnen we COUNT vastleggen op een ander nummer? Alles wat we toepassen is eerst een taxatie ‘verplaatsen’ naar deze bestemming.

Als een illustratie, stel dat we zouden willen dat COUNT een waarde van 85h zou hebben, dan kunnen we COUNT equ 85h niet noemen, aangezien dat de positie is van ons Tri-State register voor poort A. Wat we precies bereiken is het volgende: movlw 85h de waarde van 85h in het W-register movwf 08h

Verplaats het nu naar ons 08h-register. Als we vervolgens COUNT equ 08h uitdrukken, komt COUNT overeen met de waarde 85h. Delicaat, is het niet! Daarom bepalen we in eerste instantie onze constante: COUNT equ 08h Daarna moeten we deze COUNT met één verminderen totdat het nul wordt.

Het komt gewoon zo voor dat er één instructie bestaat die is ontworpen om dit voor ons te bereiken, door gebruik te maken van een ‘goto’ en een tag.

De instructie die we gaan toepassen is: DECFSZ COUNT, 1 Deze instructie stelt ‘Verlaag het register (hier is het COUNT) met het nummer dat de komma volgt. Als we nul bereiken, spring dan twee plaatsen vooruit. ’Laten we het eerst in actie vinden, voordat we het op onze koers plaatsen.

Wat we hebben uitgevoerd is in eerste instantie onze constante COUNT tot 255 instellen. Het daaropvolgende segment positioneert een tag, genaamd LABEL, dichtbij onze decfsz-instructie.

De decfsz COUNT, 1 vermindert de waarde van COUNT met één en behoudt het eindresultaat rechtstreeks in COUNT. Bovendien controleert het of COUNT de waarde 0 heeft.

Als dit niet het geval is, wordt het programma in dat geval getriggerd om naar de volgende regel te gaan. Nu hebben we een ‘goto'-verklaring die ons terugbrengt naar onze decfsz-instructie.

In het geval dat de waarde van COUNT gelijk presteert, resulteert de decfsz-instructie in ons programma om 2 plaatsen vooruit te springen, en wordt verzonden naar waar we hebben geclaimd ‘Ga hier verder’.

Daarom, aangezien u kunt observeren, hebben we ervoor gezorgd dat het programma een vooraf bepaalde tijd op één plek blijft zitten voordat we verder gaan. Dit zou een vertragingslus kunnen worden genoemd.

Inzicht in vertragingslussen

Als we een grotere vertraging nodig hebben, kunnen we de ene lus voor de volgende volgen. De extra loops, hoe langer de vertraging. Laten we er tenminste twee hebben, ervan uitgaande dat we de LED-flitser willen observeren. We zullen deze vertragingslussen in ons programma plaatsen en dit bereiken door het een echt programma te maken door opmerkingen in te voeren:

Het is mogelijk om dit programma te compileren en daarna de PIC te programmeren. Zorg er natuurlijk voor dat u het circuit probeert om te controleren of het inderdaad werkt. Het volgende is een schakelschema dat u moet construeren zodra u de PIC heeft geprogrammeerd.


Goed gedaan, je zou eigenlijk je eerste PIC-programma kunnen hebben samengesteld, en ook een circuit kunnen hebben geconstrueerd om een ​​LED aan en uit te laten knipperen. Als u deze cursussen hebt gevolgd, heeft u tot nu toe in totaal zeven van de 35 instructies geleerd, maar tot nu toe bestuurt u wellicht de I / O-poorten!

Zou u proberen de vertragingslussen te wijzigen om de LED-flits sneller te laten knipperen - wat lijkt de minimale waarde van COUNT om in wezen de LED-flitser te zien? Of misschien wilt u een derde of aanvullende vertragingslussen toevoegen na de eerste om de LED te stabiliseren. een unieke constante voor elke vertragingslus.

Je zou dan mogelijk kunnen friemelen met je vertragingslussen om de LED-flitser met een bepaalde snelheid weer te geven, bijvoorbeeld na een seconde. Laten we in de volgende instructie zien hoe we iets dat bekend staat als een subroutine kunnen gebruiken om het programma compact en eenvoudig te houden. Een subroutine is een integraal onderdeel van de code of het programma waarnaar kan worden verwezen en wanneer u het nodig heeft. Subroutines worden gebruikt in gevallen waarin u dezelfde functie vaak uitvoert.

Wat zijn subroutines

De voordelen van het gebruik van een subroutine zijn dat het waarschijnlijk eenvoudiger zal zijn om de waarde eenmaal binnen een subroutine te wijzigen in plaats van bijvoorbeeld tien keer in uw hele programma, en het draagt ​​ook enorm bij aan het verminderen van het geheugenniveau dat uw programma in de PIC. We zullen een subroutine bekijken:

In eerste instantie moeten we onze subroutine een aanduiding geven, en in deze situatie hebben we ROUTINE geselecteerd. We typen daarna de code die we normaal zouden willen uitvoeren. Daarom hebben we de vertraging geselecteerd in ons knipperende led-programma. Ten slotte sluiten we de subroutine af door de RETURN-instructie in te toetsen.

Om de subroutine overal in ons programma te starten, typen we snel de instructie CALL en vervolgens de subroutine-aanduiding.

We zullen dit wat dieper bespreken. Zodra we aankomen bij het gedeelte van ons programma dat CALL xxx, waarin xxx de naam is van onze subroutine, springt het programma naar elke plek waar de subroutine xxx is geïnstalleerd. De instructies in de subroutine worden uitgevoerd.

Telkens wanneer de instructie RETURN is voltooid, springt het programma terug naar ons hoofdprogramma naar de instructie volgend op onze CALL xxx instructie.

Het is mogelijk om de vergelijkbare subroutine meerdere keren aan te roepen, wat verklaart waarom het gebruik van subroutines de algemene duur van ons programma verkort.

Desalniettemin zijn er een aantal factoren die u moet weten. In eerste instantie, net als bij ons hoofdprogramma, moeten alle specifieke constanten worden erkend voordat u ze kunt gebruiken.

Deze kunnen mogelijk worden erkend binnen de subroutine zelf, of direct aan het begin van het hoofdprogramma. Ik stel voor dat je alles erkent aan het begin van je hoofdprogramma, aangezien je dan erkent dat de zaken in een identieke positie verkeren. Vervolgens moet men ervoor zorgen dat het hoofdprogramma de subroutine overslaat.

Wat ik hiermee bedoel, is dat als je de subroutine direct aan het einde van je primaire programma plaatst, behalve als je een 'Ga naar'-verklaring gebruikt om weg te springen van waar de subroutine zich bevindt, het programma zou doorgaan en de subroutine zou implementeren, ongeacht of je vereisen het aan of anderszins.

De PIC zou geen onderscheid maken tussen een subroutine en het hoofdprogramma. We zullen ons knipperende led-programma bekijken, maar deze keer gaan we gebruik maken van een subroutine voor de vertragingslus. In het ideale geval zult u ontdekken hoeveel minder gecompliceerd het programma lijkt, en ook zult u ontdekken hoe de subroutine praktisch toepasbaar is.

Uiteindelijk kun je zien dat we de afmetingen van het programma mogelijk hebben verkleind door een subroutine te gebruiken voor onze vertragingslus.

Elke keer dat we een vertraging wensen, mogelijk wanneer de LED aan of uit is, noemen we in feite de vertragingssubroutine. Aan het einde van de subroutine leidt het programma terug naar de regel volgens onze 'Oproep'-instructie. In de bovenstaande afbeelding zetten we de LED aan.

We nemen daarna contact op met de subroutine. Het programma komt dan terug zodat we de LED kunnen uitschakelen. We noemen de subroutine nogmaals, voor het geval de subroutine zou zijn voltooid, komt het programma terug en de daaropvolgende instructie die het herkent, is ‘goto Start’. Voor iedereen die misschien geïntrigeerd is, was ons eerste programma 120 bytes lang.

Door het gebruik van de subroutine konden we onze programmagrootte terugbrengen tot 103 bytes. Dit klinkt misschien niet zo fantastisch, maar gezien het feit dat we in totaal slechts 1024 bytes in de PIC hebben, profiteert elke kleine hoeveelheid ervan.

Laten we in de volgende instructie het lezen van de poorten bekijken.

Tot nu toe hebben we gecomponeerd naar poort A om een ​​LED aan en uit te kunnen schakelen. Op dit punt zullen we zien hoe we de I / O-pinnen op de poorten gaan lezen.

Invoer- / uitvoerpoorten lezen

Dit is precies om ervoor te zorgen dat we een extern circuit kunnen koppelen en alle specifieke outputs die het biedt, kunnen beïnvloeden.

Mocht u onthouden van onze eerdere cursussen, als u de I / O-poorten wilt instellen, moesten we van Bank 0 naar Bank 1 springen. We zullen dat aanvankelijk bereiken:

Op dit punt hebben we bit 0 van poort A vast om in te voeren. we moeten nu onderzoeken of de pin hoog of laag is. Om dit te bereiken, kan men slechts een van de twee instructies gebruiken:

BTFSC en BTFSS.

De BTFSC-instructie betekent ‘Doe een bit-test op het register, evenals een bit die we aanwijzen.

Is het een 0, dan laten we de volgende instructie weg ’. BTFSS impliceert ‘Doe een bit-test in het register en het bit dat we vaststellen. Als het is ingesteld op een 1, dan slaan we de volgende instructie over.

Welke we gebruiken, wordt bepaald door precies hoe we willen dat ons programma reageert terwijl we de input bestuderen. Ter illustratie: in het geval dat we wachten tot de invoer een 1 is, kunnen we de BTFSS-instructie op de volgende manier gebruiken:

Code hier:

BTFSS PortA, 0 Ga naar start Ga hier verder:

Het programma zou gewoon verschuiven naar ‘Ga door hier’ op voorwaarde dat bit 0 op PortA is gepland naar een 1.

We zullen momenteel een programma schrijven dat een LED met één snelheid kan oproepen, maar als een schakelaar beperkt is, zou de LED twee keer zo langzamer knipperen.

Het is mogelijk om dit programma alleen uit te oefenen, maar toch hebben we de lijst op de een of andere manier opgenomen.

Je zou kunnen proberen om het hele programma te schrijven, om te controleren of je de principes hebt begrepen. We zullen het equivalente circuit gebruiken zoals voorheen, met de opname van een schakelaar RA0 van de PIC en de positieve rail van onze voeding.

Wat we hier hebben bereikt, is het inschakelen van de LED. Ik bepaal vervolgens of de schakelaar is uitgeschakeld.

In het geval dat het beperkt is, maak ik vervolgens verbinding met onze vertragingssubroutine. Dit levert ons dezelfde vertraging op als voorheen, maar we nemen op dit moment twee keer contact op.

Hetzelfde geldt wanneer de LED uit is. In het geval dat de schakelaar niet dicht is, dan hebben we onze eerdere in- en uitschakelperiodes vastgelegd.

Volg je deze lessen vanaf het begin, dan zou je kunnen proberen te begrijpen dat je momenteel tien van de 35 instructies voor de PIC 16F84 hebt ontdekt! En elk stukje hiervan wordt toevallig geleerd door alleen een LED aan en uit te zetten.

Tot nu toe hebben we de PIC samengesteld, knipperend een LED aan en uit.

Vervolgens waren we in staat om met onze PIC een schakelaar op te nemen, dus de flitssnelheid te variëren.

Geheugenruimte efficiënt gebruiken

Het enige probleem is dat het programma behoorlijk lang is en nogal inefficiënt qua geheugenruimte. Het leek oké terwijl ik de commando's voor het eerst opnam, maar er zou een gemakkelijkere manier moeten zijn om het uit te voeren. Positief is dat, we zullen analyseren hoe we de LED letterlijk aan en uit zetten.

movlw 02hmovwf PORTAmovlw 00hmovlw PORTA

Eerst vulden we ons w register met 02h, daarna stuurden we het naar ons PortA register om de LED aan te zetten. Om het uit te schakelen, hebben we w ingepakt met 00h, waarna het naar ons PortA-register werd verplaatst.

Tussen al deze routines door waren we genoodzaakt om contact op te nemen met een subroutine om ervoor te zorgen dat we de LED konden zien knipperen.

Daarom moesten we een paar keer twee sets informatie overbrengen (een keer naar het w-register en dan naar PORTA) en moesten we ook twee keer een subroutine aanroepen (een keer voor aan en een keer voor uit). Dus hoe kunnen we dit bereiken met extra efficiëntie? Erg makkelijk.

We gebruiken een andere instructie die bekend staat als XORF. De XORF-instructie werkt een exclusieve OF-functie op het register die we bepalen met de informatie die we verstrekken. Ik denk dat ik moet verduidelijken wat in de wereld een exclusieve OK is voordat we verder gaan. Als we twee ingangen en één uitgang hebben, kan de ingang alleen een 1 zijn als en zolang de twee ingangen verschillen. Hoewel ze hetzelfde zijn, is de uitvoer waarschijnlijk 0. Het volgende is een waarheidstabel voor individuen die ervoor kiezen om deze te bekijken:

A B F0 0 00 1 11 0 11 1 0

We zullen nu kijken wat er gebeurt als we B weergeven zoals onze eerdere uitvoer, en simpelweg de waarde van A wijzigen:

A B F
0 0 0
0 0 0
1 0 1
1 1 0
1 0 1

Als we de waarde van A hetzelfde houden als 1, en we Exclusief OF met de uitvoer, zou de uitvoer schakelen. Als u dit niet kunt opmerken aan de hand van de waarheidstabel, kunt u het hieronder zien met behulp van binair:

0 Stroomuitgang
EX-OR met 1 1 nieuwe output
EX-OR met 1 0 nieuwe output

Misschien kun je dat vinden door de uitvoer exclusief te ordenen met 1, we nu de uitvoer schakelen van 0 naar 1 naar 0.
Om onze LED aan en uit te zetten, hebben we dus maar een paar zinnen nodig:

MOVLW 02h
XORWF DEUR, 1

Wat we precies zullen bereiken, is het toevoegen van ons w-register met 02h. Wij zijn in dat geval Exclusief OF dit nummer te gebruiken ongeacht wat er op onze PortA staat. In het geval dat bit 1 een 1 is, zal het veranderen in een 0. In het geval dat bit 1 een 0 is, zal het veranderen in een 1. Laten we deze code een of twee keer bekijken om te laten zien hoe het binair draait:

DEUR
00010
xorwf 00000
xorwf 00010
xorwf 00000
xorwf 00010

We hoeven niet elke keer dezelfde waarde in ons w-register te laden, daarom is het mogelijk om dit een keer aan het begin te doen en gewoon terug te springen naar ons wisselcommando. Bovendien hoeven we geen waarde vast te leggen in ons PortA-register. De reden? Zeker, aangezien het bij het opstarten een 1 is, kunnen we deze gemakkelijk omschakelen. Ik, als alternatief een 0 bij het opstarten, zouden we het nu zelfs omschakelen.

Daarom zou je onze nieuw gevormde code willen zien. De eerste vertegenwoordigt onze knipperende LED-code, terwijl de tweede de code met de toevoeging van de schakelaar toont:

Ik zou willen dat je dat kunt vinden door simpelweg gebruik te maken van één eenvoudige instructie, we nu de schaal van ons programma hebben verkleind. De waarheid is dat, om aan te tonen hoeveel we onze programma's zouden kunnen verminderen, we de twee programma's hebben gedemonstreerd, wat er precies was samengesteld en hun afmetingen in de onderstaande tabel:

Program Alter Dimensions (bytes)
Knipperende LED Origineel 120
Knipperende LED Subroutine Toegevoegd 103
Knipperende LED XOR-functie gebruikt 91
LED Met Schakelaar Origineel 132
LED met schakelaar XOR-functie gebruikt 124.

Daarom hebben we niet alleen een paar nieuwe instructies ontdekt, maar zeker ook de omvang van onze scripting verkleind!

Hieronder zullen we analyseren hoe u individuele bits kunt wiebelen, bepaalde eenvoudige rekenkundige bewerkingen kunt uitvoeren, evenals gegevenstabellen.

Logische managers

In de laatste tutorial heb ik de exclusieve OR-bewerking gepresenteerd. De ExOR-functie wordt opgevat als een logische operator.

In deze tutorial zal ik de extra logische operatoren die de PIC promoot, toelichten. Puntprogramma's zullen geen enkel geval zijn, maar we zullen eenvoudige methoden leren om de operatoren te gebruiken door kleine stukjes code toe te passen.

AND De AND-functie analyseert in feite twee bits en levert een 1 op of ze hetzelfde zijn, en een 0 als ze onderscheidend zijn. Als we bijvoorbeeld 1 AND 1 noemden, is de uitkomst 1, terwijl als we 1 AND 0 declareren, de consequentie 0 zou zijn.

Onnodig te zeggen dat we ook in staat zijn om woorden te evalueren, evenals alle EN-functies die worden bereikt door de twee termen beetje bij beetje te herzien. Het onderstaande voorbeeld laat zien dat twee 8-bits woorden samen met het product een AND worden gemaakt:

11001011
EN 10110011
Is gelijk aan 10000011

Ik hoop dat u het ermee eens bent, het resultaat zal gewoon een 1 hebben wanneer 2 1s hand in hand met elkaar in het paar woorden. We kunnen de AND-functie gebruiken om bijvoorbeeld de poorten te verifiëren.

In het geval dat we een paar I / O-pinnen controleren die aan een circuit zijn gekoppeld, en we een bepaalde situatie in de gaten moeten houden waarin slechts een paar pinnen hoog zijn, in dat geval kunnen we vrijwel de port, waarna EN het resultaat met de conditie waarnaar we hebben onderzocht, identiek is aan de bovenstaande instantie.

De PIC biedt ons twee ingrediënten voor AND.
Het zijn ANDLW en ANDWF. ANDLW stelt ons in staat een AND-functie uit te voeren met de gegevens van het W-register en een door ons vast te stellen bedrag.

De syntaxis is: ANDLW waarin is precies wat we gaan EN de inhoud van W met.

Het gevolg van de AND-functie zou direct in het W-register worden opgeslagen.
ANDWF stelt ons in staat een AND-functie uit te voeren op het W-register en een ander register, bijvoorbeeld een PORT. De syntaxis is: ANDWF, d waarin het register is waar we enthousiast over zijn, bijv. PORTA, en d toont de PIC waar u het resultaat moet plaatsen. Als d = 0, wordt de uitkomst in het W-register geplaatst en van d = 1 wordt het eindresultaat opgeslagen in het door ons bepaalde register. De twee onderstaande delen van de code geven een goed voorbeeld van elke EN-functie weer.

De eerste is het onderzoeken van de status van de PORTA, waarin we moeten controleren of de inputs 1100 zijn. We kunnen de uitkomst terug in het W-register plaatsen

movlw 1100
ANDWF 05h, 0 De tweede illustratie kan nu de inhoud van het W-register verifiëren:
ANDLW 1100

OF

We hebben inmiddels één OR-functie ontdekt, om precies te zijn de XOR. Dit ontwikkelt zich tot een 1 als twee bits niet hetzelfde zijn, maar wel verschillend. U kunt een andere OR-functie vinden met de naam IOR, de inclusieve OR. Deze functie genereert een 1 in het geval een van beide bits een 1 is, maar bovendien als elke bit 1 is. Hieronder staat een duidelijke waarheidstabel om dit te illustreren:

A B O / P
0 0 0
0 1 1
1 0 1
1 1 1

Wat zijn rekenkundige operatoren

TOEVOEGEN

Deze functie bereikt wat gewoonlijk wordt beweerd. Het draagt ​​twee cijfers bij! Als het gevolg van het optellen van de twee cijfers 8 bits overschrijdt, zal in dat geval waarschijnlijk een CARRY-vlag worden ingesteld. De CARRY-vlag bevindt zich op adres 03h bit 0.

Wanneer dit bit is gepland, hebben de twee cijfers 8 bits overtroffen. Als het een 0 is, bevindt het gevolg zich in dat geval binnen 8 bits. Net als voorheen levert de PIC ons twee ADD-stijlen, specifiek ADDLW en ADDWF. Zoals je misschien hebt aangenomen, lijkt dit op de bovenstaande functie. ADDLW biedt de inhoud van het W-register aan die wij bepalen. De syntaxis is: ADDLW ADDWF voeg de inhoud toe van het W-register en een ander register dat we aanwijzen.

De syntaxis is: ADDWF, d is waar

SUB

Op dit moment denk ik dat je niet kunt aannemen wat deze functie doet! Inderdaad, je vermoedde het, deze functie
trekt het ene bit van het andere af. Opnieuw biedt de PIC ons 2 smaken: SUBLW en SUBWF. De syntaxis is precies hetzelfde als voor de ADD-functie, behalve dat je blijkbaar SUB typt in plaats van ADD!

Toename Als we 1 tot een getal in de PIC wilden opnemen, zouden we absoluut gebruik kunnen maken van de ADD-functie, en de nummer één. ~ De moeilijkheid hierbij is dat we het cijfer eerst in het W-register moeten plaatsen en vervolgens de ADDLW 1-besturing moeten gebruiken om het te verhogen. Als we 1 in een register wilden opnemen, kan het nog erger zijn. We moeten eerst het nummer 1 in het W-register plaatsen, daarna ADDWF, 1 gebruiken. Om bijvoorbeeld 1 toe te voegen aan locatie 0C, zouden we bijvoorbeeld het volgende deel van het script moeten bezitten:

movlw 01
addwf 0c, 1

Er bestaat een eenvoudigere methode om dit uit te voeren. We kunnen het commando INCF uitoefenen. De syntaxis is: INCF, d waar, is het register of de plaats waar we ons zorgen over maken, en d toont de PIC waar je de uitkomst moet plaatsen. In het geval d = 0, is de uitkomst binnen het W-register, en in het geval d = 1, wordt het gevolg vastgelegd in het register dat we hebben bepaald.

Door gebruik te maken van deze individuele instructie zijn we in staat om daadwerkelijk vijftig procent van de codering te doen. Als we wilden dat het resultaat in het W-register werd hersteld, in dat geval met behulp van de bovenstaande instantie, hadden we misschien een extra commando moeten opnemen om de items van 0C terug te verplaatsen naar het W-register, waarna we het 0C-register weer op nee hebben gezet. wat het was.

Er bestaat een increment-commando. Het is INCFSZ. Dit commando kan het register verhogen dat we bepalen, maar als we het register gelijk zijn aan 0 na de toename (dat zal gebeuren terwijl we 1 tot 127 opnemen), zal de PIC daarna waarschijnlijk de volgende instructie overslaan. Het onderstaande gedeelte van de code weerspiegelt dit:

Lus incfsz 0C
Ga naar Loop


Rest van programma.

In het bovenstaande gedeelte van de code wordt 0C opgehoogd met 1. Vervolgens hebben we een instructie die de PIC informeert om terug te keren naar onze tag met de naam Loop, en 0C opnieuw met 1 te verhogen. Dit gaat door totdat 0C gelijk is aan 127. In deze omstandigheid, wanneer we 0C met 1 verhogen, komt 0C nu overeen met 0. Onze INCFSZ-instructie zou de PIC heel goed kunnen informeren om de volgende instructie weg te laten, wat in dit geval de goto-declaratie is, daarom zal de PIC doorgaan met de rest van het programma.

Afname

We hebben de verlagingsfunctie nu in eerdere trainingen besproken, daarom zal ik het niet meer herzien.

Aanvulling

De laatste instructie in deze discussie zou elk bit in het register dat we bepalen, omkeren. De syntaxis is: COMF, d waarin

Bit-bewerkingen begrijpen

Dit zou bijvoorbeeld kunnen worden gebruikt om de pinnen van een poort snel van output naar input te wisselen, enzovoort. Met bitfuncties kunnen we een enkele bit binnen een uitdrukking vormen. Ze stellen ons in staat om door te gaan, enkele bits in te stellen en te verwijderen in registers of getallen die we bepalen.

Aan het einde van deze cursus zullen we een programma onthullen dat is ontworpen om een ​​reeks opeenvolgende lichten te creëren die vooruitgaan en vervolgens omgekeerd. We hebben dit eerder waargenomen toen we de exclusieve OF-functie onderzochten, waarbij we de poorten exclusief met een expressie OR-den. We hebben tot nu toe een paar bit-functies opgemerkt toen we de poorten op de PIC tot stand brachten, en

Ik herhaal hun gebruik hier.

BCF

Deze instructie zal een stukje wegvagen dat we vastleggen in een register dat we aanwijzen. De syntaxis
is:
BCF,

We hebben dit eerder gebruikt om van pagina 1 naar pagina 0 te gaan door een bit uit het STATUS-register te verwijderen. We kunnen het ook gebruiken om een ​​bit op 0 te zetten in elk ander register / locatie. Als we bijvoorbeeld de 3e bit in 11001101, opgeslagen in sectie 0C, op 0 willen zetten, kunnen we
invoegen:

BCF 0C, 03

BSF

Deze instructie zou elk bit dat we voorschrijven repareren in 1 in elk register dat we aangeven. We hebben dit eerder gebruikt om van pagina 0 naar pagina 1 te gaan. De syntaxis is: BSF ,, en wordt op precies dezelfde manier gebruikt als BCF hierboven.

BTFSC Tot nu toe konden we een beetje instellen of wissen in een register. Maar stel je voor dat we in feite moeten controleren of een bit een 1 of een 0 is in een register?

Het is zeker mogelijk om BTFSC te gebruiken. Het vermeldt Bit Test Register F en Overslaan als het duidelijk is. Deze instructie gaat het bit analyseren dat we in het register aanwijzen. In het geval dat de bit een 0 is, zou de instructie de PIC informeren om de volgende instructie te omzeilen.

We zouden deze instructie kunnen gebruiken als we een vlag willen controleren, bijvoorbeeld de carry-vlag. Dit bespaart ons de noodzaak om het STATUS-register te lezen en naar de individuele bits te zoeken om te weten welke vlaggen zijn opgelost. 29 Als we bijvoorbeeld wilden controleren of de vlag Carry op 1 stond nadat we 2 cijfers hadden toegevoegd, dan konden we het volgende typen:

BTFSC 03 uur, 0
ga hier door indien ingesteld op 1
of hier indien ingesteld op 0

In het geval dat de status van de bit een 1 is, zou in dat geval de instructie volgend op BTFSC worden voltooid. Als deze is ingesteld op een 0, wordt de volgende instructie overgeslagen. Het volgende deel van de code laat zien waarin deze kan worden gebruikt:

Lus:


BTFSC 03,0
Ga naar Loop

In de bovenstaande code komt de PIC gewoon uit de lus in het geval bit 0 van het STATUS-register (of de Carry-vlag) wordt gedefinieerd als 0. Of anders wordt het goto-commando uitgevoerd.

BTFSS

Deze instructie vermeldt Bit Test Register F en Skip If Set. Dit kan vergelijkbaar zijn met de BTFSC-instructie, behalve dat de PIC de volgende instructie zou weglaten als de bit die we hebben geëvalueerd is ingesteld op 1 in plaats van 0.

CLRF

Deze instructie zou de volledige details van een register op 0 zetten. De syntaxis is:

CLRF
We hebben dit eerder gebruikt om de output van de Ports op 0 te zetten door CLRF 85h toe te passen. We hebben het bovendien gebruikt om de poorten zodanig te repareren dat alle pinnen naar uitvoer worden opgenomen door CLRF te gebruiken
05 uur.

CLRW

Dit zou kunnen lijken op de CLRF-instructie, behalve dat het W-register wordt gewist. De syntaxis is vrij eenvoudig:

CLRW

RLF en RRF

Deze richtingen zouden een bit in een register een enkele sleuf naar links (RLF) of rechts (RRF) in een register transporteren. Als we bijvoorbeeld 00000001 nodig hadden en we gebruikten RLF, in dat geval zouden we 00000010 kunnen hebben. Wat gebeurt er op dit moment als er 10000000 is en de RLF-instructie wordt toegepast? Zeker, de 1 zou in de draagvlag worden geplaatst. Als we de RLF-instructie nog een keer zouden toepassen, zou de 1 bij het begin weer verschijnen. Hetzelfde gebeurt echter in het tegenovergestelde voor de RRF-instructie. Het onderstaande geval toont dit voor de RLF-instructie, waarin we de 8 bits van een register kunnen zien, evenals de carry-vlag:

C 87654321
0 00000001
RLF 0 00000010
RLF 0 00000100
RLF 0 00001000
RLF 0 00010000
RLF 0 00100000
RLF 0 01000000
RLF 0 10000000
RLF 1 00000000
RLF 0 00000001

Voorbeeldprogramma

We gaan nu een voorbeeldcode zien die men kan compileren en besturen. Het zou een sequentielicht genereren dat begint bij PortA bit 0, gaat naar PortB bit 8 en
dan terugkeren.
Sluit LED's aan op elk van de poortpinnen. We zullen er een deel van hebben
procedures beschreven in deze tutorial.

TIME EQU 9FH Variabele voor de vertragingslus.
PORTB EQU 06H Poort B-adres.
TRISB EQU 86H Port B Tristate-adres.
PORTA EQU 05H Poort A-adres.
TRISA EQU 85H Port A Tristate adres.
STATUS EQU 03H Pagina selecteren register.
COUNT1 EQU 0CH Loop register.
COUNT2 EQU 0DH Loop register.

BSF STATUS, 5 Ga naar pagina 1
MOVLW 00H en ingesteld
MOVWF TRISB zowel poort A als B
MOVLW 00H voor uitvoer,
MOVWF TRISA en ga dan terug naar
BCF STATUS, 5 pagina 0.
MOVLW 00H Wis poort A.
MOVWF DEUR

Start van het hoofdprogramma

RUNMOVLW
01H Stel de eerste bitMOVWF in
PORTB op Port B.CALL
DELAY Wacht even
VERTRAGING
Verplaats de bit op poort B naar links en pauzeer dan.RLF
PORTB, 1CALL
UITGESTELDE OPROEP
DELAYRLF
PORTB, 1CALL
UITGESTELDE OPROEP
DELAYRLF
PORTB, 1CALL
UITGESTELDE OPROEP
DELAYRLF
PORTB, 1CALL
UITGESTELDE OPROEP
DELAYRLF
PORTB, 1CALL
UITGESTELDE OPROEP
DELAYRLF
PORTB, 1CALL
UITGESTELDE OPROEP
DELAYRLF
PORTB, 1CALL
UITGESTELDE OPROEP
DELAYRLF
PORTB, 1 Dit verplaatst het bit naar de draagvlag
Ga nu naar poort A en verplaats het bit naar links.RLF
PORTA, 1 Dit verplaatst de bit van de nulvlag naar PortACALL
DELAYCALL DELAYRLF
DEUR, 1 OPROEP
UITGESTELDE OPROEP
DELAYRLF
DEUR, 1 OPROEP
UITGESTELDE OPROEP
DELAYRLF
DEUR, 1 OPROEP
UITGESTELDE OPROEP
VERTRAGING
Verplaats het bit terug op poort ARRF
DEUR, 1 OPROEP
UITGESTELDE OPROEP
DELAYRRF
DEUR, 1 OPROEP
UITGESTELDE OPROEP
DELAYRRF
DEUR, 1 OPROEP
UITGESTELDE OPROEP
DELAYRRF
PORTA, 1 Dit verplaatst de bit naar de nulvlag. Verplaats nu de bit
terug op Port BRRF
PORTB, 1CALL
UITGESTELDE OPROEP
DELAYRRF
PORTB, 1CALL
UITGESTELDE OPROEP
DELAYRRF
PORTB, 1CALL
UITGESTELDE OPROEP
DELAYRRF
PORTB, 1CALL
DELAYCALL DELAYRRF
PORTB, 1CALL
UITGESTELDE OPROEP
DELAYRRF
PORTB, 1CALL
UITGESTELDE OPROEP
DELAYRRF
PORTB, 1CALL
UITGESTELDE OPROEP
VERTRAGING Nu zijn we terug waar we begonnen, GOTO
RUN laten we weer gaan.

Er is een geweldige optie in de trainingsset waarmee u gebruik kunt maken van een gegevenstabel.

Een gegevenstabel is slechts een lijst met gegevenscitaten, waarin alles wordt bekeken op basis van een paar overwegingen.
U kunt bijvoorbeeld een circuit hebben dat gebruikmaakt van een PIC die het aantal instanties telt dat een ingangspen in 1 seconde hoog wordt. Daarna kunt u het nummer tentoonstellen op een 7-segment-display.

Zodra de timing is gestart, begint de PIC met het tellen van het aantal keren dat de pin hoog gaat. Na 1 seconde bezoekt het de tafel en kijkt naar de gegevens, het moet het nummer op het scherm weergeven dat het aantal situaties symboliseert dat de pin hoog werd. Dit kan gunstig zijn, aangezien we pas bepalen wat het cijfer zou kunnen zijn als de PIC zijn schatting heeft gemaakt.

Door een tabel te gebruiken, kunnen we de PIC laten bepalen welke figuur moet worden afgebeeld. Op dit punt, voordat ik verder ga laten zien hoe de gegevenstabel werkt, moet ik je misschien vertellen dat de PIC het pad bewaart van de verblijfplaats in het programma terwijl het programma werkt.

Het vergemakkelijkt voor degenen die bepaalde programmering in BASIC hebben uitgevoerd. Maak je anders geen zorgen, misschien wil je doorgaan met het leren van de theorie. Stel je voor dat er een BASIC-programma is dat lijkt op het programma dat hieronder wordt weergegeven:

10 JAAR K = 0
11 K = K + 1
12 ALS K> 10 DAN GA NAAR 20 ANDERS GAAN 11
20 AFDRUKKEN K
21 EINDE

Het programma begint op regel 10. Zodra K op 0 staat, gaat het verder naar regel 11. Nadat we 1 tot K hebben opgenomen, gaan we verder naar regel 12.

Op dit punt zijn we misschien benieuwd of K hoger is dan 10. Als dat zo is, gaan we vervolgens naar regel 20, of anders keren we terug naar regel 11.

Lijn 20 documenteert de K en lijn 21 sluit het programma af. BASIC gebruikt lijnstatistieken om de programmeur te helpen bij het bijhouden van waar problemen zijn, aangezien labels niet zijn geautoriseerd. De PIC gebruikt labels om te ontsnappen tussen bestemmingen - of kan het echt?

We gebruiken de labels om ervoor te zorgen dat we op de hoogte zijn van waar de problemen zijn, en om ervoor te zorgen dat we de PIC op een eenvoudige manier kunnen informeren over waar ze kunnen zoeken.

Wat er precies gebeurt, is dat de PIC profiteert van een teller op de binnenlijn, een zogenaamde Program Counter. De Program Counter (afgekort tot PC) spoor van de geheugenbestemming waar de huidige instructie zich bevindt.

Telkens wanneer we de PIC informeren om een ​​geselecteerd label te bezoeken, begrijpt het de geheugenplek en vergroot daarom de pc totdat het die geheugenbestemming ziet. Dit is precies dezelfde methode als we het BASIC-programma hierboven bekijken. Hieronder ziet u een codesegment met de geheugenruimten of de items van de pc naast elke instructie:

PC Instructie0000 movlw 03
0001 movwf 0C
0002 Lus decfsc 0C
0003 ga naar Loop
0004 einde

In de demonstratie hierboven hebben we de pc gefixeerd op 0000. Hierop hebben we de instructie movlw 03. Wanneer de PIC deze gegevens heeft geïmplementeerd, verhoogt het de pc zodat de volgende instructie wordt gescand. Op dit punt bekijkt de PIC movwf 0C. De pc wordt opnieuw verhoogd.

Nu bestudeert de PIC decfsc 0C. In het geval dat de details van 0C niet 0 zijn, wordt in dat geval de pc opgehoogd met 1, evenals de volgende instructie, ga naar Loop, informeert de pc om terug te keren naar positie 0003, waar de genoemde Loop is. In het geval dat de details van 0C 0 zijn, dan wordt de PC geadviseerd om met 2 te verhogen, laat de volgende instructie gewoon weg.

Inzicht in gegevenstabellen

Dit plaatst de pc op positie 0004, waar het programma eindigt. De bestemmingen worden vastgesteld door de assembler en over het algemeen hoeven we ons geen zorgen te maken over wat de pc doet. Totdat we de behoefte vinden om het onder controle te krijgen, net als bij het gebruik van gegevenstabellen. De handigste manier om te beschrijven hoe een gegevenstabel werkt, is om te beginnen met een illustratie.

PC equ 02
movlw 03
oproep tafel

tabel addwf pc
retlw 01
retlw 02
retlw 03
retlw 04
retlw 05
retlw 06
retlw 07
terugkeer

De eerste instructie is om de label-pc het adres van de programmateller (02h) toe te wijzen. We zullen spoedig na het invoeren van de waarde van 03h in het w register zijn. We communiceren daarna met tafel. De voorste regel in de subroutinetabel vergroot de details van het W-register (03h) naar de programmateller.

Dit triggert de programmateller om met 3 te verhogen, of, anders gezegd, stimuleert de programmateller om 3 regels naar beneden te gaan. Terwijl de teller 3 regels lager arriveert, herkent de PIC de instructie retlw. Dit commando stuurt de waarde die erop volgt naar het W-register, waarna het terugkomt van de subroutine. RETLW betekent in feite Return, Letterlijk voor W.

Ik heb een komma achter het woord Return geplaatst. Omdat we ons in een subroutine bevinden, hebben we een Return-instructie nodig om deze op te halen. Daarom de RET in de instructie. Na de RETLW-instructie staat een nummer, en dit is precies wat er in het W-register wordt ingevoerd.

In dit geval is het het cijfer 3. We kunnen elke hoeveelheid aan het W-register toewijzen, zolang dit cijfer wordt gecombineerd met de Program Counter in de tabel-subroutine, gaan we een retlw-instructie ontdekken. In de bovenstaande illustratie houdt dit in dat we elk nummer van 1 tot 7 kunnen hebben. Als we verder gaan dan de subroutine, kunnen we misschien een extra deel van het programma afronden. Om deze reden is het meestal een slimme zet om de gegevenstabel precies tegen het einde van het PIC-programma te plaatsen, dus als we in dat geval doorschieten, komen we hoe dan ook tot het einde van het programma.

Het onderwerp onderbrekingen is misschien wel de langste en moeilijkste om door te nemen.

U kunt geen ongecompliceerde methode vinden om interrupts te detailleren, maar met een beetje geluk aan het einde van dit deel kunt u mogelijk interrupts in uw eigen programma's toepassen.
We hebben de sectie opgedeeld in 2 fasen. Dat is om het onderwerp in secties te kunnen scheiden, ook om u een handig overzicht te geven dat u gemakkelijk kunt begrijpen.

Wat is een onderbreking precies? Zoals de term aangeeft, is een interrupt zeker een techniek of een signaal dat een microprocessor / microcontroller verhindert wat hij uitvoert, dat er iets anders zou kunnen gebeuren.

Sta mij toe u een dagelijkse illustratie te geven. Denk dat u zich thuis ontspant en met iemand anders praat. Plots klinkt de telefoon.

Je stopt met praten en pakt de telefoon om met de beller te praten. Als u eenmaal telefonisch contact heeft gehad, besluit u terug te keren naar het gesprek met de persoon voordat de telefoon ging. Het is mogelijk om de belangrijkste routine te overwegen terwijl u met iemand praat, het overgaan van de telefoon kan uw conversatie verstoren, en de onderbreking van de routine is de methode om aan de telefoon te spreken.

Terwijl het telefoongesprek ten einde loopt, ga je terug naar je primaire chatroutine. Deze illustratie is precies hoe een processor een processor onderbreekt om actie te ondernemen.

Het primaire programma is in werking en voert een bepaalde functie uit in een circuit, maar als er een onderbreking plaatsvindt, stopt het primaire programma terwijl een andere routine wordt uitgevoerd. routine eindigt, keert de processor terug naar de primaire routine, net als voorheen.

Inzicht in onderbrekingen

De PIC beschikt over 4 storingsbronnen. Ze kunnen worden opgesplitst in een aantal groepen. Twee zijn bronnen van onderbrekingen die buitenwaarts naar de PIC kunnen worden gebruikt, terwijl de andere twee interne processen zijn. Laat me de twee externe typen hier verduidelijken. De andere twee zullen in verschillende tutorials worden beschreven zodra we bij timers aankomen en gegevens opslaan.

Als je de pin-out van de PIC bekijkt, zul je zien dat pin 6 RB0 / INT is. Op dit punt is RB0 duidelijk poort B bit 0. De INT geeft aan dat het net zo goed kan worden geconfigureerd als een externe interruptpin. Bovendien kunnen poort B pinnen 4 tot 7 (pinnen 10 tot 13) ook worden gebruikt voor interrupts. Voordat we de INT of een andere poort B-pinnen kunnen gebruiken, moeten we twee taken uitvoeren. Allereerst moeten we de PIC informeren dat we interrupts zullen gebruiken.

Vervolgens moeten we aangeven welke poort B-pin we gaan gebruiken als interrupt in plaats van als I / O-pin. In de PIC vind je een register dat bekend staat als INTCON, en is op adres 0Bh. In dit register ontdek je 8 bits die kunnen worden in- of uitgeschakeld. Bit 7 van INTCON staat bekend als GIE. Dit is de Global Interrngupt Enable. Door dit op 1 te zetten, wordt de PIC geïnformeerd dat we een interrupt zullen gebruiken.

Bit 4 van INTCON staat bekend als INTE, INTerrupt Enable. Door dit bit op 1 te zetten, wordt aan de PIC doorgegeven dat RB0 een interrupt-pin zal zijn. Het configureren van bit 3, genaamd RBIE, informeert de PIc dat we poort B bits 4 tot 7 gaan gebruiken. Op dit punt begrijpt de PIC wanneer deze pin hoog of laag kan zijn, moet hij stoppen met wat hij doet en doorgaan met een interrupt routine. Op dit punt moeten we de PIC informeren of de interrupt waarschijnlijk op de stijgende flank (0V tot + 5V) of de dalende flank (+ 5V tot 0V) transformatie van het signaal zal zijn.

Simpel gezegd, willen we dat de PIC elke keer dat het signaal van laag naar hoog of van hoog naar laag beweegt, onderbreekt. Door delinquentie kan dit worden vastgesteld om op de stijgende rand te worden geplaatst.

De 'triggering' van de rand is gepland in een extra register, het OPTION-register, op adres 81h. Het bit waar we enthousiast over zijn, is bit 6, ook wel INTEDG genoemd.

Als u dit op 1 instelt, wordt de PIC op de montagerand verstoord (standaardstatus) en als u dit op 0 instelt, wordt de PIC gestimuleerd om de glijrand te verstoren. Als je wilt dat de PIC aan de stijgende rand wordt geactiveerd, hoef je hier zeker niets aan te doen.

Op dit punt bevindt het optieregister zich helaas in bank 1, wat betekent dat we het leuk vinden om van bank 0 naar bank 1 te wijzigen, de bit in het optieregister in te stellen en daarna terug te keren naar bank 0. De sleutel hier is om elk bit te volbrengen van de Bank 1 registreert in een enkele slag, bijvoorbeeld het vaststellen van de poortpinnen, daarna keert u terug naar Bank 0 als u klaar bent.

Goed, daarom hebben we de PIC op de hoogte gesteld welke pin waarschijnlijk de interrupt zal zijn en waar de edge moet worden geactiveerd, wat gebeurt er in het programma en de PIC telkens wanneer de interrupt plaatsvindt? Er gebeuren een paar dingen. Allereerst is er een ‘vlag’ gepland.

Dit informeert de interne processor van de PIC dat er een onderbreking heeft plaatsgevonden. Vervolgens geeft de programmateller (waarover ik het had in de vorige tutorial) tips naar een specifiek adres binnen de PIC. Laten we deze allemaal snel afzonderlijk bekijken. Interruptvlag In ons INTCON-register is bit 1 de interruptvlag, genaamd INTF. Op dit punt, wanneer er een onderbreking optreedt, zal deze vlag waarschijnlijk worden vastgezet op 1.

Als er geen onderbreking is, wordt de vlag op 0 geplaatst. En dat is ook zo ongeveer alles. Op dit punt vraag je je misschien af ​​‘wat is het punt?’. Zeker, ook al staat deze vlag gepland op 1, de PIC kan en zal niet reageren op een andere onderbreking. Laten we daarom zeggen dat we een onderbreking teweegbrengen. De vlag zal waarschijnlijk worden vastgesteld op 1 en de PIC kan naar onze routine gaan om de interrupt te laten werken.

Als deze vlag niet was vastgesteld op 1, en de PIC mocht doorgaan met het beantwoorden van de interrupt, kon het continu pulseren van de pin ervoor zorgen dat de PIC terugkeerde naar het begin van onze interruptroutine en in geen geval voltooide. Terugkomend op mijn illustratie van de telefoon, het is vergelijkbaar met het opnemen van de telefoon, en onmiddellijk als ik verder ga met bespreken, begint het weer te rinkelen omdat een andere persoon met je wil praten.

Het is raadzaam om één dialoog te voltooien en vervolgens de telefoon opnieuw te pakken om met de volgende persoon te spreken. Bij deze vlag kun je een klein probleempje vinden. Hoewel de PIC deze vlag snel instelt op 1, wordt deze niet opnieuw op 0 gezet! Die activiteit moet worden uitgeoefend door de programmeur - d.w.z. u. Dit kan moeiteloos worden bereikt, aangezien ik er zeker van ben, en moet worden bereikt nadat de PIC de interruptroutine heeft uitgevoerd.

Geheugenlocatie Telkens wanneer u de PIC voor het eerst opstart, of in het geval dat er een reset plaatsvindt, tipt de programmateller om 0000h te adresseren, dat kan onmiddellijk aan het begin van het programmageheugen zijn. Maar in het geval dat er een onderbreking is, zou de programmateller adres 0004h aangeven.

Daarom moeten we, terwijl we ons programma samenstellen dat interrupts heeft, eerst de PIC informeren om over adres 0004h te springen, en de interruptroutine behouden die begint op adres 0004h, discreet van de rest van het programma.

Dit kan probleemloos worden uitgevoerd. In eerste instantie beginnen we ons programma met een commando dat bekend staat als ORG. Deze opdracht geeft Origin aan, of start. We houden het vast met een adres. Omdat de PIC begint op adres 0000h, typen we ORG 0000h. Daarna moeten we het adres 0004h omzeilen. We doen dit door een GOTO-instructie te plaatsen, vergezeld van een label met tips naar ons primaire programma.

We houden ons daarna aan dit GOTO-commando met nog een ORG, dit moment met het adres 0004h. Het is na dit commando dat we onze interrupt-routine invoegen. Op dit punt zijn we mogelijk in staat om onze interrupt-routine direct na het tweede ORG-commando in te typen, of we zijn in staat om een ​​GOTO-instructie te plaatsen die naar de interrupt-routine verwijst.

Het is echt gerelateerd aan de optie van uw kant. Om de PIC die het aanbiedt te informeren dat deze aan het einde van de interruptroutine is aangekomen, moeten we het commando RTFIE tegen het einde van de routine plaatsen. Dit commando betekent terugkeer van de interruptroutine. Terwijl de PIC dit opmerkt, geeft de programmateller de eindpositie aan waar de PIC zich bevond voordat de onderbreking optrad. We hebben hieronder een kort stukje code opgesteld om het bovenstaande weer te geven:

Er zijn een paar dingen die u moet weten wanneer u interrupts gebruikt. De eerste is dat als u het identieke register in uw primaire programma en de interruptroutine gebruikt, u er rekening mee moet houden dat de details van het register hoogstwaarschijnlijk zullen veranderen wanneer de interrupt plaatsvindt.

Laten we bijvoorbeeld het w-register gebruiken om gegevens naar het primaire programma van poort A door te sturen, daarom kunt u ook het w-register in de interruptroutine gebruiken om gegevens van de ene bestemming naar de andere te verplaatsen.

Als u niet voorzichtig bent, zou het w-register de laatste waarde bevatten die het ontving terwijl het in de interruptroutine zat, dus wanneer u terugkeert van de interrupt, wordt deze informatie naar poort A gestuurd in plaats van de waarde die u eerder bezat de onderbreking vond plaats.

Het middel hiervoor is om de details van het w-register tijdelijk op te slaan voordat u het opnieuw gebruikt in de interruptroutine. De tweede is het feit dat u een vertraging kunt vinden tussen het moment waarop een onderbreking plaatsvindt en wanneer de volgende kan optreden. Zoals je begrijpt, heeft de PIC een externe klok, die mogelijk een kristal kan zijn of een combinatie van weerstand en condensator.

Ongeacht de frequentie van deze klok, de PIC deelt deze door 4, waarna deze wordt gebruikt voor zijn innerlijke timing. Als je bijvoorbeeld een 4MHz-kristal aan je PIC hebt gekoppeld, voert de PIC de instructies uit op 1MHz. Deze interne timing staat bekend als een instructiecyclus. Op dit punt beweert het gegevensblad (ongetwijfeld in kleine lettertjes) dat je tussen de onderbrekingen 3 tot 4 instructierondes moet inschakelen.

Mijn zou zijn om 4 rondes mogelijk te maken. De reden achter de vertraging is dat de PIC tijd nodig heeft om naar het interruptadres, de vlag, te springen en weer weg te komen van de interruptroutine. Houd hier daarom rekening mee als u met een alternatief circuit werkt om een ​​interrupt voor de PIC te activeren.

Op dit punt is een punt het feit dat als u bits 4 tot 7 van poort B als interrupt gebruikt. U kunt geen specifieke pinnen op poort B kiezen om als interrupt te functioneren.

Daarom, als u deze pinnen toestaat, kunnen ze waarschijnlijk allemaal verkrijgbaar zijn. Daarom kunt u bijvoorbeeld niet simpelweg bits 4 en 5 hebben - bits 6 en 7 zullen waarschijnlijk tegelijkertijd worden geactiveerd. Wat is precies het doel om vier bits een interrupt te laten voorstellen? Het kan zijn dat u een circuit hebt aangesloten op de PIC, voor het geval een van de vier lijnen hoog wordt, in dat geval kan dit een probleem zijn dat u onmiddellijk door de PIC moet beïnvloeden.

Een illustratie hiervan zou een huisbeveiligingsalarm kunnen zijn, waarbij vier sensoren zijn gekoppeld aan poort B pinnen 4 tot 7. Elke specifieke sensor kan de PIC vragen om een ​​alarm te activeren, en de alarmsignaleringsroutine is de interruptroutine. Dit bespaart het voortdurend controleren van de poorten en stelt de PIC in staat om door te gaan met verschillende zaken. In de volgende tutorial gaan we een programma samenstellen om een ​​interrupt te beheren.

We hebben veel basisprincipes behandeld in de laatste tutorial, daarom heb ik het gevoel dat de tijd is gekomen dat we ons eerste programma hebben samengesteld.

Het programma dat we zullen schrijven, zou het aantal keren tellen dat we een schakelaar aanzetten, en dan het aantal laten zien.

Het programma telt van 0 tot 9, zichtbaar op 4 LED's in binaire vorm, samen met de input of interrupt zal waarschijnlijk op RB0 staan.

Het allerbelangrijkste dat we moeten doen, is de PIC informeren om over het adres te springen waarnaar de programmateller verwijst wanneer er een onderbreking plaatsvindt.

U zult opmerken dat we een unieke methode gebruiken om hexadecimale getallen weer te geven. Voordat ik gebeurde, pas F9h toe waarin h hexadecimaal aangeeft. We zouden dit kunnen schrijven als 0xF9, wat de structuur is die we vanaf nu gaan gebruiken.

Nu moeten we de PIC vertellen dat we interrupts gaan gebruiken, en we gebruiken RB0 pin 6 als een interrupt pin:

bsf INTCON, 7GIE - Globale onderbreking inschakelen (1 = inschakelen)
bsf INTCON, 4INTE - RB0 interrupt inschakelen (1 = inschakelen)
Ik ga de interruptvlag wissen voor het geval dat (ik vertrouw nooit iets!)
bcf INTCON, 1INTF - Wis vlagbit voor het geval dat

Momenteel moeten we onze 2 poorten tot stand brengen. Houd er rekening mee dat, aangezien we nu RB0 gebruiken als een interrupt-pin, dit moet worden ingesteld als een invoer:

We gaan een variabele genaamd COUNT gebruiken om het aantal schakeltellingen op te slaan. We zouden gewoon de waarde op poort A kunnen verhogen, maar je zult zien waarom ik een variabele gebruik wanneer we onze interruptroutine schrijven.

Daarom is ons hoofdprogramma samengesteld, en op dit punt moeten we de PIC informeren hoe verder te gaan als er een onderbreking plaatsvindt. In dit voorbeeld zal onze interrupt waarschijnlijk de switch zijn. Precies wat we willen dat de PIC is, is één op de instelbare COUNT elke keer dat de schakelaar beperkt is.

Desalniettemin willen we alleen maar laten zien hoe vaak de schakelaar van 0 naar 9 sluit. Hierboven zei ik dat we de waarde op poort A misschien gewoon konden verhogen elke keer dat er een interrupt is. Poort A heeft echter 5 bits, voor het geval we de poort gewoon verhogen, zullen we de hoogste telling van 31 hebben. Er zijn een aantal verklaringen waarom ik ervoor heb gekozen om niet naar 31 te gaan.

In eerste instantie zullen we een 7-segmenten scherm gebruiken, dat hooguit van 0 tot 15 kan gaan (0 tot F in hex). Vervolgens wil ik u nog enkele van de rekenkundige opdrachten laten zien die u in de afgelopen lessen tegenkwam.

Daarom gaan we door met onze interruptroutine. Momenteel moeten we eerst de details van ons w-register kort opslaan, aangezien we dit hebben toegepast om de inhoud van COUNT naar PORTA te verplaatsen. In het geval dat we het niet opslaan, kunnen we in dat geval misschien een heel ander getal leveren vanwege onze rekenkunde. Laten we dat daarom eerst doen:

Op dit punt weten we of de waarde van COUNT 9 of meer is. Precies wat we nu moeten bereiken, is als COUNT meer is dan 9, plaats het terug naar 0, of keer terug naar het hoofdprogramma om er zeker van te zijn dat we het kunnen leveren aan poort A. Het BTFSS-commando, aangezien u begrijpt dat de volgende
instructie voor het geval de carry-vlag is gepland, d.w.z. COUNT = 10:

Het enige dat nu nog moet gebeuren, is collectief invoeren en waarden bepalen voor onze constanten, die we direct aan het begin van ons programma kunnen uitvoeren.

Elke keer dat u de schakelaar activeert, tellen de LED's binair op van 0000 tot 1010 en vervolgens terug naar 0000.

De volgende afbeelding toont het schakelschema dat compatibel is met de hierboven toegelichte code. Interessant is dat u zult zien dat de timingcondensator in het ontwerp is opgenomen. Dit is een leuke kleine truc waardoor je de vrijheid krijgt om de opname van de condensator te vermijden voor het geval je er gedurende die tijd geen hebt.

Hier komt de capaciteit in het spel via de strooicapaciteit over de oscillatorpen en aarde.
Het lijkt natuurlijk misschien niet een erg intelligente manier om een ​​condensator praktisch te vermijden, aangezien de strooiwaarde kan variëren met verschillende gegeven omstandigheden.

Een ander deel dat in het circuit kan worden gezien, is het aanklachtnetwerk over de switch. Dit voorkomt interferentie tijdens mechanisch schakelen en voorkomt dat de PIC in de war raakt als het schakelen een enkele schakelaar of meerdere schakelaars was.




Vorige: Programmeerbaar bidirectioneel motortimercircuit Volgende: Hoe Buck-Boost-circuits werken