I vores tidligere tutorial lærte vi om at blinke en LED ved hjælp af PIC-mikrocontroller og byggede det samme kredsløb på Perf-kortet. Derefter brugte vi PICkit 3, ICSP og MPLAB IPE til at dumpe programmet på vores Perf-kort. Nu, i denne vejledning vil vi fremme os selv til at bruge flere ben på PIC-mikrocontrolleren. Vi bruger 7 udgange (LED'er) og en indgang. Til denne vejledning bruger vi det gamle Perf-kort (vist nedenfor) og tilføjer bergpinde for at trække de nødvendige stifter ud på det andet LED-kort. I slutningen af denne tutorial genererer vi en sekvens af blinkende lysdioder ved hjælp af PIC-mikrocontroller PIC16F877A og lærer, hvordan man bruger flere ind- og udgange, nogle grundlæggende om 'for' loop og funktionsopkald.
LED-kortet er intet andet end et andet perf-kort, hvorpå vi lodder LED'erne med en strømbegrænsende modstand (vist nedenfor). Vi tilføjer også en trykknap for at starte sekvens-LED blinker.
Kredsløbsdiagram:
PIC Microcontroller PIC16F877A LED blinkende sekvenskode og arbejdsforklaring:
Komplet kode er angivet nedenfor (tjek i slutningen), her får vi det gennem linje for linje. Denne kode begynder at lyse lysdioder i rækkefølge, når der trykkes på trykknappen. For at forstå sekvenserne, se videoen i slutningen af vejledningen. Jeg vil anbefale dig at sammenligne output vist i video med nedenstående kode og prøve at forstå programmet.
Lad os se på koden linje for linje. De første par linjer er til opsætning af konfigurationsbits, som blev forklaret i den foregående tutorial, så jeg springer dem over indtil videre. Den bedste måde at forstå ethvert program på er at starte fra hovedfunktionen ( ugyldig hoved () ), så lad os gøre det
TRISB0 = 1; // Instruer MCU'en, at PORTB-pin 0 bruges som input til knap. TRISD = 0x00; // Instruer MCU'en om, at alle ben er output PORTD = 0x00; // Initialiser alle ben til 0
Ordet TRIS bruges til at definere, om stiften bruges som input / output, og ordet PORT bruges til at lave en pin High / Low. Linjen TRISB0 = 1 udgør den 0. Pin i PORT B som input. Dette vil være vores trykknap. Linjerne TRISD = 0x00; PORTD = 0x00; vil gøre alle benene i port D som output og tildele en startværdi på LAV til disse ben.
Da vi sagde, at B0 bruges som input, forbinder vi den ene ende af trykknappen til stiften B0 og den anden ende til jorden. På det tidspunkt, når vi trykker på knappen, holdes stiften til jorden som vist i forbindelsesdiagrammet ovenfor. Men for at få dette til at ske skal vi bruge en pull-up-modstand, så stiften holdes højt, når der ikke trykkes på knappen. En pull up-modstand er sådan noget.
Men vores PIC MCU har en intern svag pull up-modstand, som kan aktiveres af software på den måde, hvilket sparer en masse besvær (når flere knapper skal tilsluttes).
Hvad er en svag pull up-modstand?
Der er to typer pull up-modstand, den ene er Weak Pull Up og den anden er Strong Pull Up. De svage pull-up-modstande er af høj værdi og tillader således en svag strøm at strømme igennem, og de stærke pull-up-modstande er af lav værdi, hvorved en stærk strøm kan strømme. Alle MCU bruger for det meste svage pull up-modstande. For at aktivere dette i vores PIC MCU skal vi se på vores datablad for OPTION_REG (option register) som vist i snapshotet nedenfor.
Som vist beskæftiger bit 7 sig med den svage pull up-modstand. Det skal gøres nul for at aktivere det. Dette gøres af OPTION_REG <7> = 0 . Dette handler specifikt om bit 7, der overlader de andre bits til dens standardværdier. Med dette kommer vi ind i vores while-loop, hvor det kontrolleres, om knappen trykkes på ved hjælp af if (RB0 == 0). Hvis betingelsen er opfyldt, kalder vi vores funktion med parametrene 1, 3, 7 og 15.
sblink (1); // FUNCTION CALL 1 med parameter 1 sblink (3); // FUNCTION CALL 3 med parameter 3 sblink (7); // FUNCTION CALL 7 med parameter 7 sblink (15); // FUNKTIONSOPKALD 4 med parameter 15
Hvorfor bruger vi funktioner?
Funktioner bruges til at reducere antallet af linjer i vores kode. Dette er hvad de fleste af os ville have vidst. Men hvorfor har vi brug for at reducere antallet af linjer, især når det kommer til MCU-programmering. Den Årsagen er den begrænsede plads i vores program hukommelse. Hvis vi ikke optimerer koden korrekt, kan vi løbe tør for hukommelsesplads. Dette vil være praktisk, når vi skriver lange sider med koder.
Enhver funktion har en funktionsdefinition ( sblink (int get) i vores tilfælde) og en funktion Call ( sblink (1) i vores tilfælde). Det er valgfrit at have en funktionserklæring, for at undgå det har jeg placeret min funktionsdefinition, inden jeg kalder funktionen til min hovedfunktion.
Funktionsparametre er den værdi, der overføres fra funktionsopkaldet til funktionsdefinitionen. I vores tilfælde er heltalsværdierne (1, 3, 7, 15) de parametre, der sendes fra funktionsopkaldet, og variablen "get" får værdien af parametrene ind i funktionsdefinitionen for at behandle dem. En funktion kan have mere end en parameter.
Når funktionen er kaldet, udføres nedenstående linjer i funktionsdefinitionen.
for (int i = 0; i <= 7 && RB0 == 0; i ++) {PORTD = get << i; // LED-bevægelse Venstre rækkefølge __forsink_ms (50); } for (int i = 7; i> = 0 && RB0 == 0; i--) {PORTD = get << i; // LED-bevægelse Venstre sekvens __forsinkelse_ms (50); }
Nu ser denne linje ud til at være underlig: PORTD = get << i . Jeg vil forklare, hvad der faktisk sker her.
"<<" er en venstre skiftoperatør, der skifter alle bits til sin venstre position. Nu når vi kalder sblink (int get) -funktionen med parameteren '1' som sblink (1), vil den gøre værdien af 'get' som 1, som i binær er 0b00000001. Derfor vil denne linje være som PORTD = 0b00000001 << i .
Værdien af "i" vil variere fra 0 til 7, da vi har brugt en 'for loop' til (int i = 0; i <= 7 && RB0 == 0; i ++). Værdien af at 'jeg' er fra 0 til 7 ændrer resultatet således:
Som du kan se, har vi tændt en LED ad gangen (fra venstre mod højre) ved at holde resten FRA. Den næste 'for loop' for (int i = 7; i> = 0 && RB0 == 0; i--) , vil også gøre det samme, men denne gang tændes LED'en fra højre mod venstre i en sekvens, da vi startede fra 7 og gik ned til 0. Vi har brugt en forsinkelse på 200 ms, så vi kan visualisere, at LED'en tændes og slukkes.
Når vi nu videregiver værdi 3 i sblink (int get) -funktionen, så bliver funktionen sblink (3) udført, hvilket gør værdien af 'get' som 0b00000011, derfor bliver resultatet på PORTD:
Så nu denne gang vil to lysdioder blive tændt til enhver tid ved hjælp af sblink (3). Tilsvarende for sblink (7) og sblink (15) vil tre og fire lysdioder være tændt i en rækkefølge. Når dette er færdigt, får vi al LED til at være tændt ved hjælp af linjen PORTD = 0xFF . Tjek videoen nedenfor for fuld demonstration.
Håber du har forstået koden og dermed har lært at bruge funktioner, 'for' og 'while' til at få dine ønskede output. Nu kan du tilpasse koden for at få din forskellige rækkefølge af LED til at blinke. Fortsæt med at kompilere din kode og dumpe den på din MCU og nyd output. Du kan bruge kommentarsektionen, hvis du sidder fast et sted. Jeg har også vedhæftet simulerings- og programfilerne her.
Det er det for nu i vores næste tutorial, vi lærer, hvordan man bruger PIC16F877A-timere i stedet for at bruge forsinkelsesfunktioner. Du kan gennemse alle PIC-mikrocontroller-tutorials her.