การสร้างฟังก์ชันนับเวลาทุก ๆ 1 มิลลิวินาที

  ในการทำงานกับไมโครคอนโทรลเลอร์บ้างครั้งเราคง อยากที่จะได้ฟังก์ชันที่สามารถนับเวลาทุก 1 มิลลิวินาทีและนับต่อเนื่องไปเรื่อย ๆ จนกว่าเราจะปิดเครื่องหรือรีเซตจึงกลับมาเริ่มตันนับเวลาใหม่ ฟังก์ชันนับเวลาแบบนี้มีประโยชน์มาก เมื่อเราต้องการให้โปรแกรมยังคงทำงานส่วนอื่น ๆ ไปก่อน จนกว่าจะได้เวลาที่ต้องการแล้วค่อยทำงานในส่วนของเวลาที่ได้กำหนดไว้ จากนั้นก็กลับไปทำงานอื่นตามเดิมจนกว่าจะได้เวลาครบตามที่กำหนดอีกครั้ง 
        
        ฟังก์ชันที่เราสร้างขึ้นมานี้ ให้ชื่อว่า millis()บางท่านอาจจะคุ้น ๆ กับชื่อฟังก์ชันนี้ ถ้าท่านเคยได้เล่นไมโครคอนโทรลเลอร์ที่ใคร ๆ ก็บอกว่าง่าย จะมีฟังก์ชันนี้มาให้แล้ว แต่ถ้าท่านอยากรู้ว่า dsPIC30F ก็สามารถทำฟังก์ชันดังกล่าวได้ง่าย ๆ เช่นเดียวกัน  (ตามตัวอย่างบทความนี้) และอยากรู้ว่าง่ายอย่างไรลองมาลงคอร์สเรียนกับเราครับ เรื่องที่ยากสำหรับไมโครคอนโทรลเลอร์จะกลายเป็นเรื่องที่ง่ายในทันที  :)



ความรู้ทั่วไป
        การนับเวลาด้วยโมดูล Timer1 มีสิ่งที่ต้องทำความเข้าใจดังนี้คือ

  • ค่า PLLx (Phase Lock Loop) หรือตัวคูณความถี่ มีค่าเท่ากับ 1, 4, 8, และ 16 
  • ค่า Prescaler หรือตัวหารความถี่ มีค่าเท่ากับ 1, 8, 64 และ 256 
  • internal instruction cycle clock เท่ากับ Fosc/4 
  • Timer1 มีขนาด 16 บิต นับได้สูงสุดเท่ากับ 65535 ค่า และเมื่อนับจนถึงค่าสูงสุด (65535) จะกลับไปเริ่มต้นนับศูนย์ใหม่ การกลับไปนับเริ่มต้นใหม่นี้ เรียกว่าการเกิดโอเวอร์โฟลว์ของการนับ 
  • การนับหนึ่งครั้งของ Timer1 จะใช้เวลาเท่ากับ T = 1/f = 1/(Fosc/4) และเมื่อเกี่ยวข้องกับค่า PLLx และ Prescaler จะได้สมการการนับดังนี้

T = 1/ [(Fosc X PLLx) / (4 X Prescaler)]

  • เมื่อมีการเปิดใช้งานอินเตอร์รัปต์ ทุก ๆ การเกิดโอเวอร์โฟลว์จะเกิดอินเตอร์รัปต์ 
วงจรทดลองตามรูป

 
โค้ดโปรแกรมก็ตามนี้ครับ (โค้ดสำหรับไมโครคอนโทรลเลอร์ dsPIC30F)

1  : /*****************************************
2  : Author:     prajin palangsantikul
3  : Course:     dsPIC Microcontroller
4  : WWW:        www.appsofttech.com
5  : *****************************************/
6  : #include
7  : #include
8  :
9  : _FOSC(CSW_FSCM_OFF & XT);
10 : _FWDT(WDT_OFF);
11 :
12 : #define PLLx    1         // XT
13 : #define Fosc    7372800   // 7.3728MHz
14 : #define Pre     256      // Prescaler
15 : #define Tc      ((4.0*Pre)/(Fosc*PLLx)) // Timer Count
16 : #define To      (Tc*1000) // Timer Overflow (ms)
17 : #define T1ms    (1/To)   // Count 1 ms
18 :
19 : volatile unsigned long t_millis = 0;
20 : unsigned long millis();
21 :
22 : const long interval = 1000;
23 : int ledState = 0;
24 : unsigned long previousMillis = 0;
25 :  
26 : // Setup function
27 : void setup(void)
28 : {
29 :   OpenTimer1(T1_ON &
30 :              T1_IDLE_CON &
31 :              T1_GATE_OFF &
32 :              T1_PS_1_256 &
33 :              T1_SYNC_EXT_OFF &
34 :              T1_SOURCE_INT,
35 :              T1ms);
36 :
37 :   ConfigIntTimer1(T1_INT_ON);
38 :  
39 :   _TRISD0 = 0;    // Set RD0 Output
40 : }
41 :
42 : // Main function
43 : int main(void)
44 : {
45 :   char ledState;
46 :   unsigned long currentMillis;
47 :  
48 :   setup();
49 :  
50 :   while(1) {      // Loop
51 :     currentMillis = millis();
52 : 
53 :     if(currentMillis - previousMillis >= interval) {
54 :       previousMillis = currentMillis;  
55 :
56 :       if (ledState == 0)
57 :         ledState = 1;
58 :       else
59 :         ledState = 0;
60 :
61 :       _LATD0 = ledState;
62 :     }
63 :   }
64 : }
65 :
66 : unsigned long millis()
67 : {
68 :   return t_millis;
69 : }
70 :
71 : // Timer1 Interrupt
72 : void _ISR _T1Interrupt(void)
73 : {
74 :   t_millis++;
75 :   _T1IF = 0;
76 : }

ความคิดเห็น

แสดงความคิดเห็น

โพสต์ยอดนิยมจากบล็อกนี้

สร้างต้นคริสต์มาสด้วย JAVA

ฟังก์ชัน SerialEvent กับ Arduino

การใช้งาน PIC18Fxxxx กับ MPLAB X + XC8 ด้วย Peripheral Libraries (PLIBS)