William Sandqvist william@kth.se Melodispelaren Denna demonstrationslaboration visar, steg för steg, hur man skriver ett kort program i programspråket C, och hur man "laddar ned det" det till en PIC-krets ( Perpherial Interface Computer ) med en kretsprogrammerare. Om PIC-kretsen förses med några elektroniska kringkomponenter kan den sedan utföra den uppgift den programmerats för. Som programmeringsuppgift har vi valt att låta PIC-kretsen spela upp en melodi. Detta är inte bara en "lek", utan det kan faktiskt vara en viktig funktion hos en datorstyrd konsumentprodukt av idag. Möjligheten att få en personlig ringsignal till sin mobiltelefon har varit ett av de viktigaste konkurensmedlen mellan mobiltelefontillverkarna! Uppgiften är tillräckligt komplex för att visa PIC-kretsens möjligheter, och för den delen, egenheter. William Sandqvist william@kth.se
William Sandqvist william@kth.se Stämgaffel Vi börjar med att göra en "stämgaffel", det vill säga låta PIC-kretsen avge en kontinuerlig 440 Hz ton. William Sandqvist william@kth.se
William Sandqvist william@kth.se playtone.c /* playtone.c Generates a 440 Hz "A4" tone */ /* Use processor 16F628 */ #include " 16F628.h" #pragma config |= 0x3f90 void main(void ) { char note = 114; /* gives pitch A4 440 Hz */ TRISB = 0b11111110; /* B.0 is output */ while (1) /* forever */ { char i; /* local variable */ for(i = note; i > 0; i--) { /* Delay. Loop + nop()'s totals 10 us */ nop(); nop(); nop(); nop(); } PORTB.0 = !PORTB.0; /* Toggle bit B.0 */ } } William Sandqvist william@kth.se
William Sandqvist william@kth.se Delay 10 s När man kompilerar C-programmet får man också en fil med motsvarande assemblerkod! Man undersöker assemblerkoden, varje instruktion kommer att ta 1 s, förutom hoppinstruktioner som tar 2 s. Vid behov ”kryddar” man med att lägga till eller ta bort någon NOP, nop() i C-koden. ; The 10 us delay loop. m002 MOVF i,1 ; 1 us BTFSC 0x03,Zero_ ; 2 us (When skipped) GOTO m003 ; NOP ; 1 us NOP ; 1 us NOP ; 1 us NOP ; 1 us DECF i,1 ; 1 us GOTO m002 ; 2 us ; Total of 10 us! William Sandqvist william@kth.se
William Sandqvist william@kth.se Hela skalans toner … Tabellen innehåller tal mellan 51…255. Bland de lediga talen låter vi 0 betyda “slut på melodin” och 1 betyda “paus”. William Sandqvist william@kth.se
William Sandqvist william@kth.se TIMER0 TIMER0 är en 8-bitars modulo 256-räknare som kan läsas/skrivas med program. Om biten TOCS i OPTION -registret är "0" så räknas var fjärde av processorns klockcykler ( Fosc/4 ). Om biten TOCS är "1" räknas de pulsflanker som inkommer på pinnen T0CKI. Med biten TOSE bestämmer man om det är positiva eller negativa "flanker" som ska räknas. Med biten PSA=0 kan man koppla in en prescaler, en frekvensdelare. Med den inkopplad räknas bara en bråkdel av de inkommande pulserna, och det tar då längre tid innan TIMER0 "räknar runt". Med bitarna PS2 PS1 PS0 ställer man in prescalerns delningstal. William Sandqvist william@kth.se
William Sandqvist william@kth.se Strukturdiagram Strukturdiagrammet är ett enkelt tvådimensionellt diagram som kan användas för att dokumentera datorprogram. I diagrammet används symboler för sekvens, selektion och iteration, vilka är de grundläggande operationer som bygger upp alla datorprogram. I horisontell ledd visas tidsdimensionen, dvs i vilken ordning saker utförs. I vertikal led visas upplösningen, för varje nivå nedåt ökas detaljrikedomen i beskrivningen. William Sandqvist william@kth.se
Strukturdiagram Melodyplayer Alla noter är 1/8 långa. En ”helnot” får man genom att upprepa 1/8 not 8 ggr. Funktionen LookUpNote( i) returnerar melodins not nr i. Notvärdet 0 betyder att melodin är slut och notvärdet 1 att det är en paus. William Sandqvist william@kth.se
William Sandqvist william@kth.se Computed GoTo ? PIC-processorns instruktioner är 14 bitar långa. Konstanter, sk "literals", lagras i programminnet inbakade i instruktioner. Tabellvärden lagras i med assemblerinstruktionen RETLW k ( RETurn with Litteral in W ), där k är den 8 bitars konstant som ska bakas in i instruktionen. Om processorn "hoppar" till en sådan instruktion, skickas den tillbaks med talet k i arbetsregistret, W-registret. Vid assemblerprogrammering används detta tillsammans med indexerad adressering så att man med hjälp av ett index kan styra vilken av tabellens konstanter man ska komma tillbaks med. Detta kallas för Computed GOTO. William Sandqvist william@kth.se
Tabell i assemblerprogram Tabell i assemblerprogram. k1 k2 k3 är tabellens tre konstanter. CALL TABLE ; W contains table offset ... TABLE ADDWF PC ; W = offset, go to offset table entry RETLW k1 ; Begin table, return with k1 in w RETLW k2 ; return with k2 in w RETLW k3 ; End of table, return with k3 in w Det finns inget "självklart" sätt att utrycka detta med C-språket. B Knutsen har infört en (inbyggd) funktion skip(i) som ska lösa detta. Denna betyder att man hoppar över det antal C-instruktioner som anges med "i". William Sandqvist william@kth.se
William Sandqvist william@kth.se Tabell i C-program Exempel C-funktion (enligt CC5X). k1 k2 k3 är tabellens tre konstanter. char table(char i) { skip(i); /* internal function in CC5X */ return k1; return k2; return k3; } William Sandqvist william@kth.se
William Sandqvist william@kth.se En melodi char LookUpNote(char W) { skip(W); /* internal function to CC5X compiler */ return 1; /* Pause */ return 76; /* E5 */ return 85; /* D5 */ return 76; /* E5 */ return 76; return 76; return 76; return 114; /* A4 */ return 114; return 114; . . . return 101; /* B4 */ return 101; return 1; /* Pause */ return 0; /* End */ } Här använder vi arbetsregistret W som variabel, på så sätt ”sparar” vi en lokal variabel i funktionen. Provkör programmet så får Du veta vilken melodi det är … William Sandqvist william@kth.se