PIC Opg 5 Løsning
Denne side gennemgår løsningen for PIC Opgave 5 - Flip-flops
Løsningsforslag for Flip-flop.
Generelt er alle løsningerne laved med den sædvanlig opstartskode til en PIC16F684, og selve funktionen realiseret i et forever loop.
include 16f684 -- Setup pic pragma target clock 4_000_000 pragma target WDT DISABLED pragma target OSC INTOSC_NOCLKOUT pragma target PWRTE ENABLED pragma target MCLR INTERNAL pragma target CP DISABLED pragma target CPD DISABLED pragma target BROWNOUT ENABLED pragma target IESO DISABLED pragma target FCMEN DISABLED include delay -- enable_digital_io() -- disable analog I/O (if any) -- -- IO definitioner porta_direction = all_input portc_direction = all_output -- alias Q is pin_c0 alias Q_not is pin_c1 Q_not = ! Q -- Main loop forever loop -- Flip-flop koden her end loop
Som man kan se defineres udgangen Q til Q og den inverterede udgang Q til Q_not. Lige inden man går ind i forever-loopet sættes Q_not til det inverterede af Q.
Der er forskellige typer flip-flop, men generelt for alle typer er det at de indeholder et hukommelses-element. Det fremgår ikke så tydeligt af løsningerne, da de alle anvender portens indbyggede hukommelse (at en portben bliver stående på det niveau det er sat til, hvis man ikke gør noget ved det).
Koden som jal-filer
Alle eksemplerne kan hentes i denne ZIP-fil.
RS-flip-flop
Som man kan læse i sandhedstabellen under RS-flip-flop, så er der to indgange, en Set (S) og en Reset (R), hvor S sætter udgangen Q til høj, og R sætter udgangen Q til lav. Q_not er normalt det modsatte af Q. Hvis man både setter og resetter er udgangen udefineret, og i koden her er det valgt at sætte både Q og Q_not til høj.
I initialiseringen defineres de to indgange R og S:
alias R is pin_A0 alias S is pin_A1
Funktionen af RS-flip-flopen er realiseret med følgende kode:
35 if S then 36 if ! R then 37 Q = high 38 Q_not = low 39 else 40 Q = high 41 Q_not = high 42 end if 43 else 44 if R then 45 Q = low 46 Q_not = high 47 end if 48 end if
Linje 35 tester om S-benet er sat, og linje 36 tester så om R-benet ikke er sat, hvis begge dele er tilfældet, så stiller linje 37-38 udgangene, så flip-flopen er sat.
Linje 39-42 udføres hvis begge indgange er sat (og sætter begge udgange høje).
Linje 43 er hvis S-benet ikke er sat, hvor man så i linje 44 tester om R-benet er at, og hvis det er så stiller linje 45-46 udgangene, så flip-flippen er resat.
Linje 47-48 er afslutningerne på hhv. R sætningen og S sætningen.
Hele koden ligger i filen RS-FF.jal inde i ZIP-filen.
D-flip-flop
Som det kan ses i sandhedstabellen unde D-flip-flop, så er der en data-indgang D og en clock-indgang CLK. Når CLK går fra lav til høj, så sættes udgangen Q til det niveau D har, og Q_not sættes til det inverterede.
Indgangene er defineret som følger:
alias D is pin_A2 alias CLK is pin_A3
For at registrere om CLK laver et skift fra lav til høj (positivt gående kant), så kan man læse en mekanisme under Trykknap#Forkant der giver en generel måde at gøre det på, dette kræver en variabel som vi definerer her, og sætter til det niveau som CLK har i starten af programmet:
var bit CLK_last = CLK
Hele koden inde i forever-loopet til D-flip-flopen ser ud som følger:
37 if CLK then 38 if ! CLK_last then 39 Q = D 40 Q_not = ! D 41 end if 42 CLK_last = high 43 else 44 CLK_last = low 45 end if
Hovedparten af koden: linje 37-38 og linje 41-45 drejer sig om at finde ud af om det er en forkant. Linje 39-40 er det der udføres når man har fundet en forkant.
Hele koden ligger i filen D-FF.jal inde i ZIP-filen.
JK-flip-flop
Som det kan ses i sandhedstabellen unde JK-flip-flop, så er der to data-indgange J og K samt en clock-indgang CLK. Når CLK går fra lav til høj, så stilles udgangen Q ud fra de niveauer J og K har, og Q_not sættes til det inverterede.
- Hvis både J og K er lave, så sker der ikke noget på udgangene, de forbliver det samme.
- Hvis J er høj og K er lav, så sættes Q høj.
- Hvis K er høj og J er lav, så sættes Q lav.
- Hvis både J og K er høje, så toggler udgangen (høj bliver til lav, og lav bliver til høj)
Indgangene er defineret som følger:
alias CLK is pin_A3 alias J is pin_A4 alias K is pin_A5
For at registrere om CLK laver et skift fra lav til høj (positivt gående kant), bruges samme princip som ved D-flip-flopen igen med mekanismen fra Trykknap#Forkant.
Hele koden inde i forever-loopet til JK-flip-flopen ser ud som følger:
38 if CLK then 39 if ! CLK_last then 40 if J then 41 if K then 42 Q = Q_not 43 Q_not = ! Q 44 else 45 Q = high 46 Q_not = low 47 end if 48 else 49 if K then 50 Q = low 51 Q_not = high 52 end if 53 end if 54 end if 55 CLK_last = high 56 else 57 CLK_last = low 58 end if 59 delay_1ms(10) -- Hindrer det meste prel
Hovedparten af koden: linje 38-39 og linje 54-58 drejer sig om at finde ud af om det er en forkant. Linje 40-41 finder toggle-delen og linje 42-43 løser Toggle-delen (at udgangen skifter). Linje 44-47 er der hvor J er høj og K er lav, så de sætter Q høj. Linje 48-53 er der hvor K er høj og J er lav, så der sættes Q lav. Hvis både J og K er lave, så skal flip-flopen ikke reagere, så det er ikke skrevet i koden.
En ting mere, som ikke var med i D-flip-flopen, er at man kan modtage to CLK-pulser lige efter hinanden.(det vil blot sætte samme niveau to gange på D-flip-flopen). Ved JK-flip-flopen kan det skabe problemer når den er i toggle-mode, og det er faktisk et reelt problem, som det er skitseret ved Trykknap#Prel, nemlig at når en kontakt laver forbindelse, så kan den lige idet den gør det have en overgang, hvor der skiftevis er forbindelse, og skiftevis ikke er det, det vil gøre at når den toggler, så vil den kunne modtage et lige antal, og dermed lande i samme tilstand (altså ikke toggle). Dette er forhindret ved at lægge et delay ind i loopet på 10 millisekunder, hvilket gør at det mest almindelige prel er overstået, uden at brugeren kan mærke den korte forsinkelse.
Hele koden ligger i filen JK-FF.jal inde i ZIP-filen.
Inde ved koderne ligger der også en JK-RS-FF.jal, som er en kombination af en JK-flip-flop og en RS-flip-flop, som også er realiseret i digitale kredse (de anvendes normalt ved at R eller S holder styr op opstarten, så man ved hvilken stilling den står i som udgangspunkt).
Toggle-flip-flop
Som det kan ses i sandhedstabellen unde Toggle-flip-flop, så er der en indgang T, der angiver om den skal toggle og en clock-indgang CLK. Når CLK går fra lav til høj, så inverteres udgangen Q hvis T er høj, og Q_not sættes til det modsatte. Hvis T er lav sker der ingenting
Indgangene er defineret som følger:
alias T is pin_A2 alias CLK is pin_A3
For at registrere om CLK laver et skift fra lav til høj (positivt gående kant), som beskrevet ved D- og JK-flip-flop.
Hele koden inde i forever-loopet til Toggle-flip-flopen ser ud som følger:
36 if CLK then 37 if ! CLK_last then 38 if T then 39 Q = Q_not -- Toggel output hvis T er høj 40 Q_not = ! Q 41 end if 42 end if 43 CLK_last = high 44 else 45 CLK_last = low 46 end if 47 delay_1ms(10) -- Hindrer det meste prel
Hovedparten af koden: linje 36-36 og linje 42-46 drejer sig om at finde ud af om det er en forkant. Linje 38-41 er det der udføres når man har fundet en forkant, hvor den toggler udgangene, hvis T er høj, og ellers sker der ikke mere.
Som beskrevet ved JK-flip-flop, så er der sat 10 ms delay ind, for at mindske indvirkningen af prel.
Hele koden ligger i filen T-FF.jal inde i ZIP-filen.
Alle typer i et program
For lige at illustrere en måde at lægge flere programmer ind i samme PIC, så er det lavet et all-FF.jal.
Alle indgangene er defineret som følger:
alias R is pin_A0 alias S is pin_A1 alias D is pin_A2 alias T is pin_A2 alias CLK is pin_A3 alias J is pin_A0 alias K is pin_A1 alias skift is pin_A4
Den sidste indgang skift er til at skifte mellem de 4 typer flip-flop.
Internet i programmet er typerne defineret som tal på følgende måde:
const RS_FF = 0 const D_FF = 1 const JK_FF = 2 const T_FF = 3
Til at håndtere hvilken type det er, og til at finde kanten af skift er der defineret en byte og en bit som følger:
var byte type = RS_FF var bit skift_last = skift
Hele koden inde i forever-loopet indeholder de 4 koder fra det foregående sat op som en CASE-struktur, men først håndteres skiftet mellem de 4 typer. Starten af koden ser ud som følgende:
52 portc = (portc & 0b1111_0011) | type << 2 53 if skift then 54 if ! skift_last then 55 type = (type + 1) & 0b0000_0011 56 end if 57 skift_last = high 58 else 59 skift_last = low 60 end if 61 CASE type OF 62 RS_FF : BLOCK
Linje 52 udlæser på bit 2 og bit 3 hvilen type det er der vises (binært tal fra 0-3) Linje 53-54 og linje 56-60 drejer sig om at finde ud af om der er en forkant på skift-inputtet. Linje 55 tæller typen en op når man har fundet en forkant.
På denne måde kan man skifte til den flip-flop man ønsker, og teste den, og så skifte videre til en anden type.
Linje 61-62 er lige starten af CASE-strukturen, der går på type. Den første BLOCK er koden til RS-flip-flopen, go så kommer det ellers der efter. Hele koden ligger i filen all-FF.jal inde i ZIP-filen.
Der er også lavet en version all2-FF.jal, der har præcist den samme funktion, men som bare viser at man kan genbruge den kode der detekterer CLK-indgangen, så den ikke skal laves for de 3 typer der har en CLK-indgang.
PIC | |
---|---|
PIC-Typer | PIC16F84 - PIC12F675 - PIC16F628 - PIC16F684 - PIC16F690 - PIC16F877 - PIC18F2550 |
Programmeringsbegreber | Maskinkode - Mikrocontroller |
Programmeringsmiljø | PIC-brænder - UsbPicProg - Analog indgang - ICSP |