W
mikrokontrolerach PIC (PIC24/ds33) mamy trzy typy Timerów : A, B, C
Wszystkie
Timery są standardowo 16 bitowe (PIC24/ds33). Jest możliwość połączenia
dwóch Timerów z grupy B lub C i stworzyć jeden timer 32 bitowy .
•
Typ A timer (Timer1)
•
Typ B timer (Timer2, Timer4, Timer6 and Timer8),
określane jako Timerx
Cechą
charakterystyczną Typu A jest możliwość podpięcia
oscylatora zegarkowego typu 32 kHz i wtedy timer typu A tyka nam jak
zegarek mu zagra :) Drugą cechą wyróżniającą typ A jest tryb
licznika asynchronicznego (Asynchronous Counter mode). Co oznacza ,
że timer zlicza nam tak jak mu będzie taktowało zewnętrzne źródło
i w tym trybie nie ma synchronizacji zegarem systemowym
Cechą
charakterystyczną dla typu B i C jest możliwość łączenia
timerów z tych grup jako timery 32 bitowe.
Cechą
charakterystyczną typu C jest współpraca z modułem ADC.
To
tyle ogólnie o typach timerów a teraz pokrótce o trybach pracy
timerów :
• Timer mode
• Timer mode
Najbardziej
popularny tryb , którego będziemy najczęściej używać , na
obrazku poniżej mamy sposób ustawienia Timera1 (typ A) i przebiegi
czasowe zdarzeń . Wykres w zasadzie wszystko tłumaczy a kod
pokazuje w jakich rejestrach trzeba grzebać i na jakich bitach.:
•
Gated Timer mode
W trybie Gated timer (bramkowany timer) jest wyzwalany zboczem narastającym sygnału zewnetrznego podanego na nóżkę TnCK. Timer zlicza w takt zegara wewnętrznego dopóki trwa poziom wysoki sygnału zewnętrznego. Przerwanie jest generowane przy każdym zboczu opadającym sygnału zewnętrznego. Timer ten przyda się w pomiarach czasu trwania jakiegoś procesu.
W praktyce możemy z tego trybu skorzystać np. jeśli chcemy zmierzyć czas nasłonecznienia za jakiś okres czasu.
I wym przypadku pismo obrazkowe najlepiej tłumaczy o co biega :
W praktyce możemy z tego trybu skorzystać np. jeśli chcemy zmierzyć czas nasłonecznienia za jakiś okres czasu.
I wym przypadku pismo obrazkowe najlepiej tłumaczy o co biega :
•
Synchronous Counter mode
W
tym trybie pracy , każde narastające zbocze sygnału zewnętrznego
(niezależne od zegara systemowego) jest zliczane . Przy czym cała
ta operacja jest synchronizowana przez zegar systemowy . Przerwanie
generuje przepełnienie rejestru TMRx (0-65535) lub ustawiona wartość
w rejestrze PRx.
Możemy
sobie zarzyczyć
np. aby po zliczeniu 1000 narastających zbócz
:) sygnału zewnętrznego wygenerowało nam się przerwanie i taki
przykład serwuje nam nota
katalogowa ale
przebiegów już zabrakło :)
:
•
Asynchronous Counter mode (Type A timer only)
Ten
tryb zarezerwowany jest tylko dla timera typu A. Zliczany jest każdy
narastający sygnał z zewnętrznego źródła (niezależne od zegara
systemowego) ale w tym przypadku brak synchronizacji zegarem
systemowym. Daje to różne ciekawe możliwości m.in. podpinamy
kwarc zegarkowy 32 kHz i po zliczeniu 32767 zbócz narastających
generujemy przerwanie co daje nam przerwanie co 1 sekundę. Poniżej
stosowny przykład z noty katalogowej :
Timer Programowy jest tutaj pomocnikiem , który umożliwia dowolne wydłużanie podstawy timera sprzętowego. Taki zabieg wynika z tego, że 16-bitowy timer sprzętowy da nam maksymalnie ciut ponad 400 ms czyli trochę brakuje do 1 s. Gdyby zastosować timer 32 bitowy a taka możliwość jest !!!! w naszym PIC24 to hulaj dusza, ograniczenie od góry to ok 27 tys sekund (ok 7.5 h)!!!!.Czyli timer 32 bitowy można ustawić tak aby przerwanie generować nawet co ok 7.5 h jak dla mnie mocna właściwość.
Pozdrawiam
picmajster.blog@gmail.com
Link :
http://ww1.microchip.com/downloads/en/DeviceDoc/70244B.pdf
1 #include "xc.h" /* wykrywa rodzaj procka i includuje odpowiedni plik 2 nagłówkowy "p24HJ128GP502.h"*/ 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <stdint.h> /*dyrektywy do uint8_t itp*/ 6 #define FCY 40000000UL /* podajemy wartość ustawionego zegara (40 MHz), ważne 7 aby przed includowaniem <libpic30.h>, potrzebne to jest to wyliczania delay-i*/ 8 #include <libpic30.h> // biblioteka dająca dostęp do delay-i. 9 10 /* 11 * to co możemy ustawić za pomocą '#pragma' jest dostępne w pliku 12 * xc16/docs/config_index.html 13 */ 14 #pragma config JTAGEN = OFF 15 // Watchdog timer enable/disable by user software 16 #pragma config FWDTEN = OFF 17 18 //********************Start Ustawień Zegara************************ 19 /* 20 * Fcy - zegar instrukcji , Fosc - zegar rdzenia (jest zawsze dwa razy wiekszy 21 * od zegara instrukcji)) Ustawiamy zegar instrukcji na 40 Mhz z wewnętrznego 22 * oscylatora Fin=7.37 MHz w/g wzoru Fcy=Fosc/2 gdzie Fosc=Fin x (M/(N1+N2)) 23 * gdzie M=43, N2=2, N1=2 ustawiane w rejestrach PLLFBD/PLLPOST/PLLPRE 24 */ 25 //Select Internal FRC (Fast RC Oscillator) 26 #pragma config FNOSC = FRC // FOSCSEL-->FNOSC=0b000 (Fast RC Oscillator (FRC)) 27 //Enable Clock Switching and Configure 28 #pragma config FCKSM = CSECMD //FOSC-->FCKSM=0b01 - włącz zegar 29 #pragma config OSCIOFNC = OFF //FOSC-->OSCIOFNC=1 - Fcy będzie na pinie OSCO 30 31 /*Blok makra/definicje*/ 32 #define LED1_TOG PORTA ^= (1<<_PORTA_RA1_POSITION) /*zmienia stan bitu na przeciwny*/ 33 /*Koniec Bloku makra/definicje*/ 34 35 /*Blok deklaracje funkcji*/ 36 void InitTimer1(void); //deklaracja funkcji do inicjacji Timera1 37 /*Koniec Bloku deklaracje funkcji*/ 38 39 /* Blok deklaracje/definicje zmiennych globalnych*/ 40 /*Timery Programowe*/ 41 volatile uint8_t Timer1_Programowy , Timer2_Programowy ; 42 /*Koniec Bloku deklaracje/definicje zmiennych globalnych*/ 43 44 int main(void) { 45 46 /*Config PLL prescaler, PLL postscaler, PLL divisor*/ 47 PLLFBD = 41 ; //M=43 (0 bit to 2 stąd 41 = 43 patrz w rejestrze), tutaj 3.685 x 43 = 158.455MHz 48 CLKDIVbits.PLLPRE=0 ; //N1=2, tutaj 7.37 MHz / 2 = 3.685 MHz 49 CLKDIVbits.PLLPOST=0 ; //N2=2, tutaj 158.455 MHz / 2 = 79.2275 MHz (Fosc) 50 /* 51 * UWAGA przerwania muszą być wyłączone podczas wywoływania poniższych 52 * dwóch funkcji __builtin_write_...brak definicji w pliku nagłówkowym 53 * to wewnętrzne funkcje kompilatora patrz help M-LAB IDE 54 * i datasheet str 140(11.6.3.1 Control Register Lock) 55 */ 56 /*Initiate Clock Switch to Internal FRC with PLL (OSCCON-->NOSC = 0b001)*/ 57 __builtin_write_OSCCONH(0x01); //tutaj argumentem jest wartość z NOSC 58 /*Start clock switching*/ 59 __builtin_write_OSCCONL(0x01); 60 61 /*Wait for Clock switch to occur*/ 62 while(OSCCONbits.COSC !=0b001); 63 64 /*Wait for PLL to lock*/ 65 while(OSCCONbits.LOCK !=1) {}; 66 //**************************Koniec ustawień zegara*********************** 67 /* 68 * wyłączamy ADC , wszystkie piny chcemy mieć cyfrowe 69 * pojedyńczo piny analogowe wyłączamy w rejestrze AD1PCFGL 70 * Po resecie procka piny oznaczone ANx są w trybie analogowych wejść. 71 */ 72 PMD1bits.AD1MD=1 ; //wyłączamy ADC 73 /* 74 * ustawiamy wszystkie piny analogowe (oznacznone ANx) jako cyfrowe 75 * do zmiany mamy piny AN0-AN5 i AN9-AN12 co daje hex na 16 bitach = 0x1E3F 76 */ 77 AD1PCFGL = 0x1E3F ; 78 79 TRISAbits.TRISA1 = 0 ; // RA1 jako wyjście 80 81 InitTimer1(); /*wywołanie funkcji odpalającej Timer1, przerwanie co 100ms*/ 82 83 while(1) 84 { 85 /*Główna Pętla Programu*/ 86 if(!Timer1_Programowy) { 87 Timer1_Programowy = 10 ; /*Timer1 sprzętowy x Timer1_Programowy = 100ms x 10 = 1 s*/ 88 LED1_TOG ; /*zmieniaj stan wyjścia na przeciwny*/ 89 } 90 91 } 92 93 return 0; 94 } 95 96 void InitTimer1(void){ 97 /*konfiguracja Timer1*/ 98 T1CONbits.TON = 0 ; /*Stop the timer1*/ 99 TMR1 = 0x0000 ;/*Clear timer register*/ 100 /*Zegar ok 40 MHz Prescaler 1:64; PR1 Preload = 61897; Actual Interrupt Time = 100 ms*/ 101 T1CONbits.TCKPS = 0b10 ; /*Prescaler 1:64*/ 102 103 /*konfiguracja przerwań*/ 104 IFS0bits.T1IF = 0; /*Clear Timer1 Interrupt Flag*/ 105 IEC0bits.T1IE = 1; /*Enable Timer1 Interrupt*/ 106 107 /*ustaw priorytet dla przerwania*/ 108 IPC0bits.T1IP = 0b100 ; /*Set Timer1 Interrupt Prioryty Level 4*/ 109 110 /*TMR1 zlicza do wartości ustawionej w PR1 jeśli TMR1=PR1 zgłaszane jest przerwanie*/ 111 /*40MHz / Prescaler / PR1 = ok 10 Hz (100ms)*/ 112 PR1 = 61897; /*Load period value*/ 113 T1CONbits.TON = 1 ; /*Start the timer1*/ 114 } 115 116 /*Obsługa wektora przerwania dla Timer1*/ 117 void __attribute__((interrupt, no_auto_psv))_T1Interrupt() 118 { 119 /*kod użytkownika do obsługi przerwania*/ 120 uint8_t x; 121 x = Timer1_Programowy ; 122 if (x) Timer1_Programowy = --x ; 123 x = Timer2_Programowy ; 124 if (x) Timer2_Programowy = --x ; 125 126 /* Clear Timer1 interrupt */ 127 IFS0bits.T1IF = 0 ; /*Clear Timer1 Interrupt Flag*/ 128 }
Brak komentarzy:
Prześlij komentarz