ธันวาคม 13, 2018, 07:38:17 am *
ยินดีต้อนรับคุณ, บุคคลทั่วไป กรุณา เข้าสู่ระบบ หรือ ลงทะเบียน
ส่งอีเมล์ยืนยันการใช้งาน?

เข้าสู่ระบบด้วยชื่อผู้ใช้ รหัสผ่าน และระยะเวลาในเซสชั่น
   หน้าแรก   ช่วยเหลือ เข้าสู่ระบบ สมัครสมาชิก  
หน้า: [1]   ลงล่าง
  พิมพ์  
ผู้เขียน หัวข้อ: Tip&Trick PIC Microcontroller, 1.000mS Timer0's Interrupt (In-depth explanation)  (อ่าน 11069 ครั้ง)
0 สมาชิก และ 1 บุคคลทั่วไป กำลังดูหัวข้อนี้
ShadowMan
Administrator
Hero Member
*****
ออฟไลน์ ออฟไลน์

เพศ: ชาย
กระทู้: 8272


ShadowWares


| |
« เมื่อ: มีนาคม 13, 2011, 08:02:06 pm »

วันนี้เขียนโปรแกรมนาฬิกาเล่นๆ ตั้งใจจะให้ความละเอียดของเวลามีค่า 1mS
นั่งคำนวณเวลาอยู่หลายรอบ ไม่ลงตัวสักที ทั้งๆ ที่รู้อยู่ในใจว่าไม่มีทางจะลงตัว ที่ XTAL 8MHz
และใช้ Prescaler เท่ากับ 1:8 แน่นอน ค่านี้เป็นค่าที่เหมาะสมสำหรับ Timer0 (8-bit)
ที่ XTAL 8MHz ไม่มีอะไรที่เป็นไปไม่ได้ดังนั้นต้องหาลู่ทางกันต่อไป
ด้วยโครงสร้างของ PIC16F และหลายๆ ตัว FCY=FOSC/4 นั่นคือ 1 Machine cycle (MC) จะมีค่าเท่ากับ
4/8MHz ซึ่งเท่ากับ 0.5uS ห่างกันตั้ง 2,000 เท่าเมื่อเทียบกับเวาลาที่ต้องการ คือ 1mS แบบนี้ก็หมูๆแล้ว
กลับไปพิจารณากันที่โปรแกรมต่อ มองอะไรไม่ค่อยออก งั้นเข้าไปดูใน Assembly แล้วกัน ชัดเจนเลย
แบบนี้ก็ต้องชดเชยค่าจากการคำนวณกันหน่อย เพราะการ Interrupt ก็ต้องเสียเวลาเล็กน้อย ก่อนที่
CPU จะเข้ามาใน ISR นั่นคือ 4 MC ตามด้วยการ save context (เรื่องนี้ว่างๆ จะมาเล่าให้ฟัง เพราะน่าสนใจ
สำหรับคนที่เล่น RTOS หรือนักพัฒนา Real time Kernel ทั้งหลาย) อีก 9 MC ตามมาด้วยการ Check ว่ามี
การเปิดใช้งาน Interrupt อยู่จริงหรือเปล่า ตรงนี้เสียไปอีก 2 MC เท่านั้นยังไม่พอ การ re-load Timer
ต้องทำแบบ Manual (ไม่ได้เป็น Auto-Reload) ทำให้เสียไปอีก 4 MC รวมกันทั้งหมดก็ปาเข้าไป 19 MC
นั่นก็คือ 2 Clock ของ Timer (2*8 MC) กับอีก 3 MC นอกจากนี้อย่าลืมว่าหลังจาก Timer ถูกเขียน
ค่าใหม่ลงไป การนับจะเริ่มใหม่ และเวลาจะเริ่มจาก MC ต่อไป แน่นอน ก็ต้องเสียไปอีก 1 MC
สรุปแล้วตอนนี้ เศษเหลือคือ 4 MC หาคำสั่งที่ใช้ 1 MC มาใส่ลองไป 1 คำสั่ง (ทำซ้ำ 4 ครั้ง) ในที่นี้เลือก
คำสั่ง nop (no operation)ที่เลือกเป็น asm() เพราะต้องการความมั่นใจว่า optimizer จะไม่ ignore คำสั่ง
ไร้ประโยชน์เหล่านี้ (ส่วนนี้ค่อยเล่าให้ฟังในส่วนของ Optimization)  ต่อไปคือ 2 Clock ของ Timer
หรือ 16 MC นั่นเอง ค่าเหล่านี้เรีกว่า "Overhead" ต่อไปก็ต้องทำการชดเชยลงไปที่ค่า reload ของ Timer
ในที่นี้คือ TIMER_VALUE แต่อย่าเผลอนะครับ Timer จะ Overflow เมื่อค่าวนกลับ สำหรับ Timer แบบ 8-bit
จะเกิด Overflow ขั้นเมื่อค่าของ Timer เปลี่ยนจาก 0xFF เป็น 0x00 นั่นเป็นตัวบอกว่าจะต้องชดเชยไปอีก 1 Clock
ของ Timer หรือ 8 MCY ผลที่ได้ก็เป็นไปตามโปรแกรม (ดูในส่วน define TIMER_VALUE) เก็บไว้ใช้ได้ตราบนานเท่านาน

