มีหลายปัจจัยที่นี่:
- ATmega328P MCU สามารถรับอัตราการรับส่งข้อมูลได้สูงเพียงใด
- อินเตอร์เฟส USB-Serial สามารถรับอัตราการรับส่งข้อมูลได้สูงเท่าใด
- ความถี่ oscillator บน ATmega328P คืออะไร?
- ความถี่ oscillator บนอินเตอร์เฟส USB แบบอนุกรมคืออะไร (ถ้ามี)
- อินเตอร์เฟซแบบอนุกรม USB ของ Baud-rate ไม่สอดคล้องกันเพียงใด
ปัจจัยทั้งหมดเหล่านี้เกี่ยวข้องกับการกำหนดอัตราการรับส่งข้อมูลสูงสุดที่สามารถทำได้ ATmega328P ใช้ตัวหารฮาร์ดแวร์จากอัตรานาฬิกาเพื่อสร้างนาฬิกาพื้นฐานสำหรับอินเตอร์เฟสแบบอนุกรม หากมีอัตราส่วนจำนวนเต็มไม่มีจากนาฬิกาหลักเพื่อบิตเวลาของการอัตราการส่งข้อมูลที่ต้องการ MCU ที่จะไม่สามารถที่จะตรงผลิตอัตราที่ต้องการ สิ่งนี้สามารถนำไปสู่ปัญหาที่อาจเกิดขึ้นเนื่องจากอุปกรณ์บางประเภทมีความไวต่อการรับข้อมูลที่ไม่ตรงกันมากเกินไป
อินเทอร์เฟซที่ใช้ FTDI นั้นค่อนข้างทนทานต่ออัตราการรับส่งข้อมูลที่ไม่ตรงกันมากถึงข้อผิดพลาดหลายเปอร์เซ็นต์ อย่างไรก็ตามฉันได้ทำงานกับโมดูล GPS แบบฝังพิเศษที่ไม่สามารถจัดการกับข้อผิดพลาดของอัตราการส่งข้อมูล 0.5% ได้
อินเตอร์เฟสแบบอนุกรมทั่วไปสามารถทนต่อข้อผิดพลาด baud-rate 5% อย่างไรก็ตามเนื่องจากปลายแต่ละด้านสามารถปิดได้ข้อมูลจำเพาะที่พบบ่อยคือ + -2.5% ด้วยวิธีนี้หากปลายด้านหนึ่งเร็ว 2.5% และปลายอีกด้านช้า 2.5% ข้อผิดพลาดโดยรวมของคุณยังคงเป็นเพียง 5%
อย่างไรก็ตาม. Uno ใช้ ATmega328P เป็น MCU หลักและ ATmega16U2 เป็นอินเตอร์เฟส USB แบบอนุกรม เราโชคดีเช่นกันที่ MCU ทั้งสองนี้ใช้ฮาร์แวร์ USART ที่คล้ายคลึงกันรวมถึงนาฬิกา 16 Mhz
เนื่องจาก MCU ทั้งสองมีฮาร์แวร์และอัตรานาฬิกาเหมือนกันทั้งคู่จะมีข้อผิดพลาดอัตราการรับส่งข้อมูลเดียวกันในทิศทางเดียวกันดังนั้นเราจึงสามารถละเว้นปัญหาข้อผิดพลาดการรับส่งข้อมูลได้
อย่างไรก็ตามคำตอบที่ "ถูกต้อง" สำหรับคำถามนี้จะเกี่ยวข้องกับการขุดแหล่งที่มาสำหรับ ATmega16U2 และหาอัตราการรับส่งข้อมูลที่เป็นไปได้จากที่นั่น แต่เนื่องจากฉันขี้เกียจฉันคิดง่ายการทดสอบเชิงประจักษ์จะใช้งานได้
ภาพรวมอย่างรวดเร็วที่แผ่นข้อมูล ATmega328P สร้างตารางต่อไปนี้:
ดังนั้นด้วยอัตรารับส่งข้อมูลสูงสุดที่ระบุไว้ที่ 2 Mbps ฉันจึงเขียนโปรแกรมทดสอบอย่างรวดเร็ว:
void setup(){};
void loop()
{
delay(1000);
Serial.begin(57600);
Serial.println("\r\rBaud-rate = 57600");
delay(1000);
Serial.begin(76800);
Serial.println("\r\rBaud-rate = 76800");
delay(1000);
Serial.begin(115200);
Serial.println("\r\rBaud-rate = 115200");
delay(1000);
Serial.begin(230400);
Serial.println("\r\rBaud-rate = 230400");
delay(1000);
Serial.begin(250000);
Serial.println("\r\rBaud-rate = 250000");
delay(1000);
Serial.begin(500000);
Serial.println("\r\rBaud-rate = 500000");
delay(1000);
Serial.begin(1000000);
Serial.println("\r\rBaud-rate = 1000000");
delay(1000);
Serial.begin(2000000);
Serial.println("\r\rBaud-rate = 2000000");
};
จากนั้นดูพอร์ตอนุกรมที่เกี่ยวข้องด้วยเทอร์มินัลอนุกรม:
ดังนั้นจึงปรากฏว่าฮาร์ดแวร์สามารถทำงานที่ 2,000,000 บอดไม่มีปัญหา
โปรดทราบว่าอัตราการรับส่งข้อมูลนี้จะให้วงจรนาฬิกา64บิตต่อไบต์ต่อไบต์ดังนั้นจึงเป็นเรื่องที่ท้าทายอย่างยิ่งที่จะทำให้อินเตอร์เฟซอนุกรมไม่ว่าง ในขณะที่แต่ละไบต์อาจถูกถ่ายโอนอย่างรวดเร็วมากมีโอกาสมากที่จะไม่ได้ใช้งานอินเตอร์เฟส
แก้ไข: การทดสอบจริง!
2 Mbps เป็นจริง:
แต่ละ bit-time คือ 500 ns ซึ่งตรงกับสิ่งที่คาดหวัง
ปัญหาด้านประสิทธิภาพ! ความยาวของแพ็กเก็ตโดยรวม:
500 Kbaud:
1 ล้านบาท:
2 Mbaud: หมายเหตุ : การ overhoot ที่
สังเกตเห็นได้นั้นเกิดจากการปฏิบัติกราวด์ของโพรบขอบเขตที่ไม่ดีและอาจไม่จริง ฉันใช้คลิปกราวด์ซึ่งเป็นส่วนหนึ่งของโพรบขอบเขตของฉันและการเหนี่ยวนำตัวเหนี่ยวนำน่าจะเป็นสาเหตุของการโอเวอร์เฮทส่วนใหญ่
อย่างที่คุณเห็นความยาวการส่งโดยรวมจะเท่ากันสำหรับ 0.5, 1 และ 2 Mbaud นี่เป็นเพราะรหัสที่วางไบต์ในบัฟเฟอร์อนุกรมได้รับการปรับให้เหมาะสม ดังนั้นคุณจะไม่ประสบความสำเร็จในสิ่งที่ดีกว่า500 Kbaud ที่มีประสิทธิภาพเว้นแต่ว่าคุณจะเขียนไลบรารีอนุกรมของคุณเอง ห้องสมุด Arduino นั้นได้รับการปรับปรุงอย่างไม่ดีนักดังนั้นมันอาจจะไม่ยากเกินไปที่จะรับ 2 Mbaud ที่เหมาะสมอย่างน้อยก็สำหรับการส่งสัญญาณต่อเนื่องหากคุณใช้เวลาสักระยะหนึ่ง