ฉันใช้ RAM มากเกินไป สิ่งนี้จะวัดได้อย่างไร


19

ฉันอยากรู้ว่าฉันใช้ RAM เท่าใดในโครงการเท่าที่ฉันสามารถบอกได้ว่าไม่มีวิธีการทำงานจริง ๆ (นอกเหนือจากการผ่านและคำนวณด้วยตนเอง) ฉันได้ขึ้นเวทีในโครงการที่ค่อนข้างใหญ่ซึ่งฉันตัดสินใจแล้วว่า RAM ของฉันหมด

ฉันได้พิจารณาสิ่งนี้เพราะฉันสามารถเพิ่มหัวข้อและจากนั้นนรกทั้งหมดก็หลุดไปที่อื่นในรหัสของฉันโดยไม่มีเหตุผลที่ชัดเจน ถ้าฉันมี#ifndefอย่างอื่นมันก็ใช้งานได้อีก ไม่มีอะไรผิดปกติทางโปรแกรมกับรหัสใหม่

ฉันสงสัยว่าในขณะที่ฉันไปถึงจุดจบของ RAM ที่มีอยู่ ฉันไม่คิดว่าฉันใช้สแต็กมากเกินไป (แม้ว่าจะเป็นไปได้) วิธีที่ดีที่สุดในการพิจารณาจำนวนแรมที่ฉันใช้จริงคืออะไร

เมื่อผ่านไปและพยายามที่จะทำงานออกมาฉันมีปัญหาเมื่อฉันไปหา enums และ structs; หน่วยความจำมีราคาเท่าใด

แก้ไขครั้งแรก : นอกจากนี้ฉันได้แก้ไขร่างของฉันตั้งแต่เริ่มต้นสิ่งเหล่านี้ไม่ใช่ผลลัพธ์ที่แท้จริงที่ฉันได้รับในตอนแรก แต่เป็นสิ่งที่ฉันได้รับตอนนี้

  text     data     bss     dec     hex filename
 17554      844     449   18847    499f HA15_20140317w.cpp.elf
 16316      694     409   17419    440b HA15_20140317w.cpp.elf
 17346      790     426   18562    4882 HA15_20140317w.cpp.elf

บรรทัดแรก (ที่มีข้อความ 17554) ไม่ทำงานหลังจากแก้ไขมากแล้วบรรทัดที่สอง (พร้อมข้อความ 16316) ก็ทำงานได้ตามที่ควรจะเป็น

แก้ไข: บรรทัดที่สามมีการทำงานทุกอย่างการอ่านแบบอนุกรมฟังก์ชั่นใหม่ของฉัน ฯลฯ ฉันจะลบตัวแปรทั่วโลกและรหัสซ้ำ ฉันพูดถึงสิ่งนี้เพราะ (สงสัยว่า) มันไม่เกี่ยวกับรหัสนี้ต่อคนมันต้องเกี่ยวกับการใช้ RAM ซึ่งนำฉันกลับไปที่คำถามเดิม "วิธีวัดให้ดีที่สุด" ฉันยังคงตรวจสอบคำตอบอยู่ขอบคุณ

ฉันจะตีความข้อมูลข้างต้นได้อย่างไร

จนถึงตอนนี้ความเข้าใจของฉันคือ:

`TEXT` is program instruction memory
`DATA` is variables (unitialised?) in program memory
`BSS`  is variables occupying RAM

เนื่องจาก BSS มีขนาดน้อยกว่า 1024 ไบต์อย่างมากเหตุใดจึงใช้งานครั้งที่สอง แต่อันแรกไม่ทำงาน ถ้าเป็นเช่นDATA+BSSนั้นทั้งคู่ครอบครองมากกว่า 1024

การแก้ไขอีกครั้ง:ฉันแก้ไขคำถามเพื่อรวมรหัส แต่ตอนนี้ฉันได้ลบออกเพราะจริงๆแล้วมันไม่มีอะไรเกี่ยวข้องกับปัญหา (นอกเหนือจากการเข้ารหัสที่ไม่ดีการประกาศตัวแปรและสิ่งที่คล้ายกัน) คุณสามารถตรวจสอบรหัสโดยการมองย้อนกลับไปผ่านการแก้ไขหากคุณจริงๆต้องการที่จะเห็นมัน ฉันต้องการกลับไปที่คำถามซึ่งมีพื้นฐานมาจาก: วิธีการวัดการใช้ RAM