ลงเชิงลึกไปหน่อยครับ แต่ในงานที่ต้องการความเที่ยงตรงสูงๆ สิ่งเหล่านี้เป็นเพียงเรื่องพื้นฐานเท่านั้น
หวังเป็นอย่างยิ่งว่าจะเป็นประโยชน์ (หรืออาจเป็นโทษ) กับท่านผู้อ่านนะครับ :)


Code: (c)
/************************************************
* FILE:      MAIN.C                              *
* CPU:      PIC16F887                           *
* XTAL:     8MHz                                *
* IDE:      MPLAB IDE v8.63                     *
* COMPILER: HI-TECH PIC-C Compiler vV9.71a      *
* AUTHOR:   SANTI NURATCH @ SHADOWWARES.COM     *
* DATE:     13 March, 2011                      *
* DESCRIPTION:                                  *
*   Using Timer0 and its interrupt.             *
*   The T0's interrupt is trigered every 1mS.   *
*************************************************/

#include <htc.h>
//................................................................................

__CONFIG(INTIO & WDTDIS & PWRTDIS & MCLRDIS & UNPROTECT); 
#define _XTAL_FREQ          8000000.0f         /* Clock Source            */ 
#define _FCY            _XTAL_FREQ/4.0f      /* CPU and Peripheral Clock */ 
#define TIMER_TICK_RATE      1000.0f         /* System Clock Rate      */ 
#ifdef _TIMING_DEBUG_ 
#define TIMER_PRESCALER    2.0f               /* PRES=2, see in Init()   */ 
#else   
#define TIMER_PRESCALER    8.0f               /* PRES=8, see in Init()   */ 
#endif 
#define TIMER_VALUE       (256f+3f-(_FCY/TIMER_PRESCALER/TIMER_TICK_RATE)+0.5)   
                                    /*-4 is an overhead compensation */ 
//................................................................................
volatile unsigned int ISRTickCounter = 0;

//................................................................................

void SysInit(void){
   TMR0   = (unsigned char)TIMER_VALUE;
   GIE    = 1;      // Enable Global Interrupt
   PEIE   = 1;      // Enables peripheral interrupts
   OPTION = 2;    // 1:8 T0's Prescaler
   #ifdef _TIMING_DEBUG_
   OPTION = 0;      // 1:2 T0's Prescaler
   #endif
   T0IF   = 0;      // Clear interrupt flag
   T0IE   = 1;      // Enable T0's interrupt
   TMR0   = 0;      // TIMER_VALUE   
}

static void interrupt ISR(void) @ 0x004{
   if(T0IE && T0IF){
      asm("nop"); asm("nop");   /* Overhead compensation */
      asm("nop"); asm("nop");    
      #ifdef _TIMING_DEBUG_
      TMR0 = -8;   /* 16uS ISR Freq @ FOSC=8MHz, PRES=2*/      
      #else
      TMR0 = (unsigned char)TIMER_VALUE;
      #endif
      T0IF = 0;
      ISRTickCounter++;
   }
}
   
void main(void){
   SysInit();
   while(1);      
}   




ต่อไปก็มาดูหลักฐานกันครับ ว่าทุกสิ่งทุกอย่างนั้นถูกจริงหรือเปล่า
ใช้  Oscilloscope มาวัดสัญญาณหรอ? ไม่ใช่หรอกเพราะมันบอกอะไรไม่ค่อยได้
ทำอย่างไรดี วิธีง่ายๆ และยืนยันได้ครับ ใช้ Simulator ที่ติดมากับ MPLAB นั่นแหละ
นับกันเป็น Machine Cycle ไปเลย จากข้อมูลของ Hardware ที่บอกไปด้านบน
ระยะเวลา 1mS ตะต้องใช้จำนวน Machine Cycle เท่ากับ 2,000 Cycles (2,000*0.5=1,000 = 1mS)
ผลการทำงาน ก็เป็นไปตามที่คำนวณทุกประการครับ ตามรูปด้านล่าง



