I vår forrige opplæring lærte vi om å blinke en LED ved hjelp av PIC-mikrokontroller og bygde den samme kretsen på Perf-kortet. Så brukte vi PICkit 3, ICSP og MPLAB IPE for å dumpe programmet på Perf-kortet. Nå, i denne opplæringen, vil vi fremme oss selv til å bruke flere pinner på PIC-mikrokontrolleren. Vi vil bruke 7 utganger (LED) og en inngang. For denne opplæringen vil vi bruke det gamle Perf-kortet (vist nedenfor) og vil legge til bergpinner for å trekke ut de nødvendige pinnene på det andre LED-kortet. På slutten av denne opplæringen genererer vi en sekvens av blinkende lysdioder ved hjelp av PIC-mikrokontroller PIC16F877A og lærer hvordan du bruker flere innganger og utganger, noen grunnleggende om 'for' loop- og funksjonsanrop.
LED-kortet er ingenting annet enn et annet perf-kort, som vi vil lodde LED-ene med en strømbegrensende motstand på (vist nedenfor). Vi vil også legge til en trykknapp for å starte sekvens-LED som blinker.
Kretsdiagram:
PIC Microcontroller PIC16F877A LED blinkende sekvenskode og arbeidsforklaring:
Komplett kode er gitt nedenfor (sjekk på slutten), her vil vi få det gjennom linje for linje. Denne koden vil begynne å lyse lysdioder på en sekvensiell måte når du trykker på trykknappen. For å forstå sekvensene, vennligst se videoen på slutten av opplæringen. Jeg vil anbefale deg å sammenligne utdataene som vises i video med koden nedenfor og prøve å forstå programmet.
La oss se på koden linje for linje. De første linjene er for å sette opp konfigurasjonsbiter som ble forklart i forrige opplæring, så jeg hopper over dem for nå. Den beste måten å forstå ethvert program på er å starte fra hovedfunksjonen ( ugyldig hoved () ), så la oss gjøre det
TRISB0 = 1; // Instruer MCU at PORTB pin 0 brukes som inngang for knapp. TRISD = 0x00; // Instruer MCU at alle pinner er utgang PORTD = 0x00; // Initialiser alle pinnene til 0
Ordet TRIS brukes til å definere om pinnen brukes som input / output og ordet PORT brukes til å lage en pin High / Low. Linjen TRISB0 = 1 vil utgjøre den 0. Pinnen i PORT B som inngang. Dette vil være vår trykknapp. Linjene TRISD = 0x00; PORTD = 0x00; vil lage alle pinnene i port D som utgang og tildele en startverdi på LAV til disse pinnene.
Siden vi sa at B0 brukes som inngang, vil vi koble den ene enden av trykknappen til stiften B0 og den andre enden til bakken. Når vi trykker på knappen, holdes pinnen til bakken som vist i koblingsskjemaet ovenfor. Men for å få dette til, må vi bruke en opptrekksmotstand slik at pinnen holdes høyt når knappen ikke trykkes. En pull-up motstand er noe slikt.
Men vår PIC MCU har en intern svak opptrekksmotstand som kan aktiveres av programvare på den måten og sparer mye bry (når flere knapper skal kobles til).
Hva er en svak opptrekksmotstand?
Det er to typer pull up-motstand, den ene er Weak Pull Up og den andre er Strong Pull Up. De svake opptrekkmotstandene har høy verdi og lar dermed en svak strøm strømme gjennom, og de sterke opptrekksmotstandene har lav verdi, slik at en sterk strøm kan strømme. All MCU bruker for det meste svake motstander. For å aktivere dette i vår PIC MCU, må vi se på databladet for OPTION_REG (alternativregister) som vist i øyeblikksbildet nedenfor.
Som vist handler bit 7 om den svake motstanden. Det skal gjøres null for å aktivere det. Dette gjøres av OPTION_REG <7> = 0 . Dette handler spesifikt om bit 7 som overlater de andre bitene til standardverdiene. Med dette kommer vi inn i mens loop, der det sjekker om knappen trykkes ved å bruke if (RB0 == 0). Hvis tilstanden er oppfylt, kaller vi funksjonen vår med parameterne 1, 3, 7 og 15.
sblink (1); // FUNKSJONSRING 1 med parameter 1 sblink (3); // FUNKSJONSANROP 3 med parameter 3 sblink (7); // FUNKSJONSANROP 7 med parameter 7 sblink (15); // FUNKSJONSANROP 4 med parameter 15
Hvorfor bruker vi funksjoner?
Funksjoner brukes til å redusere antall linjer i koden vår. Dette er det de fleste av oss ville ha visst. Men hvorfor trenger vi å redusere antall linjer, spesielt når det gjelder MCU-programmering. Den grunnen er begrenset plass i vårt program minne. Hvis vi ikke optimaliserer koden ordentlig, kan det hende at vi går tom for minne. Dette vil være nyttig når vi skriver lange sider med koder.
Enhver funksjon vil ha en funksjonsdefinisjon ( sblink (int get) i vårt tilfelle) og en funksjon Call ( sblink (1) i vårt tilfelle). Det er valgfritt å ha en funksjonserklæring, for å unngå det har jeg plassert funksjonsdefinisjonen min før jeg kalte funksjonen til hovedfunksjonen min.
Funksjonsparametere er verdien som vil bli overført fra funksjonsanropet til funksjonsdefinisjonen. I vårt tilfelle er heltallverdiene (1, 3, 7, 15) parametrene som sendes fra funksjonsanropet, og variabelen "get" får verdien av parameterne inn i funksjonsdefinisjonen for å behandle dem. En funksjon kan ha mer enn én parameter.
Når funksjonen er kalt, vil linjene nedenfor i funksjonsdefinisjonen bli utført.
for (int i = 0; i <= 7 && RB0 == 0; i ++) {PORTD = get << i; // LED-bevegelse Venstre sekvens __forsink_ms (50); } for (int i = 7; i> = 0 && RB0 == 0; i--) {PORTD = get << i; // LED-bevegelse Venstre sekvens __forsink_ms (50); }
Nå ser denne linjen ut til å være merkelig: PORTD = få << i . Jeg skal forklare hva som faktisk skjer her.
"<<" er en venstre skiftoperatør som skifter alle biter til sin venstre posisjon. Nå når vi kaller sblink (int get) -funksjonen med parameteren '1' som sblink (1), vil den gjøre verdien av 'get' som 1, som i binær er 0b00000001. Derfor vil denne linjen være som PORTD = 0b00000001 << i .
Verdien av "i" vil variere fra 0 til 7 siden vi har brukt en 'for loop' for (int i = 0; i <= 7 && RB0 == 0; i ++). Verdien av at jeg er fra 0 til 7 vil endre resultatet slik:
Som du ser har vi slått på en LED om gangen (fra venstre til høyre) ved å holde resten AV. Den neste 'for loop' for (int i = 7; i> = 0 && RB0 == 0; i--) , vil også gjøre det samme, men denne gangen vil LED-en slås PÅ fra høyre til venstre i en sekvens, da vi startet fra 7 og gikk ned til 0. Vi har brukt en forsinkelse på 200 ms slik at vi kan visualisere at LED-en blir slått PÅ og AV.
Nå når vi passerer verdi 3 i sblink (int get) -funksjonen, så blir funksjonen sblink (3) utført som gjør verdien til 'get' som 0b00000011, og resultatet på PORTD blir derfor:
Så nå vil denne gangen to lysdioder slås på til enhver tid ved å bruke sblink (3). Tilsvarende for sblink (7) og sblink (15) vil tre og fire lysdioder være PÅ i en sekvens. Når dette er fullført, vil vi lage hele LED-lampen til å være på ved hjelp av linjen PORTD = 0xFF . Sjekk videoen nedenfor for full demonstrasjon.
Håper du har forstått koden og dermed har lært hvordan du bruker funksjoner 'for' og 'while' for å få de ønskede utgangene. Nå kan du justere rundt koden for å få den forskjellige sekvensen av LED til å blinke. Fortsett å kompilere koden og dump den på MCU-en din og nyt utdataene. Du kan bruke kommentarseksjonen hvis du sitter fast et sted. Jeg har også lagt ved simulerings- og programfilene her.
Det er det for nå i vår neste opplæring, vi lærer hvordan du bruker PIC16F877A-tidtakere i stedet for å bruke forsinkelsesfunksjoner. Du kan bla gjennom alle PIC-mikrokontrolleropplæringene her.