ฉันคิดว่าฉันจะเพิ่มฉันได้เพิ่มส่วนใหม่ของรหัสในช่วงไม่กี่สัปดาห์ที่ผ่านมาจากนั้น optomised จนกว่าจะได้ผล แต่ตอนนี้ฉันเพิ่งเพิ่มครึ่งโหลไบต์ doz vars และฉันทำ ... :(
Madivad

คุณใช้Stringพิมพ์ในโปรแกรมของคุณหรือไม่? เป็นที่ทราบกันว่าทำการจัดสรรและปล่อยหน่วยความจำแบบไดนามิกบ่อยครั้งซึ่งอาจแยกส่วนฮีปไปยังจุดที่คุณอาจไม่จำ
jfpoilpret

@jfpoilpret ฉันอยู่ห่างจากStrings เพราะค่าใช้จ่าย ฉันมีความสุขที่ได้ทำงานกับ char arrays ที่กล่าวว่าฉันเกือบจะกำหนดอาร์เรย์ char ทั้งหมดของฉันด้วยขนาดคงที่ (ในขณะนี้ฉันมีอาร์เรย์หนึ่งไบต์ที่ไม่หมดจดเพราะฉันเปลี่ยนความยาวเนื้อหาสำหรับการรีคอมไพล์ต่าง ๆ
Madivad

โพสต์รหัสของคุณที่นี่ (หรือไปที่ pastebin ถ้ามันใหญ่เกินไป) อาจจะรู้ว่าปัญหาอะไรที่คุณประสบกับหน่วยความจำ
jfpoilpret

@jfpoilpret ฉันไม่สามารถโพสต์รหัสได้มันใหญ่และน่าเสียดายมาก ๆ กระจายไปทั่ว 16 ไฟล์ มันเป็นโครงการที่ฉันอนุญาตให้เติบโตได้ดีกว่าที่ต้องการ (เป็นหลายโครงการที่รวมเข้าด้วยกัน) ฉันเริ่มต้นตอนนี้เพื่อแยกมันออกซึ่งฉันมั่นใจว่าจะช่วยแก้ไขปัญหาได้ แม้ว่าจะมีบางส่วนของมันฉันต้องการคนที่จะดู (หรือแนะนำฉันใน) ฉันจะโพสต์ในภายหลัง
Madivad

คำตอบ:


15

คุณสามารถใช้ฟังก์ชั่นที่มีให้AVRGCC: การตรวจสอบการใช้งานสแต็ก

ฟังก์ชั่นนี้มีวัตถุประสงค์เพื่อตรวจสอบการใช้งานสแต็ก แต่สิ่งที่รายงานคือ RAM จริงที่ไม่เคยใช้ (ระหว่างการดำเนินการ) ทำได้โดย "จิตรกรรม" (การเติม) RAM ด้วยค่าที่ทราบ (0xC5) จากนั้นตรวจสอบพื้นที่ RAM นับจำนวนไบต์ที่ยังคงมีค่าเริ่มต้นเท่าเดิม
รายงานจะแสดง RAM ที่ไม่ได้ใช้ (RAM ว่างขั้นต่ำ) และเพื่อให้คุณสามารถคำนวณ RAM สูงสุดที่ใช้ (RAM ทั้งหมด - RAM รายงานที่รายงาน)

มีสองฟังก์ชั่น:

  • StackPaintจะดำเนินการโดยอัตโนมัติในระหว่างการเริ่มต้นและ "paints" RAM ที่มีค่า 0xC5 (สามารถเปลี่ยนแปลงได้หากจำเป็น)

  • สามารถเรียกStackCountได้ทุกจุดเพื่อนับแรมที่ไม่ได้ใช้งาน

นี่คือตัวอย่างของการใช้งาน ไม่ได้ทำอะไรมาก แต่มีจุดประสงค์เพื่อแสดงวิธีใช้ฟังก์ชั่น

// -----------------------------------------------------------------------------
extern uint8_t _end;
extern uint8_t __stack;

void StackPaint(void) __attribute__ ((naked)) __attribute__ ((section (".init1")));

void StackPaint(void)
{
#if 0
    uint8_t *p = &_end;

    while(p <= &__stack)
    {
        *p = 0xc5;
        p++;
    }
#else
    __asm volatile ("    ldi r30,lo8(_end)\n"
                    "    ldi r31,hi8(_end)\n"
                    "    ldi r24,lo8(0xc5)\n" /* STACK_CANARY = 0xc5 */
                    "    ldi r25,hi8(__stack)\n"
                    "    rjmp .cmp\n"
                    ".loop:\n"
                    "    st Z+,r24\n"
                    ".cmp:\n"
                    "    cpi r30,lo8(__stack)\n"
                    "    cpc r31,r25\n"
                    "    brlo .loop\n"
                    "    breq .loop"::);
#endif
} 


uint16_t StackCount(void)
{
    const uint8_t *p = &_end;
    uint16_t       c = 0;

    while(*p == 0xc5 && p <= &__stack)
    {
        p++;
        c++;
    }

    return c;
} 

// -----------------------------------------------------------------------------

void setup() {

Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
Serial.println(StackCount(), DEC);  // calls StackCount() to report the unused RAM
delay(1000);
}

โค้ดที่น่าสนใจขอบคุณ ฉันใช้มันและมันบอกว่ามี 600+ ไบต์ แต่เมื่อฉันฝังไว้ในหมวดย่อยมันจะลดลง แต่ไม่ล้างออก ดังนั้นอาจเป็นปัญหาของฉันที่อื่น
Madivad

@Madivad โปรดทราบว่า 600 ไบต์นี้แทนจำนวน RAM ที่มีอยู่ต่ำสุดจนถึงจุดเมื่อคุณเรียกว่า StackCount มันไม่ได้สร้างความแตกต่างจริงๆว่าคุณโทรออกไปลึกแค่ไหนหากรหัสส่วนใหญ่และการโทรที่ซ้อนกันถูกดำเนินการก่อนที่จะเรียก StackCount ผลลัพธ์จะถูกต้อง ตัวอย่างเช่นคุณสามารถปล่อยให้บอร์ดของคุณทำงานได้ในขณะที่ (ตราบเท่าที่ใช้เพื่อให้ครอบคลุมรหัสเพียงพอหรือในอุดมคติจนกว่าคุณจะได้รับพฤติกรรมที่ไม่เหมาะสมที่คุณอธิบาย) จากนั้นกดปุ่มเพื่อรับ RAM ที่รายงาน หากมีเพียงพอก็ไม่ใช่สาเหตุของปัญหา
alexan_e

1
ขอบคุณ @alexan_e ฉันได้สร้างพื้นที่บนจอแสดงผลของฉันที่รายงานตอนนี้ดังนั้นเมื่อฉันก้าวหน้าในอีกไม่กี่วันข้างหน้าฉันจะดูหมายเลขนี้ด้วยความสนใจโดยเฉพาะอย่างยิ่งเมื่อมันล้มเหลว! ขอขอบคุณอีกครั้ง
Madivad

@Madivad โปรดทราบว่าฟังก์ชั่นที่กำหนดจะไม่รายงานผลลัพธ์ที่ถูกต้องหากใช้malloc () ในรหัส
alexan_e

ขอบคุณที่ฉันรู้ว่ามันได้รับการกล่าวถึง เท่าที่ฉันรู้ฉันไม่ได้ใช้มัน (ฉันรู้ว่าอาจมีห้องสมุดที่ใช้มันฉันยังไม่ได้ตรวจสอบอย่างเต็มที่)
Madivad

10

ปัญหาหลักที่คุณมีกับการใช้หน่วยความจำขณะใช้งานจริงคือ:

  • ไม่มีหน่วยความจำในฮีปสำหรับการจัดสรรแบบไดนามิก ( mallocหรือnew)
  • ไม่มีห้องเหลืออยู่บนสแต็กเมื่อเรียกใช้ฟังก์ชัน

ทั้งสองอย่างนั้นเหมือนกับ AVR SRAM (2K บน Arduino) ใช้สำหรับทั้งคู่ (นอกเหนือจากข้อมูลสแตติกซึ่งขนาดไม่เคยเปลี่ยนแปลงระหว่างการทำงานของโปรแกรม)

โดยทั่วไปการจัดสรรหน่วยความจำแบบไดนามิกมักไม่ค่อยใช้กับ MCU มีเพียงไม่กี่ไลบรารีเท่านั้นที่ใช้ (หนึ่งในนั้นคือStringคลาสซึ่งคุณกล่าวถึงว่าคุณไม่ได้ใช้และเป็นจุดที่ดี)

สแต็คและกองสามารถดูได้ในภาพด้านล่าง (ความอนุเคราะห์จากAdafruit ): ป้อนคำอธิบายรูปภาพที่นี่

ดังนั้นปัญหาที่คาดหวังมากที่สุดมาจากการโอเวอร์โฟลว์ของสแต็ก (เช่นเมื่อสแต็คเติบโตขึ้นไปที่ฮีปและโอเวอร์โฟลว์แล้ว - ถ้าฮีปไม่ได้ใช้ในทุกโฟลว์บนโซนข้อมูลแบบคงที่ของ SRAM ในเวลานั้น คุณมีความเสี่ยงสูงเช่น:

  • ความเสียหายของข้อมูล (เช่นกอง ovewrites กองหรือข้อมูลคงที่) ทำให้คุณมีพฤติกรรมที่ไม่สามารถเข้าใจได้
  • สแตกความเสียหาย (เช่นกองหรือข้อมูลคงเขียนทับเนื้อหากอง) โดยทั่วไปนำไปสู่ความผิดพลาด

เพื่อที่จะทราบจำนวนหน่วยความจำที่เหลือระหว่างด้านบนของกองและส่วนบนสุดของสแต็ก (อันที่จริงเราอาจเรียกมันว่าด้านล่างถ้าเราเป็นตัวแทนของกองและกองในภาพเดียวกันตามที่อธิบายด้านล่าง) คุณ สามารถใช้ฟังก์ชั่นต่อไปนี้:

int freeRam () {
  extern int __heap_start, *__brkval; 
  int v; 
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
}

ในโค้ดด้านบนให้__brkvalชี้ไปที่ด้านบนสุดของฮีป แต่0เมื่อไม่มีการใช้ฮีปในกรณีนี้เราใช้&__heap_startซึ่งชี้ไป__heap_startที่ตัวแปรแรกที่ทำเครื่องหมายด้านล่างของฮีป &vคะแนนของหลักสูตรไปที่ด้านบนสุดของสแต็ก (นี่คือตัวแปรสุดท้ายที่ผลักลงบนสแต็ก) ดังนั้นสูตรด้านบนจะส่งคืนจำนวนหน่วยความจำที่มีอยู่สำหรับสแต็ก (หรือฮีปถ้าคุณใช้) เพื่อขยาย

คุณสามารถใช้ฟังก์ชั่นนี้ในตำแหน่งต่างๆของรหัสของคุณเพื่อลองและหาขนาดที่ลดขนาดลงอย่างมาก

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


1
ถึงผู้ดูแล: ขออภัยที่ส่งโพสต์นี้ไปยังวิกิชุมชนฉันต้องทำสิ่งผิดปกติขณะพิมพ์ในระหว่างโพสต์ โปรดนำมันกลับมาที่นี่เนื่องจากการกระทำนี้ไม่ได้ตั้งใจ ขอบคุณ
jfpoilpret

ขอบคุณสำหรับคำตอบนี้ฉันเพียงแค่แท้จริงพบว่าชิ้นส่วนของรหัสแทบชั่วโมงที่ผ่านมา (ที่ด้านล่างของplayground.arduino.cc/Code/AvailableMemory#.UycOrueSxfg ) ฉันยังไม่ได้รวมไว้ (แต่ฉันจะ) เพราะฉันมีพื้นที่ค่อนข้างใหญ่สำหรับการดีบักบนจอแสดงผลของฉัน ฉันคิดว่าฉันสับสนเกี่ยวกับการมอบหมายสิ่งต่างๆแบบไดนามิก คือmallocและnewวิธีเดียวที่ฉันจะทำ? ถ้าเป็นเช่นนั้นฉันไม่มีอะไรเปลี่ยนแปลง นอกจากนี้ฉันเพิ่งได้เรียนรู้ว่า UNO มี SRAM 2K ฉันคิดว่ามันเป็น 1K เมื่อคำนึงถึงสิ่งเหล่านี้ฉันไม่ได้ใช้ RAM หมด! ฉันต้องการดูที่อื่น
Madivad

callocนอกจากนี้ยังมี แต่คุณอาจใช้ libs ของบุคคลที่สามที่ใช้การจัดสรรแบบไดนามิกโดยที่คุณไม่รู้ตัว (คุณต้องตรวจสอบซอร์สโค้ดของการอ้างอิงทั้งหมดของคุณเพื่อให้แน่ใจเกี่ยวกับมัน)
jfpoilpret

2
น่าสนใจ "ปัญหา" เพียงอย่างเดียวคือมันรายงานว่า RAM ว่าง ณ จุดที่เรียกว่าดังนั้นถ้ามันอยู่ในส่วนที่ถูกต้องคุณอาจไม่สังเกตเห็นว่าสแต็คมีการบุกรุกมากเกินไป ฟังก์ชั่นที่ฉันให้มาดูเหมือนจะมีข้อได้เปรียบในพื้นที่นั้นเนื่องจากรายงานว่า RAM ว่างขั้นต่ำจนถึงจุดนั้นเมื่อมีการใช้ที่อยู่ RAM แล้วจะไม่มีการรายงานฟรีอีกต่อไป (ทางด้านล่างอาจมี RAM ที่ว่างอยู่ ไบต์ที่ตรงกับค่า "สี" และรายงานเป็นอิสระ) นอกเหนือจากนั้นอาจมีวิธีหนึ่งที่เหมาะสมกว่าอีกวิธีหนึ่งขึ้นอยู่กับสิ่งที่ผู้ใช้ต้องการ
alexan_e

จุดดี! ฉันไม่ได้สังเกตเห็นจุดเฉพาะนี้ในคำตอบของคุณ (และสำหรับฉันที่ดูเหมือนข้อผิดพลาดในความเป็นจริง) ตอนนี้ฉันเห็นจุดของ "ภาพวาด" เขตปลอดอากรล่วงหน้า บางทีคุณอาจทำให้ประเด็นนี้ชัดเจนยิ่งขึ้นในคำตอบของคุณ?
jfpoilpret

7

เมื่อคุณหาวิธีค้นหาไฟล์. self ที่สร้างขึ้นในไดเรกทอรีชั่วคราวของคุณคุณสามารถดำเนินการคำสั่งด้านล่างเพื่อดัมพ์การใช้ SRAM ซึ่งproject.elfจะถูกแทนที่ด้วย.elfไฟล์ที่สร้างขึ้น ข้อดีของผลลัพธ์นี้คือความสามารถในการตรวจสอบวิธีการใช้ SRAM ของคุณ ตัวแปรทั้งหมดจำเป็นต้องเป็นระดับโลกหรือไม่จำเป็นต้องใช้ทั้งหมดหรือไม่

avr-objdump -S -j .bss project.elf

project.elf:     file format elf32-avr


Disassembly of section .bss:

00800060 <__bss_start>:
        ...

00800070 <measurementReady>:
        ...

00800071 <cycles>:
        ...

00800073 <measurement>:
  800073:       00 00 00 00                                         ....

00800077 <measurementStart>:
  800077:       00 00 00 00                                         ....

0080007b <timerOverflows>:
  80007b:       00 00 00 00

โปรดสังเกตว่านี่จะไม่แสดงสแต็กหรือหน่วยความจำแบบไดนามิกที่ใช้เป็น Ignacio Vazquez-Abrams ที่ระบุไว้ในความคิดเห็นด้านล่าง

นอกจากนี้avr-objdump -S -j .data project.elfยังสามารถตรวจสอบได้ แต่ไม่มีโปรแกรมใดของฉันแสดงผลอะไรเลยดังนั้นฉันจึงไม่สามารถบอกได้อย่างแน่นอนว่ามันมีประโยชน์ มันควรจะแสดงรายการ 'ข้อมูลเริ่มต้น (ไม่เป็นศูนย์) ข้อมูล'


avr-sizeหรือคุณก็สามารถใช้ แต่นั่นจะไม่แสดงการจัดสรรแบบไดนามิกหรือการใช้สแต็ก
Ignacio Vazquez-Abrams

@ IgnacioVazquez-Abrams เกี่ยวกับการเปลี่ยนแปลงเช่นเดียวกับวิธีแก้ปัญหาของฉัน แก้ไขคำตอบของฉัน
jippie

ตกลงนี่เป็นคำตอบที่น่าสนใจที่สุด ฉันได้ทดลองใช้avr-objdumpแล้วavr-sizeและฉันจะแก้ไขโพสต์ของฉันด้านบนในไม่ช้า ขอบคุณสำหรับสิ่งนี้.
Madivad

3

ฉันสงสัยว่าในขณะที่ฉันไปถึงจุดจบของ RAM ที่มีอยู่ ฉันไม่คิดว่าฉันใช้สแต็กมากเกินไป (แม้ว่าจะเป็นไปได้) วิธีที่ดีที่สุดในการพิจารณาจำนวนแรมที่ฉันใช้จริงคืออะไร

มันจะเป็นการดีที่สุดที่จะใช้การรวมกันของการประมาณค่าแบบแมนนวลและโดยการใช้ตัวsizeofดำเนินการ หากการประกาศทั้งหมดของคุณเป็นแบบคงที่สิ่งนี้ควรให้ภาพที่ถูกต้องแก่คุณ

หากคุณใช้การจัดสรรแบบไดนามิกคุณอาจพบปัญหาเมื่อคุณยกเลิกการจัดสรรคืนหน่วยความจำ นี่เป็นเพราะการกระจายตัวของหน่วยความจำบนฮีป

เมื่อผ่านไปและพยายามที่จะทำงานออกมาฉันมีปัญหาเมื่อฉันไปหา enums และ structs; หน่วยความจำมีราคาเท่าใด

Enum intที่จะเป็นพื้นที่มากในฐานะที่เป็น ดังนั้นถ้าคุณมีชุดของ 10 องค์ประกอบในที่ประกาศว่าจะenum นอกจากนี้ตัวแปรที่ใช้นับทุกเป็นเพียง10*sizeof(int)int

สำหรับโครงสร้างมันจะง่ายที่สุดในการใช้sizeofเพื่อค้นหา โครงสร้างครอบครองพื้นที่ (ขั้นต่ำ) เท่ากับผลรวมของสมาชิก avr-gccถ้าคอมไพเลอร์จะจัดตำแหน่งโครงสร้างแล้วมันอาจจะมากขึ้นอย่างไรก็ตามเรื่องนี้ไม่น่าเป็นไปในกรณีของ


ฉันกำหนดทุกสิ่งเท่าที่จะทำได้แบบคงที่ ฉันไม่เคยคิดที่จะใช้sizeofเพื่อจุดประสงค์นี้ ในขณะนี้ฉันมีเกือบ 400 ไบต์แล้ว (ทั่วโลก) ตอนนี้ฉันจะผ่านและคำนวณ enums (ด้วยตนเอง) และ structs (ซึ่งฉันมีไม่กี่ - และฉันจะใช้sizeof) และรายงานกลับ
Madivad

ไม่แน่ใจว่าคุณจำเป็นต้องsizeofรู้ขนาดของข้อมูลสแตติกของคุณจริงๆเพราะนี่พิมพ์โดย avrdude IIRC
jfpoilpret

@jfpoilpret ฉันคิดว่าขึ้นอยู่กับรุ่น ไม่ใช่ทุกเวอร์ชั่นและแพลตฟอร์มที่ให้บริการ Mine (Linux หลายรุ่น) ไม่แสดงหน่วยความจำที่ใช้เพียงอันเดียวในขณะที่ Mac ทำ
asheeshr

ฉันค้นหาผลลัพธ์ verbose แล้วฉันคิดว่ามันควรจะอยู่ตรงนั้นไม่ใช่
Madivad

@AsheeshR ฉันไม่ทราบว่าฉันทำงานได้ดีบน Windows
jfpoilpret

1

มีโปรแกรมที่เรียกว่าArduino Builderที่ให้การแสดงภาพอย่างเป็นระเบียบของปริมาณแฟลช, SRAM และ EEPROM ที่โปรแกรมของคุณใช้อยู่

Arduino Builder

สร้าง Arduino ทำให้ขึ้นเป็นส่วนหนึ่งของcodeblocks Arduino IDEแก้ปัญหา มันสามารถใช้เป็นทั้งโปรแกรมแบบสแตนด์อโลนหรือผ่านทาง IDE CodeBlocks Arduino

น่าเสียดายที่ Arduino Builder นั้นเก่าไปหน่อยแต่มันควรจะใช้ได้กับโปรแกรมส่วนใหญ่และ Arduinos ส่วนใหญ่เช่น Uno

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.