Atmega328P Datasheet 17. External Interrupt

Started by tha, August 09, 2019, 01:36:22 PM

Previous topic - Next topic

tha

พรายกระซิบบอกมาอีกแล้ว ให้ไปดูที่ ไฟล์ delay.h ใน C:\avr8-gnu-toolchain\avr\include\util ดูแล้วปรากฎว่า ฟังชั่น _delay_ms(); ประกาศตัวแปรเป็น double เลย เท่าไหร่นะ 32 บิทเลยใช่ไหม ส่วนโปรแกรมย่อยของผม ประกาศตัวแปรแค่ unsigned int 16 บิท ซึ่งน้อยกว่า แต่ว่าไม่เกินนี่ก็น่าจะใช้ได้นะใช่ไหม

Quote
void
_delay_ms(double __ms)
{
   double __tmp ;
#if __HAS_DELAY_CYCLES && defined(__OPTIMIZE__) && \
  !defined(__DELAY_BACKWARD_COMPATIBLE__) &&      \
  __STDC_HOSTED__
   uint32_t __ticks_dc;
   extern void __builtin_avr_delay_cycles(unsigned long);
   __tmp = ((F_CPU) / 1e3) * __ms;

   #if defined(__DELAY_ROUND_DOWN__)
      __ticks_dc = (uint32_t)fabs(__tmp);

   #elif defined(__DELAY_ROUND_CLOSEST__)
      __ticks_dc = (uint32_t)(fabs(__tmp)+0.5);

   #else
      //round up by default
      __ticks_dc = (uint32_t)(ceil(fabs(__tmp)));
   #endif

   __builtin_avr_delay_cycles(__ticks_dc);

#else
   uint16_t __ticks;
   __tmp = ((F_CPU) / 4e3) * __ms;
   if (__tmp < 1.0)
      __ticks = 1;
   else if (__tmp > 65535)
   {
      //   __ticks = requested delay in 1/10 ms
      __ticks = (uint16_t) (__ms * 10.0);
      while(__ticks)
      {
         // wait 1/10 ms
         _delay_loop_2(((F_CPU) / 4e3) / 10);
         __ticks --;
      }
      return;
   }
   else
      __ticks = (uint16_t)__tmp;
   _delay_loop_2(__ticks);
#endif
}

ของ winavr ก็จะเหมือนกัน ที่เรา include file มาที่หัวโปรแกรม ไฟล์ก็จะอยู่แถวนี้ ในโปรแกรมของผม ผมก็จะบอกไว้นะว่าไฟล์เหล่านี้อยู่ที่ไหน ลองไล่เช็คทำความเข้าใจดูนะ ดูบ่อยๆสักวันคงจะเข้าใจ ก็จะเก่งการเขียนโปรแกรมครับ

tha

พรายกระซิบบอกมาให้ประกาศตัวแปรให้เป็น double เหมือนกันไว้ พอ build ปรากฎว่า code size ลดจาก 1646 bytes เหลือ 1582 bytes

tha

ถ้าเราไม่ optimize code (ตั้ง project->configuration options->optimization = -O0) เวลา build ก็จะขึ้น warning เหลืองเตือนว่า  # warning "Compiler optimizations disabled; functions from <util/delay.h> won't work as designed"
ผมเลยเช็คโดยการตั้งให้เวลาเยอะๆ อย่าง 5000ms แล้วใช้แท๊บเล็ตจับเวลาดู เวลาหลอด LED ติดก็ใกล้เคียงกับ 5 วินะ คงจะใช้ได้ใช่ไหม ลองเช็ตดูกัน

แต่พอเราบีบอัด optimize code (ตั้ง project->configuration options->optimization = -Os) เวลา build ก็จะขึ้น error เลย build ไม่ผ่านที่โปรแกรมย่อย delay_ms อย่างนี้หมายถึงว่า ถ้าเรา optimization = -Os เราก็ใช้ฟังชั่น   _delay_ms(500); ในส่วนต่างๆของโปรแกรมได้เลย เวลา build มันก็จะ potimize code ให้เราเอง



tha

แต่ต่อไปโปรแกรมเราจะตั้งไม่ให้ optimize (ไม่ตั้ง optimization = -Os) นะ จะตั้ง optimization = -O0 นะ ถ้าตั้งบีบอัด flag ที่เราตั้งจะถูกบีบอัดเช็ค flag ไม่ได้เลย (มั่วเหมือนกัน GCC) ตกลงตามนี้นะ เจอปัญหาก็แก้ไปเรื่อยๆครับ

tha

ตัวอย่างที่ให้ไปมันผิดอยู่นะ ให้ประกาศตัวแปร global variable ประกาศเป็น volatile ขึ้นหน้านะครับ
อย่างเช่นโปรแกรม Test_PCINT_Board2_2 ก็ประกาศอย่างนี้
Quote
volatile uint8_t a = 0;
volatile uint8_t b = 0;
เพื่อให้มันไม่ optimize ตัวแปร a, b เวลาตอนเราบีบอัด code นะ
   คราวนี้เราก็มาตั้งให้ optimize (บีบอัดโค๊ด) อย่างนี้ได้ (project->configuration options->optimization = -Os) ขนาดของ code size ก็จะลดลงมาเยอะเลย

ส่วนฟังชั่นการดีเลย์ก็ให้กลับมาใช้ฟังชั่น _delay_ms(100); ได้ตามปกติครับ

ส่วนตัว compiler ก็กลับมาใช้ winavr ก็ได้ครับ

ปล. ไม่ได้ทำมานานชักจะลืมเลยผิดพลาด ต้องขออภัยด้วย
      ขอโฆษณาหน่อย ก็เคยบวชเรียนมา ก็ว่านั่งสมาธิ พุท-โธๆ นี้ดี ทำให้ลมหายใจนี้ยาวลึกละเอียด เป็นผลดีต่อสุขภาพไม่ค่อยเป็นหวัดเป็นไอ
      อ่านหนังสือก็มีสมาธิดี เพราะนิวรณ์มันลดลง เราก็จะมีสุขมากขึ้น สุขที่ใจสงบ ชีวิตเราก็จะดีขึ้น ก็ทำง่ายๆเราหัดทำเองก็ได้ วันละนิดวันละ
      หน่อย เดี๋ยวเราก็จะรู้เองว่าควรทำอย่างไร มันก็จะดีขึ้นเรื่อยๆเองครับ
       http://www.84000.org/tipitaka/dic/d_item.php?i=225