/* * File: oscilator01.c * Author: kubalik * * Created on 18. unora 2016, 16:43 * dne 7.3.2016 to opravdu funguje a prepina kmitocet, DG ! * * * tento program demonstruje pouziti PLL * frekvenci oscilatoru je mozno sledovat na bitech RA0 RA1 RA2 * mezi zmenou na portu uplyne 10000 period Fcy * tedy 10000 instrukcnich cyklu, kmitocet oscilatoru je potom x 2 * na portu RA je tato doba od hrany k hrane, takze polovina periody * *oscilator zacina s frekvenci 7.37 MHz * * po asi 10 sec se frekvence oscilatoru prepne na 50MHz * bity RB0 a RB1 rikaji, ze jsme kmitocet uspesne prepnuli - hodnota 1 * * bit RB4 rika, ze jsme v programu dosahli mista, kde zacina prepnuti kmitoctu * * a stale je na PORTA,4 kmitocet instrukci - je tam btg PORTA,4 ???? no, ne uplne, je to ve while, takze + cas na udelani cyklu * * bity PORTA,0 1, 2 dodavaji kmitocet instrukcu deleno 10000 * tady muzeme zmerit, co ma procesor uvnitr * pri mereni nezapomente, ze kmitocet instrukci je dan casem * od vzestupne k sestupne hrane na techto pinech, * tedy tenhle cas * 10000 da periodu instukci, a /2 da periodu vnitrniho oscilatoru * * postupujeme podle example 7.2, strana 27 , oscilator.pdf * */ #include "p33EV32GM002.h" /* nasledujici makra nastavuji oscilator * hledame v header file * * Macros for setting device configuration registers * pin OSC1 jako I/O pin * vypinaji Watchdog - opet se podivejte do header file, co vsecno se da nastavit * */ // nastaveni fuses funguje, prepnuti take vyzkouseno #pragma config FNOSC = FRC // pracujeme s FRC oscilatorem 7.37MHz #pragma config IESO = OFF // Start up device with user selected oscillator source , u nas FRC #pragma config FCKSM = CSECMD // Clock Switching is enabled,Fail-safe Clock Monitor is disabled #pragma config POSCMD = NONE //Primary Oscillator disabled #pragma config OSCIOFNC = OFF //OSC2 OSC2 is clock output RA3 pin 10 // a na OSC2 se da ten kmitocet merit #pragma config IOL1WAY = ON //Allow Only One reconfiguration pro PPS #pragma config FWDTEN = OFF // WDT and SWDTEN Disabled Watchdog vypnut // pragma naleznete v C:\Program Files (x86)\Microchip\xc16\v1.36\docs\config_docs /* Select Internal FRC at POR , bod d kap. 7.7.2.2 v oscilator.pdf po resetu NENI PLL, zatim pracujeme jenom s FRC oscilatorem */ unsigned int i; /* i je globalni promenne, potrebujeme, aby si pamatovala svou hodnotu i v dobe, kdy se nevykonava obsluha preruseni */ unsigned int j; /* * */ int main() { i = 0; /* sem si dejte breakpoint ! */ j = 0; TRISA = 0x0; // zapisujeme do celeho registru najednou TRISB = 0x00; PORTB = 0; PORTA = 0; ANSELB = 0; ANSELA = 0; /* TIMER T2 * T2CON 1X1- ---- -000 0-0- * | | ||| | | * | | ||| | internal clock - FRC oscil F je 7.37 / 2 * | | ||| T32 - mame 16bitoc\ve citace * | | ||| * | | |TCKPS 00 - delime 1 u preddelicky * | | TGATE je vypnuto * | TSIDLE pracujeme i v idle stavu - to je ted dost jedno * TON citac zapnut * * cely citac je naprogramovan tak, aby deleil 10000 * delicka v citaci 1 , registr PR 10000 * */ CLKDIVbits.FRCDIV = 0; /* delíme 1 */ PR2 = 9999; T2CON = 0xA000; /* v tomhle miste bezi vnitrni oscilator na 7.3 MHz * takze na pinech RA0 RA1 RA2 jsou pulsiky s frekvenci 365 Hz */ /* povoluji preruseni */ IEC0bits.T2IE = 1; /* globalni povoleni preruseni, tohle se musi povolit, * jinak nebude zadne preruseni krome TRAP */ IFS0bits.T2IF = 0; /* pro jistotu nuluji pozadavkovy bit */ INTCON2bits.GIE = 1; j = 0 ; while ( j < 3650 ) { /* j se meni v preruseni od TMR2 j < 3650 */ i++; /* i++ jako prazdna instrukce, je nanic, kvuli simulatoru */ PORTAbits.RA4 = ! PORTAbits.RA4 ; /* negujeme bit RA4, na nem je tedy kmitocet odpovidajici vnitrnimu kmitoctu minus doba na while atd. */ } /* na tomhle miste se zastavime na 10 sec, a po tuto dobu * je kmitocet na RA 365 Hz - podivejte se */ PORTBbits.RB4 = 1 ; /* bit RB4 rika, jsme dospeli az sem * a je to opravdu 10 sec od zacatku frekvence je tedy 365 hz */ /* nastavime si PLL a vnitrni oscilator na 50 MHz */ // Configure PLL prescaler, PLL postscaler, PLL divisor // strana 26 v oscilator.pdf // na zaklade mereni muzeme doufat, ze FRC ma kmitocet 307 x 2 = 7.4 MHz PLLFBD=79; // M=81 /* PLLFBD deli * 0 - delime 2 * 1 - delime tremi * 0x1ff - delime 513 , vic to nejde * na obrazku 7-8 se tyto bity jmenuji PLLDIV * timhle cislem tedy delime vystup z VCO, abychom dostali * ten kmitocet, ktery leze do bloku PFD z FPLU * * Nas kmitocet Fplli je 2.43 MHz * x 81 = 197.1 MHz - to je Fsys * */ CLKDIVbits.PLLPOST=1; // N2=4 /* a Fsys delime 4 197.1 / 4 = 49.275 MHz */ CLKDIVbits.PLLPRE=1; // N1=3 7.4 MHz / 3 = 2.43MHz - Kmitocet Fplli /*Initiate Clock Switch to Primary Oscillator with PLL (NOSC=0b011) * postupujeme podle example 7.2, strana 27 , oscilator.pdf * opravdu jednou zapisujeme do H casti OSCCON a podruhe do L casti OSCCON, * podivejte se na to do datasheetu * __builtin_write_OSCCONH * __builtin_write_OSCCONL * H a L jsmu spravne * druha instrukce odstartuje prepnuti oscilatoru * */ INTCON2bits.GIE = 0; __builtin_write_OSCCONH(0x01); __builtin_write_OSCCONL(OSCCON | 0x01); INTCON2bits.GIE = 1; asm(" bset PORTB, #0 "); /* bit RB0 rika, ze jsme prepli hodiny */ // Wait for PLL to lock while (OSCCONbits.LOCK != 1){ i++; }; PORTBbits.RB1 = 1; /* bit RB1 rika, ze PLL ma spravny kmitocet */ while (1) { i++ ; /* tohleje je k nicemu, ale musi tady byt nejaka instrukce, aby fungoval simulator */ } return 0; } // interrupt od TMR2 void __attribute__((interrupt, auto_psv)) _T2Interrupt(void) { IFS0bits.T2IF = 0; /* shazujeme pozadavkovy bit */ asm(" bclr IFS0, #7 "); // nuluji bit pro preteceni citace /* s kmitoctem fCY / 10000 se meni stav na techto pinech * to pouzijeme pro kontrolu kmitoctu vnitrniho oscilatoru * od hrany k hrane to pred zmenou Fosc je 2.7ms, to odpovida 370Hz * a x 10000 odp[ovida 3.7MHz kmitoctu instrukci */ if( j % 100 == 0 ) asm(" btg PORTA, #0 "); /* u bitu RA0 bude videt i na diode prepnuti kmitoctu */ asm(" btg PORTA, #1 "); asm(" btg PORTA, #2 "); j++; } /* zaviraci od podprogramu _T2Interrupt retfie prida prekladac sam, je to dano atributem interrupt */