บันทึกการเข้า

By SDW: Do No Wrong Is Do Nothing
          If you want to increase your success rate, double your failure rate
วิสิทธิ์ แผ้วกระโทก
Global Moderator
Sr. Member
*****
ออฟไลน์ ออฟไลน์

กระทู้: 307



| |
« ตอบ #1 เมื่อ: มีนาคม 13, 2011, 10:35:17 pm »

เจอบทความชุดนี้ เข้าไป ต้องกลับมานั่งทบทวนกันใหม่เลยดีไหม เห็นทีต้องขอนัั่งอ่านหลายๆ รอบแล้วครับเนี้ย

อ่านไป ทำความเข้าใจไปกันใหม่  ลึกซึ้งจริงๆ ครับ   >:(
บันทึกการเข้า

ShadowMan
Administrator
Hero Member
*****
ออฟไลน์ ออฟไลน์

เพศ: ชาย
กระทู้: 8272


ShadowWares


| |
« ตอบ #2 เมื่อ: มีนาคม 13, 2011, 11:05:35 pm »

อย่าไปสนใจเรื่องแบบนี้ให้มากจนเกินไปครับ บ่อยครั้งมันก็หาสาระไม่ได้ เสียเวลาโดยใช่เหตุ
แต่ถ้ามองทุกสิ่งทุกอย่างที่เรากำลังสนใจอยู่ออก ไม่ว่าปัญหาจะมารูปแบบไหน เราจะ คิด และ วิเคราะห์ ได้ชนิดที่เรียกว่า "แตกฉาน"

บันทึกการเข้า

By SDW: Do No Wrong Is Do Nothing
          If you want to increase your success rate, double your failure rate
วิสิทธิ์ แผ้วกระโทก
Global Moderator
Sr. Member
*****
ออฟไลน์ ออฟไลน์

กระทู้: 307



| |
« ตอบ #3 เมื่อ: มีนาคม 13, 2011, 11:24:50 pm »

บอกตามตรง ผมอ่านบทความพี่ทีไร เหมือนกับว่า ผมต้องถอยกลับมาก้าวหนึ่งเสมอ ก้าวที่ไปข้างหน้าเมื่อกี้ เหมือนมันไม่มั่นคง เหมือนเราก้าวไปแบบไม่มั่นใจ ต้องถอยกลับมาก่อนเสมอ

จนบางที ก็รู้สึกเหมือนความรู้ที่มีอยู่ มันกระจัดกระจาย ยังคลุมเครืออยู่ เหมือนมอกสีจางๆ ปกคลุมทางเดินอยู่อย่างงั้น ครั้นจะไม่สนใจรายละเอียดพวกนั้น ก็ไม่ได้หน่ะครับ เวลาเจอปัญหา ก็มักจะมาจากที่เราพื้นฐานไม่แน่น หรือ ดูไม่ถี่ถ้วน มันก็เลยทำให้แต่ละก้าว เหมือนก้าวไปอย่างไม่มั่นคง เหยียบได้ไม่เต็มเืท้า  :'( 

ผมมักไม่ค่อย พอใจกับความรู้ที่ผมมีอยู่เท่าไหร่ เหมือนๆ มัน แบบ งูๆ ปลาๆ ยังงัยไม่ทราบ แต่ก็จะพยายามครับ  ;D ;D

บ่นๆ ไปอย่างงั้นแหละครับ รออ่านเนื้อหาต่อไปครับ

ปล.ถ้ามีหัวข้อไหน ที่มันมีรายละเิีอียดปลีกย่อย รบกวนพี่ ทิ้ง Keyword ไว้ก็ได้ครับ เดี๋ยวผมลองไปค้นๆดูในเนตดูก่อน ก็ได้ครับ (แต่ก็กลัวจะไปลึก จนนอกประเด็นไป เหมือนกัน)

บันทึกการเข้า

ShadowMan
Administrator
Hero Member
*****
ออฟไลน์ ออฟไลน์

เพศ: ชาย
กระทู้: 8272


ShadowWares


| |
« ตอบ #4 เมื่อ: มีนาคม 13, 2011, 11:45:54 pm »

อย่าไปสนใจว่าเรารู้ลึกตื่นแค่ไหน แต่ให้สนใจว่า เราทำอะไรกับความรู้ที่เรามี
ผมติดตามผลงานของคุณ dynamic อยู่เหมือนกัน ผมว่าคุณใช้ความรู้ที่มีอยู่ได้อย่างดีเยี่ยมแล้วครับ
แบ่งสิ่งที่รู้ให้คนอื่น ผมชื่นชมคนแบบนี้

เรื่องความไม่มันใจในสิ่งที่รู้ ระแวงทุกครั้งที่ทำสิ่งต่างๆ นั่นเป็นสัญญาณที่ดีครับ เพราะมันจะกระตุ้นให้เรา
ดิ้นรนหาวิธีเจาะลึกลงไปให้ถึงเก่น

บทความแนวนี้ที่ผมเขียน ส่วนมากจะหาอ่านในเน็ต หรือในหนังสือไม่ค่อยได้ครับ อาจจะได้ แต่คงยากพอสมควร
เพราะก่อนจะเขียนบทความ แบบถ่ายทอดประสบการณ์ ผมจะค้นในเน็ตก่อน ถ้ามีอยู่แล้ว ก็ไม่เขียนครับ

สู้ต่อไปครับ ยังไม่ต้องเจาะลึกอะไรมากหรอก แต่สักวันนึงผมมั่นใจว่าคุณจะเข้าใจคำว่า "สูงสุดสู่สามัญ"
  ;D
บันทึกการเข้า

By SDW: Do No Wrong Is Do Nothing
          If you want to increase your success rate, double your failure rate
trose88
Newbie
*
ออฟไลน์ ออฟไลน์

กระทู้: 40


| |
« ตอบ #5 เมื่อ: กรกฎาคม 03, 2011, 09:28:52 am »

น้ำตาจะไหล
บันทึกการเข้า
thapatop
Global Moderator
Newbie
*****
ออฟไลน์ ออฟไลน์

กระทู้: 22


| |
« ตอบ #6 เมื่อ: มกราคม 09, 2012, 11:26:31 pm »

ขอบคุณสำหรับความรู้ดีๆที่แบ่งปันครับอาจารย์
บันทึกการเข้า
rbung
Newbie
*
ออฟไลน์ ออฟไลน์

กระทู้: 6


| |
« ตอบ #7 เมื่อ: กรกฎาคม 20, 2012, 10:22:59 am »

ขอคุณครับ ขอฝากตัวด้วย ผมมือใหม่มาก เวลาเขียนจะเอาแค่ใช้งานได้
เวลาจะตรงหรือไม่ตรง ก็เพิ่ม/ลด delay เอา  คราวนี้จะได้ตรงกับเขาเสียที tongue
บันทึกการเข้า
ShadowMan
Administrator
Hero Member
*****
ออฟไลน์ ออฟไลน์

เพศ: ชาย
กระทู้: 8272


ShadowWares


| |
« ตอบ #8 เมื่อ: กรกฎาคม 20, 2012, 02:17:08 pm »

ยินต้อนรับคุณ rbung ครับ
ฝากตัวไม่ชอบรับเท่าฝากตังค์(แบบไม่เอาคืน)

ทำงาน ผลลัพธ์ออกมาเป็นใช้ได้ ต้องแยกให้ออกว่าสิ่งไหนงาน สิ่งไหนเรียน
แต่ถ้าทำงานโดยไม่เรียนเพิ่มเติม หรือเรียนแบบไม่ได้ลองใช้งาน ความหมายมันเท่ากัน นั่นคือไร้การพัฒนา และอะไรที่ไม่พัฒนาคือไร้ค่า

เป็นกำลังใจให้ครับ สู้ๆ
บันทึกการเข้า

By SDW: Do No Wrong Is Do Nothing
          If you want to increase your success rate, double your failure rate
bufet12123
Newbie
*
ออฟไลน์ ออฟไลน์

กระทู้: 7


| |
« ตอบ #9 เมื่อ: พฤษภาคม 03, 2018, 04:09:28 pm »

ว้าววว ขอบคุณครับ  Shocked cheesy
บันทึกการเข้า

การพนันไม่ได้เป็นสิ่งที่ไม่ดี ไม่เชื่อเข้ามาดู บาคาร่าออนไลน์
หน้า: [1]   ขึ้นบน
  พิมพ์  
 
กระโดดไป: