สารบัญ:

บัส I2C สำหรับ ATtiny และ ATmega: 8 ขั้นตอน
บัส I2C สำหรับ ATtiny และ ATmega: 8 ขั้นตอน

วีดีโอ: บัส I2C สำหรับ ATtiny และ ATmega: 8 ขั้นตอน

วีดีโอ: บัส I2C สำหรับ ATtiny และ ATmega: 8 ขั้นตอน
วีดีโอ: Arduino Dev : ความรู้พื้นฐาน Serial Comm. แบบต่างๆ (UART, USART, I2C, SPI และ RS232) 2024, พฤศจิกายน
Anonim
บัส I2C สำหรับ ATtiny และ ATmega
บัส I2C สำหรับ ATtiny และ ATmega

ฉันชอบไมโครคอนโทรลเลอร์ Atmel AVR! ตั้งแต่สร้างระบบการพัฒนาสลัมตามที่อธิบายไว้ในคำแนะนำนี้ ฉันก็สนุกกับการทดลองกับ AVR ATtiny2313 และ ATmega168 โดยเฉพาะอย่างไม่สิ้นสุด ฉันยังเขียน Instructable เกี่ยวกับการใช้สวิตช์เป็นอินพุต และขยายแนวคิด Ghetto Development System ไปยัง CPLD ในระหว่างโปรเจ็กต์ล่าสุด ฉันต้องการสวิตช์หลายตัวสำหรับการตั้งค่าการควบคุม AVR มีพิน I/O ไม่เพียงพอ ดังนั้นฉันจึงต้องคิดอะไรบางอย่าง ฉันสามารถลองใช้ระบบป้อนข้อมูลที่ซับซ้อนด้วยแป้นพิมพ์และจอแสดงผล แต่ ATtiny2313 คงจะไม่มีทรัพยากรเหลือแล้ว โชคดีที่ Atmel ได้แก้ปัญหานี้โดยการรวมอินเทอร์เฟซที่สามารถเชื่อมโยงกับชิปเพิ่มเติม (เช่นหน่วยความจำหรือพอร์ต I/O) ด้วยอินเทอร์เฟซแบบสองสายที่เรียบง่าย ถูกต้อง โดยการใช้พิน I/O เพียงสองพินบน AVR เราสามารถเข้าถึงพิน I/O เพิ่มเติมจำนวนมาก และทรัพยากรอื่นๆ ได้เช่นกัน อินเทอร์เฟซสองสายนี้เป็นที่รู้จักอย่างเป็นทางการในชื่อ Inter-Integrated Circuit bus หรือเพียงแค่บัส I2C และถูกคิดค้นโดย NXP เมื่อยังเป็น Philips Semiconductors หากคุณกำลังอ่านคำแนะนำนี้ คุณอาจเคยได้ยินเกี่ยวกับบัส I2C และอาจเคยใช้กับ PIC หรือไมโครคอนโทรลเลอร์อื่นๆ แม้ว่าแนวคิดจะเรียบง่ายมาก และสนับสนุนโดยทรัพยากรฮาร์ดแวร์บน AVR แต่ไดรเวอร์ซอฟต์แวร์ก็ยังจำเป็นต่อการใช้บัส I2C Atmel จัดเตรียม Application Notes (ดูทรัพยากรในภายหลังในคำแนะนำนี้) แต่สิ่งเหล่านี้ไม่สมบูรณ์และไม่แสดงตัวอย่างใด ๆ นอกเหนือจากการสื่อสารกับอุปกรณ์ AVR อื่น มันไม่ใช่จุดประสงค์ของคำแนะนำนี้เพื่อสอนทุกคนถึงวิธีสร้างไดรเวอร์ I2C สำหรับ AVR แต่ฉันจะจัดหาไดรเวอร์ Atmel เวอร์ชันเพิ่มเติมสำหรับอุปกรณ์ ATtiny2313 และ ATmega168 ฉันจะอธิบายข้อกำหนดและข้อจำกัดที่บังคับใช้เมื่อใช้สิ่งเหล่านี้ และฉันจะแสดงตัวอย่างการทำงานของอุปกรณ์ I2C ให้คุณดู หลังจากที่คุณทำงานผ่านคำแนะนำนี้ คุณจะสามารถใช้บัส I2C ได้สำเร็จในโครงการ AVR ของคุณ แน่นอน คุณสามารถเพิกเฉยต่อไดรเวอร์สำหรับขนาดเล็กหรือ MEGA ได้ หากคุณสนใจเพียงตัวใดตัวหนึ่งเท่านั้น สำหรับผู้ที่สนใจเรียนรู้เพิ่มเติมเกี่ยวกับบัส I2C ฉันจะให้ลิงก์ไปยังเนื้อหาที่เหมาะสม

ขั้นตอนที่ 1: อะไรคือ I2C ทั้งหมดนี้

อะไรคือสิ่งที่ I2C ทั้งหมดนี้อยู่แล้ว?
อะไรคือสิ่งที่ I2C ทั้งหมดนี้อยู่แล้ว?
อะไรคือสิ่งที่ I2C ทั้งหมดนี้อยู่แล้ว?
อะไรคือสิ่งที่ I2C ทั้งหมดนี้อยู่แล้ว?
อะไรคือสิ่งที่ I2C ทั้งหมดนี้อยู่แล้ว?
อะไรคือสิ่งที่ I2C ทั้งหมดนี้อยู่แล้ว?
อะไรคือสิ่งที่ I2C ทั้งหมดนี้อยู่แล้ว?
อะไรคือสิ่งที่ I2C ทั้งหมดนี้อยู่แล้ว?

บัส I2C เป็นการเชื่อมต่อแบบสองสายที่เรียบง่าย ซึ่งสามารถเชื่อมโยงอุปกรณ์หลายเครื่องเข้าด้วยกัน และช่วยให้สามารถแลกเปลี่ยนข้อมูลได้ ในรูปแบบที่ง่ายที่สุด มีอุปกรณ์หลักหนึ่งเครื่องที่สื่อสารกับอุปกรณ์ทาสหลายเครื่อง อุปกรณ์ทั้งหมดเชื่อมต่อแบบขนานกับสายไฟสองเส้นของบัส I2C สายไฟสองเส้นนี้เรียกว่า SCL และ SDA SCL คือสายนาฬิกาและควบคุมโดยอุปกรณ์หลัก SDA เป็นสายข้อมูลแบบสองทิศทาง ในการถ่ายโอนข้อมูล ต้นแบบจะส่งที่อยู่รองพร้อมกับแฟล็กอ่าน/เขียนหนึ่งบิต หากต้องการเขียน ต้นแบบจะส่งข้อมูลไปยังสเลฟที่แอดเดรสต่อไป หากมีการขออ่าน สเลฟจะตอบกลับด้วยข้อมูล ในการประสานงานธุรกรรม บรรทัด SCL และ SDA จะถูกควบคุมโดยมาสเตอร์และสเลฟเพื่อส่งสัญญาณเงื่อนไขต่างๆ ซึ่งรวมถึง START, STOP, ACK (รับทราบ) และ NAK (ไม่รับทราบ) รายละเอียดของเงื่อนไขเหล่านี้ได้รับการจัดการโดยไดรเวอร์ ผู้เชี่ยวชาญที่แท้จริงในหมู่คุณสามารถเรียนรู้รายละเอียดทั้งหมดในลิงก์ที่ให้ไว้ในตอนท้ายของคำแนะนำนี้ ข้อกำหนดทางไฟฟ้านั้นค่อนข้างง่าย ต้นแบบและทาสต้องใช้ระดับเดียวกันสำหรับ Vcc ต้องเชื่อมต่อกราวด์และต้องดึงสาย SCL และ SDA ขึ้นเป็น Vcc ค่าของตัวต้านทานแบบดึงขึ้นจะถูกกำหนดอย่างแม่นยำโดยการคำนวณตามความจุรวมบนบัส แต่ในทางปฏิบัติแล้วสามารถมีค่าใดก็ได้ระหว่าง 1.8K ถึง 10K ฉันเริ่มต้นด้วย 5.1K และใช้ค่าที่ต่ำกว่าจนกว่าจะได้ผล โดยปกติจะไม่เป็นปัญหาเว้นแต่ว่าคุณมีอุปกรณ์จำนวนมากหรือมีสายไฟยาวระหว่างอุปกรณ์ต่างๆ อัตราข้อมูลเล็กน้อยบนบัส I2C คือ 100Kbits/วินาที อัตรา 400Kbits/วินาที 1Mbits/วินาที และอื่นๆ เป็นไปได้เช่นกัน แต่ไดรเวอร์ไม่รองรับในคำแนะนำนี้ อุปกรณ์ I2C ทั้งหมดจะทำงานที่ 100Kbits/วินาที ATtiny2313 และ ATmega168 ใช้บัส I2C ต่างกัน ATtiny2313 ใช้ฮาร์ดแวร์ Universal Serial Interface (USI) ซึ่งสามารถใช้กับบัส SPI ได้เช่นกัน ATmega168 มีฮาร์ดแวร์เฉพาะสำหรับบัส I2C ที่เรียกว่า Two Wire Interface (TWI) เมื่อเขียนไดรเวอร์แล้ว ความแตกต่างเหล่านี้ส่วนใหญ่จะโปร่งใสต่อผู้ใช้ ความแตกต่างที่สำคัญประการหนึ่งอยู่ในซอฟต์แวร์: ไดรเวอร์ ATmega168 I2C ถูกขัดจังหวะในขณะที่ ATtiny2313 ไม่ใช่ ซึ่งหมายความว่าโปรแกรม ATmega168 ไม่จำเป็นต้องรอให้มีการถ่ายโอนข้อมูล I2C แต่ต้องรอก่อนที่จะเริ่มการถ่ายโอนอื่น หรือจนกว่าข้อมูลจะมาจากการดำเนินการอ่าน ตัวอย่างและการสนทนาที่ควรปฏิบัติตามควรทำให้ชัดเจน ที่อยู่ I2C มีความยาว 7 บิต ดังนั้นอุปกรณ์สูงสุด 127 เครื่องสามารถอยู่บนบัสได้หากแต่ละรายการมีที่อยู่ที่ไม่ซ้ำกัน ดังแสดงในรูป ที่อยู่ 7 บิตนี้ถูกเลื่อนไปทางซ้ายหนึ่งบิต และบิตที่มีนัยสำคัญน้อยที่สุดใช้เพื่อตั้งค่าสถานะการอ่านหรือเขียนอุปกรณ์ตามที่อยู่ ดังนั้นที่อยู่ทาสที่สมบูรณ์จึงเป็นไบต์ 8 บิต ที่อยู่จริงถูกกำหนดภายในบางส่วนกับอุปกรณ์และไม่สามารถเปลี่ยนแปลงได้ (4 บิตที่สำคัญที่สุด) และกำหนดบางส่วนโดยบิตที่อาจเชื่อมต่อกับพินของอุปกรณ์ (บิตที่มีนัยสำคัญน้อยที่สุด 3 บิต) ที่สามารถผูกไว้สูงหรือต่ำเพื่อตั้งค่า ที่อยู่เฉพาะ ฟังดูสับสน แต่ตัวอย่างจะทำให้สิ่งนี้ชัดเจน แผ่นข้อมูล PCA8574A แสดงให้เห็นว่าสี่บิตที่สำคัญที่สุดของที่อยู่ I2C จะเป็น 0111 เสมอ สามบิตถัดไปจะถูกกำหนดโดยการตั้งค่าบนพิน AD0, AD1 และ AD2 หมุดเหล่านี้สามารถผูกติดกับกราวด์หรือกับแหล่งจ่ายแรงดันบวก (5 โวลต์) เพื่อแสดงค่า 0 หรือ 1 ตามลำดับ ดังนั้นช่วงของที่อยู่ที่เป็นไปได้คือ 38 ถึง 3F เลขฐานสิบหก ดังแสดงในรูปอื่นจากแผ่นข้อมูล PCA8574 ดังนั้นด้วยการเปลี่ยนการตั้งค่าบิตแอดเดรส PCA8574As สูงสุด 8 PCA8574A สามารถอยู่บนบัส I2C ได้พร้อมกัน แต่ละคนจะตอบสนองต่อที่อยู่ทาสเฉพาะของตนเท่านั้น หากต้องการพอร์ต I/O มากกว่านี้ สามารถใช้ PCA8574 ได้ ข้อแตกต่างเพียงอย่างเดียวระหว่าง PCA8574 และ PCA8574A คือช่วงที่อยู่รองของ I2C ของ PCA8574 เป็นเลขฐานสิบหก 20 ถึง 27 การกำหนดที่อยู่ของอุปกรณ์ที่กำหนดอาจสร้างความสับสนได้เนื่องจากแผ่นข้อมูลบางแผ่นพิจารณาว่าบิตการอ่าน/เขียนเป็นส่วนหนึ่งของ ที่อยู่. อ่านแผ่นข้อมูลอย่างละเอียดและจำไว้ว่าที่อยู่รองจะมีความยาว 7 บิต ควรแยกบิตการอ่าน/เขียนแยกกัน ตัวอย่างจะช่วยได้อีกครั้ง แผ่นข้อมูลสำหรับ 24C16 EEPROM ที่เราจะทำการทดลองโดยระบุว่าที่อยู่สเลฟ 4 บิตแรก (ที่สำคัญที่สุด) คือ 1,010 สามบิตถัดไปสามารถกำหนดได้โดย A0, A1 และ A2; แต่โปรดทราบว่าแผ่นข้อมูลยังครอบคลุม 24C01 ถึง 24C08 ซึ่งเป็น EEPROM ที่มีขนาดเล็กกว่า ตัวเลขจากแผ่นข้อมูลแสดงว่าการตั้งค่าของบิตที่อยู่เหล่านี้จะถูกละเว้นเมื่อขนาดเพิ่มขึ้นและจะถูกละเว้นอย่างสมบูรณ์สำหรับ 24C16 นั่นคือสามบิตสุดท้ายไม่สำคัญและ 24C16 ใช้ที่อยู่ทาส I2C ทั้งหมด 50 ถึง 57 เลขฐานสิบหก ช่วงของที่อยู่รองจะระบุส่วนต่างๆ ภายใน 24C16 256 ไบต์แรกอยู่ที่ 50h, 256 ถัดไปที่ 51h และต่อไปเรื่อยๆ จนถึง 256 สุดท้ายที่ 57h - รวมเป็น 2K ไบต์ เนื่องจากที่อยู่ของ PCF8570 RAM ที่เราทดลองด้วยนั้นอยู่ในช่วงนี้ จึงไม่สามารถใช้ 24C16 และ PCF8570 ร่วมกันได้

ขั้นตอนที่ 2: สั่งซื้ออุปกรณ์ I2C บางตัว

ตอนนี้คุณรู้เพียงเล็กน้อยเกี่ยวกับ I2C Bus และต้องการใช้งานแล้ว ทำไมไม่ลองสั่งอุปกรณ์ I2C มาทดลองดูตอนนี้ เพื่อที่จะได้ไปถึงคุณในขณะที่คุณเตรียมซอฟต์แวร์ให้พร้อม?อุปกรณ์ที่เหมาะสมรวมถึง I/ O Interface Expander (โปรดของฉัน), Static Ram และ EEPROM มีอีกมาก แต่นี่เป็นการเริ่มต้นที่ดี โปรเซสเซอร์ AVR ที่เราจะใช้คือ ATtiny2313 และ Atmega168 (ใช้ใน Arduino) หากคุณยังใหม่กับสิ่งเหล่านี้ ลองดูคำแนะนำที่ยอดเยี่ยมนี้เพื่อเรียนรู้เกี่ยวกับพวกเขาและสร้างระบบการพัฒนาสลัมของคุณ แผนผังของ ATmega168 ใน Instructable ปัจจุบันแสดงวิธีการใช้ Ghetto Development System สำหรับโปรเซสเซอร์นี้ สายเคเบิลพอร์ตขนานเหมือนกับสายเคเบิลสำหรับ ATtiny2313 (ฉันยังไม่ได้ลองใช้ Ghetto Development System เวอร์ชัน USB เลยไม่แน่ใจว่าเข้าถึงบัส I2C ได้อย่างไร เช่นเดียวกับ Arduino) นี่คือหมายเลขชิ้นส่วน Digikey Port Expander:IC I2C I/O ตัวขยาย 568-4236-5-NDRAM:IC SRAM 256X8 W/I2C 568-1071-5-NDEEPROM:IC EEPROM SERIAL 16K CAT24C16LI-G-ND

ขั้นตอนที่ 3: ไดรเวอร์ I2C

นี่คือคำอธิบายของฟังก์ชันไดรเวอร์สำหรับบัส I2C สิ่งเหล่านี้ได้รับการพัฒนาโดยใช้ Atmel Apps Notes สำหรับผู้เริ่มต้น ฉันไม่สามารถทำสิ่งนี้ได้หากไม่มีพวกเขาเป็นฐานในการสร้าง การพัฒนาเสร็จสิ้นโดยใช้ WinAVR และคอมไพเลอร์ gcc C ข้อจำกัดอัตรานาฬิกาอธิบายไว้ด้านล่างสำหรับโปรเซสเซอร์แต่ละตัว เนื่องจากฉันไม่สามารถทดสอบการผสมผสานของรสชาติ/อัตรานาฬิกาของโปรเซสเซอร์ได้ทั้งหมด ฉันจะใช้สิ่งที่สามารถทดสอบได้จริงและพยายามระบุข้อจำกัดและข้อจำกัดต่อไปนี้คือฟังก์ชันของไดรเวอร์และวิธีใช้งาน โปรดดูตัวอย่างเพื่อดูรายละเอียดเพิ่มเติมและดูฟังก์ชันที่ใช้งานในโปรแกรมทั้งหมด สำหรับ ATtiny2313:Clock Requirement:ไดรเวอร์ได้รับการออกแบบสำหรับอัตรานาฬิกา 1MHz (อัตราเริ่มต้น) สำหรับ ATtiny2313 หากคุณต้องการวิ่งในอัตราอื่น คุณจะต้องปรับค่าคงที่ในไดรเวอร์ ส่งอีเมลถึงฉันหากคุณต้องการความช่วยเหลือในการทำเช่นนี้ คุณยังสามารถรับคำแนะนำบางส่วนจากบันทึกย่อของแอป Atmel ในลิงก์ใน ขั้นตอนทรัพยากรUSI_TWI_Master_Initialise()ฟังก์ชันนี้จะเริ่มต้นฮาร์ดแวร์ USI สำหรับการทำงานของโหมด I2C โทรเพียงครั้งเดียวเมื่อเริ่มต้นโปรแกรมของคุณ คืนค่าเป็นโมฆะและไม่มีข้อโต้แย้งUSI_TWI_Get_State_Info()ฟังก์ชันนี้ส่งคืนข้อมูลข้อผิดพลาด I2C และถูกใช้หากมีข้อผิดพลาดเกิดขึ้นระหว่างธุรกรรม I2C เนื่องจากฟังก์ชันนี้ส่งคืนรหัสข้อผิดพลาดเท่านั้น ฉันจึงใช้ฟังก์ชัน TWI_Act_On_Failure_In_Last_Transmission(TWIerrorMsg) เพื่อกะพริบ LED แสดงข้อผิดพลาด รหัสข้อผิดพลาดถูกกำหนดใน USI_TWI_Master.h ต่อไปนี้เป็นวิธีเรียก:TWI_Act_On_Failure_In_Last_Transmission(USI_TWI_Get_State_Info())USI_TWI_Start_Read_Write()ฟังก์ชันนี้ใช้เพื่ออ่านและเขียนไบต์เดียวไปยังอุปกรณ์ I2C นอกจากนี้ยังใช้เพื่อเขียนหลายไบต์ มี 6 ขั้นตอนในการใช้ฟังก์ชันนี้ 1)ประกาศบัฟเฟอร์ข้อความในโปรแกรมของคุณเพื่อเก็บที่อยู่สเลฟและไบต์ข้อมูลที่จะส่งหรือรับ unsigned char messageBuf (MESSAGEBUF_SIZE);2) ใส่ Slave Address เป็นไบต์แรกในบัฟเฟอร์ เลื่อนไปทางซ้ายหนึ่งบิตและ OR ในบิตอ่าน/เขียน โปรดทราบว่าบิตอ่าน/เขียนจะเป็น 1 สำหรับการอ่านและ 0 สำหรับการเขียน ตัวอย่างนี้มีไว้สำหรับอ่าน messageBuf(0) = (TWI_targetSlaveAddress<<TWI_ADR_BITS) | (TRUE<<TWI_READ_BIT); 3)เมื่อทำการเขียน ให้ใส่ไบต์ที่จะเขียนลงในตำแหน่งถัดไปในบัฟเฟอร์ 4)เรียกใช้ฟังก์ชัน USI_TWI_Start_Read_Write ด้วยบัฟเฟอร์ข้อความและขนาดข้อความเป็นอาร์กิวเมนต์.temp = USI_TWI_Start_Read_Write(messageBuf, 2);5)The ค่าที่ส่งคืน (ชั่วคราวในกรณีนี้) สามารถทดสอบเพื่อดูว่ามีข้อผิดพลาดเกิดขึ้นหรือไม่ ถ้าเป็นเช่นนั้นก็จัดการตามที่กล่าวไว้ข้างต้น ดูตัวอย่างในโปรแกรม 6)หากมีการร้องขอการอ่าน การอ่านไบต์จะอยู่ในตำแหน่งที่สองในบัฟเฟอร์ หากต้องเขียนหลายไบต์ (เช่น อุปกรณ์หน่วยความจำ) คุณสามารถใช้รูทีนเดียวกันนี้ได้ การตั้งค่าบัฟเฟอร์และการเรียกรูทีนนั้นแตกต่างกันเล็กน้อย ไบต์ที่สองในบัฟเฟอร์จะเป็นที่อยู่หน่วยความจำเริ่มต้นที่จะเขียน ข้อมูลที่จะเขียนจะเป็นไบต์ต่อๆ ไป ขนาดข้อความจะเป็นขนาดรวมทั้งข้อมูลที่ถูกต้องทั้งหมด ดังนั้นหากต้องเขียน 6 ไบต์ ขนาดข้อความจะเป็น 8 (ที่อยู่สเลฟ + ที่อยู่หน่วยความจำ + ข้อมูล 6 ไบต์)USI_TWI_Start_Random_Read()ฟังก์ชันนี้ใช้เพื่ออ่านหลายไบต์จากอุปกรณ์ I2C โดยทั่วไปแล้วจะมีความหมายสำหรับ ความทรงจำบางอย่าง การใช้รูทีนนี้คล้ายกับรูทีนก่อนหน้านี้มาก โดยมีข้อยกเว้นสองประการ การตั้งค่าบิตอ่าน/เขียนไม่สำคัญ การเรียกรูทีนนี้จะทำให้มีการดำเนินการอ่านเสมอ MessageSize ควรเป็น 2 บวกกับจำนวนไบต์ที่จะอ่าน หากไม่มีข้อผิดพลาดเกิดขึ้น ข้อมูลจะอยู่ในบัฟเฟอร์โดยเริ่มต้นที่ตำแหน่งที่สอง สำหรับ ATmega168:Clock Requirement:The ไดรเวอร์ได้รับการออกแบบสำหรับอัตรานาฬิกา 4MHz สำหรับ ATmega168 โค้ดตัวอย่างแสดงวิธีตั้งค่าอัตรานาฬิกานี้ หากคุณต้องการวิ่งในอัตราอื่น คุณจะต้องปรับค่าคงที่ในไดรเวอร์ ส่งอีเมลถึงฉันหากคุณต้องการทำสิ่งนี้TWI_Master_Initialise()ฟังก์ชันนี้จะเริ่มต้นฮาร์ดแวร์ TWI สำหรับการทำงานของโหมด I2C โทรเพียงครั้งเดียวเมื่อเริ่มต้นโปรแกรมของคุณ มันกลับเป็นโมฆะและไม่มีข้อโต้แย้ง อย่าลืมเปิดใช้งานการขัดจังหวะโดยเรียก swi() หลังจากเริ่มต้น TWI_Get_State_Info() ฟังก์ชันนี้ส่งคืนข้อมูลข้อผิดพลาด I2C และใช้หากมีข้อผิดพลาดเกิดขึ้นระหว่างธุรกรรม I2C เนื่องจากฟังก์ชันนี้ส่งคืนรหัสข้อผิดพลาดเท่านั้น ฉันจึงใช้ฟังก์ชัน TWI_Act_On_Failure_In_Last_Transmission(TWIerrorMsg) เพื่อกะพริบ LED แสดงข้อผิดพลาด รหัสข้อผิดพลาดถูกกำหนดใน TWI_Master.h แต่ได้รับการแก้ไขสำหรับการส่งสัญญาณบน LED ข้อผิดพลาด ดูรายละเอียดโค้ดตัวอย่าง ต่อไปนี้เป็นวิธีเรียก:TWI_Act_On_Failure_In_Last_Transmission(TWI_Get_State_Info()) โปรดทราบว่าการตรวจสอบข้อผิดพลาดทำได้โดยตรวจสอบให้แน่ใจว่าธุรกรรม I2C เสร็จสมบูรณ์ (ฟังก์ชันที่อธิบายไว้ด้านล่าง) จากนั้นทำการทดสอบเล็กน้อยในคำสถานะสากล TWI_Start_Read_Write()TWI_Start_Random_Read() สองฟังก์ชันทำงานเหมือนกับฟังก์ชันที่เกี่ยวข้องที่อธิบายไว้ข้างต้น แต่มีข้อยกเว้นบางประการ ฟังก์ชันเหล่านี้ไม่ส่งคืนค่าความผิดพลาดใดๆ การอ่านข้อมูลจะไม่ถูกถ่ายโอนไปยังบัฟเฟอร์ การทำเช่นนี้จะเสร็จสิ้นโดยใช้ฟังก์ชันที่อธิบายไว้ถัดไป เมื่อเรียกใช้ TWI_Start_Random_Read ข้อความขนาดควรเป็นจำนวนไบต์ข้อมูลที่ขอ บวกหนึ่ง ไม่ใช่สอง ไดรเวอร์ I2C สำหรับ ATmega168 นั้นทำงานแบบอินเตอร์รัปต์ นั่นคือ ธุรกรรม I2C เริ่มต้นและดำเนินการอย่างอิสระในขณะที่รูทีนหลักยังคงทำงานต่อไป เมื่อรูทีนหลักต้องการข้อมูลจากธุรกรรม I2C ที่เริ่มต้น จะต้องตรวจสอบเพื่อดูว่ามีข้อมูลหรือไม่ สถานการณ์จะเหมือนกันสำหรับการตรวจสอบข้อผิดพลาด รูทีนหลักต้องแน่ใจว่าธุรกรรม I2C เสร็จสมบูรณ์ก่อนที่จะตรวจสอบข้อผิดพลาด ฟังก์ชันสองฟังก์ชันถัดไปใช้เพื่อวัตถุประสงค์เหล่านี้ TWI_Transceiver_Busy()เรียกใช้ฟังก์ชันนี้เพื่อดูว่าธุรกรรม I2C เสร็จสมบูรณ์ก่อนตรวจสอบข้อผิดพลาดหรือไม่ ตัวอย่างโปรแกรมแสดงวิธีใช้ TWI_Read_Data_From_Buffer()เรียกใช้ฟังก์ชันนี้เพื่อถ่ายโอนข้อมูลจากบัฟเฟอร์การรับของไดรเวอร์ I2C ไปยังบัฟเฟอร์ข้อความ ฟังก์ชันนี้จะทำให้แน่ใจว่าธุรกรรม I2C เสร็จสมบูรณ์ก่อนที่จะถ่ายโอนข้อมูล ในขณะที่ฟังก์ชันนี้ส่งคืนค่า ฉันพบว่าการตรวจสอบบิตของข้อผิดพลาดโดยตรงนั้นเชื่อถือได้มากขึ้น นี่คือวิธีการเรียก ขนาดข้อความควรมากกว่าจำนวนบิตข้อมูลที่ต้องการหนึ่งรายการ ข้อมูลจะอยู่ใน messageBuf เริ่มต้นที่ตำแหน่งที่สอง location.temp = TWI_Read_Data_From_Buffer(messageBuf, messageSize);

ขั้นตอนที่ 4: มาสร้างกันเถอะ

มาสร้างกันเถอะ!
มาสร้างกันเถอะ!
มาสร้างกันเถอะ!
มาสร้างกันเถอะ!
มาสร้างกันเถอะ!
มาสร้างกันเถอะ!
มาสร้างกันเถอะ!
มาสร้างกันเถอะ!

เริ่มต้นด้วยการดาวน์โหลดไฟล์ I2C Schematics.zip คุณอาจต้องการสร้างโฟลเดอร์ I2C ในพื้นที่ทำงานของคุณเพื่อเก็บแผนผังและไฟล์โปรแกรมตัวอย่าง เปิดเครื่องรูดแผนผังลงในไดเร็กทอรีนี้ คุณจะพบโฟลเดอร์ชื่อ I2C Schematics เปิดไฟล์ชื่อ Tiny I2C.pdf แผนผังนี้แสดง ATtiny2313 Ghetto Development System และ PCA8574A I/O Port Expander (มีกล่องเส้นประขนาดใหญ่อยู่รอบๆ) วงจร Port Expander สร้างขึ้นบนเขียงหั่นขนม ดูภาพเพื่อดูว่าวงจรเหล่านี้มีลักษณะอย่างไร มันค่อนข้างเรียบง่ายจริงๆ ส่วน ATtiny2313 ของแผนผังเป็นเพียงระบบการพัฒนาสลัมที่มีไฟกะพริบสามดวง (LED1, 2 และ 3 บวก R4, 5 และ 6) และปุ่มกด (S1) ที่ติดอยู่ บวกหนึ่งอัน รายละเอียดเพิ่มเติม รายละเอียดนั้นคือการเพิ่มจัมเปอร์ (JP4, 5 และ 6) ซึ่งสามารถลบออกเพื่ออนุญาตให้เชื่อมต่อสาย SCL และ SDA ของบัส I2C ต้องติดตั้งจัมเปอร์สำหรับการเขียนโปรแกรม จากนั้นจึงถอดออกเพื่อให้สามารถเชื่อมต่อ SCL และ SDA ได้ ภาพถ่ายแสดงจัมเปอร์เข้าที่และถอดออก ตำแหน่งของจัมเปอร์เหล่านี้ขึ้นอยู่กับคุณ คุณเพียงแค่ต้องใส่มันลงในระบบการพัฒนาสลัมของคุณ หากคุณต้องการใช้บัส I2C ต้องถอดบัส I2C และจัมเปอร์ใส่สำหรับการเขียนโปรแกรม โปรดทราบว่าคุณจำเป็นต้องเกี่ยวข้องกับ JP4 และ JP6 สำหรับบัส I2C เท่านั้น ใส่ JP5 ถ้าคุณคิดว่าคุณเคยต้องการใช้บัส SPI เมนบอร์ด PCA8574A I/O Port Expander นั้นง่ายมาก จัดเตรียมการเชื่อมต่อ Vcc (+5 โวลต์) และ Gnd (กราวด์) และเชื่อมต่อ AD0, 1 และ 2 กับกราวด์ (ทำให้ที่อยู่ทาส I2C 38 hex) จากนั้นเชื่อมต่อไฟกะพริบ 4 ดวงและสวิตช์ DIP 4 ตัว (หากคุณไม่มีสวิตช์ DIP คุณสามารถใช้สายไฟ ผูกกับกราวด์หรือปล่อยให้ลอยเพื่อเปิดหรือปิดสัญญาณตามลำดับ) สุดท้าย เชื่อมต่อตัวต้านทานแบบดึงขึ้น (R11 และ 12) จาก SDA และ SCL กับ Vcc สิ่งเหล่านี้แสดงเป็น 3.3K แต่ค่าใด ๆ จาก 1.8K ถึง 5.1K ควรใช้งานได้ (อาจสูงถึง 10K แต่ฉันยังไม่ได้ลอง) เมื่อคุณตั้งโปรแกรม ATtiny2313 แล้ว คุณสามารถถอดจัมเปอร์ออกและเชื่อมต่อ SDA และ SCL เพื่อการทดสอบ ตอนนี้สำหรับ ATmega168 รอยย่นเดียวที่นี่คือคุณอาจไม่ได้สร้าง Ghetto Development System สำหรับโปรเซสเซอร์นี้ หากเป็นกรณีนี้ แผนผังที่ฉันให้ไว้ (MEGA I2C.pdf) จะแสดงให้คุณเห็นว่า นี่เป็นเพียงการเปลี่ยนแปลงของรุ่น ATtiny2313 หากคุณวางแผนล่วงหน้า คุณสามารถมั่นใจได้ว่าสายเคเบิลการเขียนโปรแกรมของคุณจะพอดีกับทั้งสองระบบ ความแตกต่างที่สำคัญคือการเพิ่ม C2 และ C3 ดูภาพสำหรับการจัดวางสิ่งเหล่านี้ควรอยู่ใกล้กับชิปมาก หนึ่งในนั้นอยู่ภายใต้ชิป สิ่งเหล่านี้ช่วยป้องกันสัญญาณรบกวนจากตัวแปลงอนาล็อกเป็นดิจิตอลโดยเฉพาะ คุณไม่จำเป็นต้องใส่จัมเปอร์ เว้นแต่ว่าคุณวางแผนที่จะใช้บัส SPI เนื่องจากไม่จำเป็นสำหรับบัส I2C บนชิปนี้ โปรดทราบว่าเขียงหั่นขนม PCA8754A จะไม่เปลี่ยนแปลง คุณเพียงแค่เชื่อมต่อ SDA และ SCL แล้วออกไป! ง่ายเหรอ?

ขั้นตอนที่ 5: มาโค้ดและทดสอบกัน

มาโค้ดและทดสอบกันเถอะ!
มาโค้ดและทดสอบกันเถอะ!
มาโค้ดและทดสอบกันเถอะ!
มาโค้ดและทดสอบกันเถอะ!
มาโค้ดและทดสอบกันเถอะ!
มาโค้ดและทดสอบกันเถอะ!

ได้เวลาสร้างไดรเวอร์และโปรแกรมตัวอย่างแล้ว เราจะเริ่มด้วย ATtiny2313 และเขียงหั่นขนม PCA8574A ที่เราเพิ่งสร้างขึ้น ดาวน์โหลดไฟล์ I2C.zip ลงในไดเร็กทอรีงาน I2C ของคุณและเปิดเครื่องรูด คุณจะมีโฟลเดอร์ใหม่ชื่อ I2C ในนั้นคุณจะพบ USI I2C (สำหรับ ATtiny2313) และ TWI I2C (สำหรับ ATmega168) ใน USI I2C คุณจะพบโฟลเดอร์ I_O Port โฟลเดอร์นั้นประกอบด้วยโค้ดสำหรับโปรแกรมตัวอย่างแรกของเรา และไดรเวอร์ USI I2C โดยใช้ WinAVR คอมไพล์และโหลดโค้ดลงใน ATtiny2313 หายใจเข้าลึกๆ แล้วเปิดเครื่อง นี่คือสิ่งที่จะเกิดขึ้น: เมื่อเปิดเครื่อง ไฟ LED 1 ที่พอร์ต PD6 ของ ATtiny2313 จะกะพริบสองครั้ง และจะไม่มีอะไรเกิดขึ้นอีกจนกว่าคุณจะกดปุ่ม (S1) ทุกครั้งที่กดปุ่ม สวิตช์จะถูกอ่านและการตั้งค่าจะแสดงบน LED ที่เชื่อมต่อกับ PCA8574A เปลี่ยนค่าของสวิตช์ กดปุ่ม และไฟ LED ควรเปลี่ยน ทำสิ่งนี้ต่อไปจนกว่าคุณจะรู้สึกตื่นเต้นที่ได้เห็นมันทำงาน หาก (พระเจ้าห้าม!) สิ่งต่าง ๆ ไม่ทำงานตามที่คาดไว้ ให้ตรวจสอบสายไฟของคุณอย่างละเอียด ข้อผิดพลาด I2C จะส่งสัญญาณโดยการกะพริบบน LED3 (PD4) และอาจหมายความว่าคุณต้องตรวจสอบว่า SDA และ SCL เชื่อมต่อกับพินที่ถูกต้องและดึงขึ้นอย่างถูกต้องหากยังคงใช้งานไม่ได้ โปรดอ่านส่วนที่เหลือของส่วนนี้เพื่อเรียนรู้เกี่ยวกับการดีบัก ย้อนกลับไปดูโค้ดกัน เปิดไฟล์ USI_I2C_Port.c นี่คือรหัสสำหรับโปรแกรมตัวอย่าง (USI_TWI_Master.c และ USI_TWI_Master.h มีไดรเวอร์ - คุณสามารถเพิกเฉยได้เว้นแต่คุณจะอยากรู้) ใช้ตัวอย่างเพื่อเป็นแนวทางในการใช้งาน I2C ของคุณเอง โดยส่วนใหญ่ โปรแกรมจะแสดงวิธีเริ่มต้นและใช้งานไดรเวอร์ I2C รวมถึงการตั้งค่า เพิ่มแอดเดรสสเลฟและบัฟเฟอร์ข้อความที่เหลือ แล้วดึงข้อมูลออกมา คุณจะเห็นว่าฉันดีบักปุ่มและตั้งค่า while loop อย่างไร มีรายละเอียดเล็ก ๆ น้อย ๆ ของโปรแกรมที่ควรค่าแก่การกล่าวถึง โปรดทราบว่าข้อมูลจากสวิตช์จะถูกกลับด้านก่อนที่จะเขียนไปยัง LED บน Port Expander นอกจากนี้ โปรดทราบว่าพอร์ตอินพุตบน Port Expander จะต้องเขียนเป็น High เพื่อให้ทำงานได้อย่างถูกต้อง รายละเอียดดังกล่าวได้อธิบายไว้ในแผ่นข้อมูล PCA8574A อ่านแผ่นข้อมูลอย่างระมัดระวังเสมอ! สิ่งที่น่าสนใจกว่าคือการใช้การดีบักแบบมีเงื่อนไข ใกล้กับจุดเริ่มต้นของไฟล์โปรแกรมคือคำสั่ง //#define DEBUG และโปรเจ็กต์ทั่วทั้งโค้ดคือคำสั่ง #ifdef DEBUG ตราบใดที่ไม่ได้กำหนด DEBUG (เครื่องหมายทับทั้งสองทำให้บรรทัดเป็นความคิดเห็นและป้องกันไม่ให้มีการกำหนด) โค้ดภายในคำสั่ง #ifdef ถึง #endif จะไม่ถูกคอมไพล์ แต่ถ้าสิ่งต่าง ๆ ไม่ทำงานตามที่คุณคาดหวัง ให้คอมไพล์ใหม่และโหลดโค้ดใหม่โดยที่ไม่ใส่ความคิดเห็น #define DEBUG คุณจะมีไฟ LED กะพริบถี่ขึ้นมาก ซึ่งคุณสามารถถอดรหัสเพื่อติดตามการทำงานของโปรแกรมและช่วยคุณค้นหาจุดที่เกิดข้อผิดพลาดได้อย่างแม่นยำ อันที่จริง ฉันแนะนำให้คุณลองทำสิ่งนี้เพื่อดูว่าเกิดอะไรขึ้น สิ่งที่คุณจะเห็นคือ LED 2 (บน PD5) จะกะพริบตามความคืบหน้าในการดำเนินการผ่านโปรแกรม ค่าที่อ่านจากสวิตช์จะกะพริบบน LED 1 (PD6) ก่อนที่จะแสดงบนไฟ LED ของ Port Expander คุณควรจะสามารถติดตามโปรแกรมในขณะที่ทำงานโดยใช้ไฟ LED เหล่านี้ เราจะทำงานกับ ATmega168 ต่อไป ข้ามส่วนนี้หากคุณสนใจเฉพาะ ATtiny2313 ยังอยู่กับฉัน? ดี. ย้ายไปยังโฟลเดอร์ TWI_I2C เปลี่ยนไดเร็กทอรีการทำงานของคุณเป็น IO_Port และคอมไพล์และโหลด TWI_I2C_Port.c ลงใน ATmega168 ตัดการเชื่อมต่อสาย SDA และ SCL จาก ATtiny2313 และเชื่อมต่อกับ ATmega168 เชื่อมต่อพลังงานและกราวด์ และเปิดเครื่อง การดำเนินการควรจะเหมือนกัน! เล่นจนหายตื่นเต้นแล้วมาดูโค้ดกัน เปิด TWI_I2C_Port.c. รหัสเกือบจะเหมือนกันยกเว้นการจัดการข้อผิดพลาดและรองรับไดรเวอร์ที่ขับเคลื่อนด้วยอินเตอร์รัปต์ นี่คือข้อแตกต่าง:โปรดทราบว่าต้องตั้งค่านาฬิกาเป็น 4MHz เพื่อให้บัส I2C ทำงานได้อย่างถูกต้อง เซ (); คำสั่งเปิดอินเตอร์รัปต์หลังจากเริ่มต้นไดรเวอร์ I2C เพื่อตรวจสอบข้อผิดพลาด บิตสถานะจะถูกทดสอบ ในระหว่างการอ่าน ต้องเรียกใช้ฟังก์ชัน TWI_Read_Data_From_Buffer เพื่อถ่ายโอนข้อมูลที่อ่านไปยังบัฟเฟอร์ข้อความ ระหว่างการเขียน ในขณะที่ต้องใช้ (TWI_Transceiver_Busy()) เพื่อให้แน่ใจว่าการถ่ายโอนเสร็จสมบูรณ์ก่อนที่จะตรวจสอบข้อผิดพลาด สองฟังก์ชันสุดท้ายนี้อธิบายไว้ข้างต้นในคำอธิบายของไดรเวอร์ นอกจากนั้น รหัสค่อนข้างเหมือนกับ ATtiny2313 DEBUG ทำงานเหมือนกันถ้าคุณต้องการทดลองกับสิ่งนั้น

ขั้นตอนที่ 6: การใช้หน่วยความจำ I2C

การใช้หน่วยความจำ I2C
การใช้หน่วยความจำ I2C
การใช้หน่วยความจำ I2C
การใช้หน่วยความจำ I2C
การใช้หน่วยความจำ I2C
การใช้หน่วยความจำ I2C
การใช้หน่วยความจำ I2C
การใช้หน่วยความจำ I2C

ตอนนี้เราได้เรียนรู้การใช้บัส I2C เพื่ออ่านและเขียน I/O Port Expander แล้ว มาต่อกันที่การใช้หน่วยความจำ I2C ทั้ง RAM และ EEPROM ความแตกต่างที่สำคัญคือสามารถอ่านหรือเขียนหลายไบต์จากหน่วยความจำด้วยคำสั่ง I2C เดียว เพื่อเตรียมพร้อมสำหรับการทดลองเหล่านี้ เราจำเป็นต้องปรับเปลี่ยนฮาร์ดแวร์เล็กน้อย และสร้างวงจรใหม่สองสามวงจรบนเขียงหั่นขนม เก็บวงจร Port Expander เนื่องจากเราจะใช้เพื่อแสดงค่าหน่วยความจำบางส่วน ถอดสวิตช์ DIP ออกจาก PCA8574A แล้วติดไฟกะพริบที่หมุดเหล่านั้น หากคุณมีไฟกะพริบไม่เพียงพอ ให้ย้ายไฟที่ P4 ถึง P7 ไปที่ P0 ถึง P3 (ค่าที่จะแสดงมีขนาดเล็กพอ) ตอนนี้ดูที่แผนผัง I2C Ram.pdf และเชื่อมต่อ PCF8570 บนเขียงหั่นขนม ดูรูปกันยังครับ. อย่าลืมผูกพิน 7 กับ Vcc เดินสายไฟสำหรับ SDA และ SCL จาก PCA8574A ไม่จำเป็นต้องใช้ตัวต้านทานแบบดึงขึ้นเพิ่มเติม หากคุณสนใจ EEPROM ด้วย ให้สร้างวงจรนั้นโดยใช้ I2C EEPROM.pdf สำหรับ 24C16 แต่โปรดทราบว่าตัวอย่างนี้ใช้ ATmega168 วงจรนี้ง่ายจริงๆ ตามที่กล่าวไว้ข้างต้น บิตที่อยู่ควรถูกละเว้น เพียงแค่เชื่อมต่อพลังงานและกราวด์ อย่าเพิ่งเชื่อมต่อ SDA และ SCL เนื่องจากเรายังทำการทดลองกับ Ram ยังไม่เสร็จ เราจะเริ่มการทดสอบหน่วยความจำด้วย ATtiny2313 ที่เชื่อมต่อกับ PCA8574A Port Expander และ PCF8570 Ram โปรแกรมจะเขียนตัวเลขไปที่ Ram จากนั้นอ่านกลับและแสดงบน Port Expander เปลี่ยนไดเร็กทอรีการทำงานของคุณเป็น RAM ภายใต้ USI I2C ใช้ไฟล์ make เพื่อคอมไพล์และดาวน์โหลด USI_I2C_RAM.c โปรดทราบว่าไฟล์ไดรเวอร์ I2C จะเหมือนกับไฟล์ที่เราใช้ก่อนหน้านี้ ต่อสายไฟและคุณจะเห็นไฟ LED 1 กะพริบหนึ่งครั้ง (PD6) ข้อมูลจะถูกเขียนลงในหน่วยความจำ 4 ไบต์แรก กดปุ่มและสองไบต์จะถูกอ่านและแสดงผล คุณควรเห็นไฟ LED ดวงหนึ่งบน Port Expander (P0) หยุด 2 วินาที จากนั้นไฟ LED สองดวง (P0 และ P1) หยุดอีกสองวินาทีและไฟ LED จะดับลง กดปุ่มอีกครั้งเพื่อเริ่มลำดับใหม่ การดีบักนั้นคล้ายกับวิธีการที่อธิบายไว้ข้างต้น ลองมาดูโค้ดกัน เปิด USI_I2C_RAM.c ควรมีลักษณะค่อนข้างคล้ายกับรหัสก่อนหน้า ความแตกต่างที่สำคัญคือรายละเอียดของการอ่านและการเขียนหน่วยความจำ ดูวิธีการโหลดบัฟเฟอร์ข้อความก่อนการเรียกที่ทำการเขียนจริง ไบต์แรกคือแอดเดรสสเลฟที่มีบิตอ่าน/เขียนตั้งค่าไว้อย่างเหมาะสม แต่ไบต์ถัดไปคือที่อยู่หน่วยความจำที่จะเริ่มเขียนข้อมูล จากนั้นไบต์ข้อมูลจริงจะโหลดตามลำดับลงในหน่วยความจำโดยเริ่มจากที่อยู่ที่เราระบุ เราระบุขนาดข้อความเป็น 6 ดังนั้นเราจึงเริ่มเขียนที่ที่อยู่ 00 และเขียนค่า 01, 03, 02 และ 06 ลงในตำแหน่งหน่วยความจำ 00 ถึง 03 หากต้องการอ่านข้อมูลกลับจากหน่วยความจำ เราต้องใช้ฟังก์ชัน USI_TWI_Start_Random_Read บัฟเฟอร์ข้อความรับแอดเดรสสเลฟในไบต์แรกและแอดเดรสเริ่มต้นในไบต์ที่สอง จากนั้นเรียกใช้ฟังก์ชันโดยตั้งค่าขนาดข้อความเป็นจำนวนไบต์ที่จะอ่าน บวก 2 โปรดทราบว่าบิตอ่าน/เขียนไม่สำคัญเนื่องจากการอ่านจะดำเนินการโดยไม่คำนึงถึง ข้อมูลที่ส่งคืนจะเริ่มในตำแหน่งที่สองในบัฟเฟอร์ข้อความ เมื่ออ่านข้อมูลแล้ว ข้อมูลจะกลับด้านเพื่อแสดงบน Port Expander และเขียนทีละไบต์โดยหยุดระหว่างค่าต่างๆ ในที่สุด ไฟ LED ของ Port Expander จะดับลง การเขียนไปยัง Port Expander จะเหมือนกับที่ทำในตัวอย่างก่อนหน้านี้ เพื่อความสนุก คุณสามารถยกเลิกการใส่เครื่องหมาย #define DEBUG คำสั่งข้างต้น และดูไฟ LED กะพริบจำนวนมาก เติมความตื่นเต้นด้วยความตื่นเต้นหลังจากการทดลองที่ประสบความสำเร็จอีกครั้ง ไปที่ ATmega168 และ EEPROM เปลี่ยนไดเร็กทอรีการทำงานของคุณเป็น EEPROM ภายใต้ TWI I2C ใช้ไฟล์ make เพื่อคอมไพล์และดาวน์โหลด TWI_I2C_EEPROM.c. โปรดทราบว่าไฟล์ไดรเวอร์ I2C จะเหมือนกับไฟล์ที่เราใช้ก่อนหน้านี้สำหรับ PCA8574A หากต้องการทดสอบโปรแกรม ให้ถอด ATtiny2313 และเชื่อมต่อ ATmega168 ทิ้งบัส I2C ไว้กับแรมแล้วเปิดเครื่อง ผลลัพธ์จะแตกต่างออกไป เนื่องจากตอนนี้เรากำลังเขียนและอ่านข้อมูลเพิ่มเติม LED 1 บน PD7 ควรกะพริบเมื่อเริ่มต้น กดปุ่มและข้อมูลจะถูกอ่านกลับจากหน่วยความจำและแสดงผล ไฟ LED บน PCA8574 ควรกะพริบตามลำดับต่อไปนี้: P1, P0 & P2, (ปิดทั้งหมด), P0 & P1, P1 & P2 ในที่สุดไฟ LED ของพอร์ตก็ดับลง กดปุ่มอีกครั้งเพื่อทำซ้ำ โอ้ แต่เดี๋ยวก่อน คุณพูด โปรแกรมนี้สำหรับ EEPROM ไม่ใช่หรือ เนื่องจากเรากำลังเข้าถึงอุปกรณ์หน่วยความจำที่อยู่ I2C เดียวกัน โปรแกรมเดียวกันจึงใช้ได้กับทั้ง RAM และ EEPROM ปิดเครื่องและย้าย SDA และ SCL จาก Ram ไปยัง EEPROM แล้วเรียกใช้โปรแกรมอีกครั้ง มันควรจะทำงานเหมือนกันทุกประการ โปรดทราบว่า EEPROM และ Ram ไม่สามารถเชื่อมต่อกับบัส I2C พร้อมกันได้ เนื่องจากใช้ที่อยู่เดียวกัน (คนฉลาดในหมู่คุณอาจพิจารณาเปลี่ยนบิตแอดเดรสที่ตั้งโปรแกรมได้บน Ram แต่ก็ยังใช้ไม่ได้ 24C16 ใช้บล็อกที่อยู่ทั้งหมดที่สามารถตั้งโปรแกรมสำหรับ Ram ได้) โอเค มาดูโปรแกรมสุดท้ายนี้กัน. เปิด TWI_I2C_EEPROM.c สิ่งแรกที่ควรสังเกตคือฉันได้ระบุวิธีจัดการกับ EEPROM 24C16 ที่สมบูรณ์แล้ว สามารถเข้าถึงได้ใน 256 ไบต์ที่ 8 ที่อยู่สลาฟ I2C ที่แตกต่างกัน ดูว่า MEMORY_ADDR ถูกกำหนดให้เป็นที่อยู่เริ่มต้นที่ 50 เลขฐานสิบหกอย่างไร นั่นเป็นเหตุผลที่แรมทำงาน หากคุณต้องการเข้าถึงช่วงอื่นๆ ของ 24C16 ให้ใช้ที่อยู่อื่นตามที่ฉันได้ระบุไว้ มาดูกันว่าผมตั้งค่าให้เขียนลงหน่วยความจำได้อย่างไร อันดับแรก แอดเดรสสเลฟพร้อมชุดบิตการอ่าน/เขียนจะถูกใส่ในบัฟเฟอร์ จากนั้นแอดเดรสเริ่มต้นคือ 00 จากนั้นจึงใส่ข้อมูล 16 ไบต์ ฟังก์ชัน TWI_Start_Read_Write ถูกเรียกให้เขียนข้อมูล (เช่นเคย) โดยกำหนดขนาดข้อความไว้ที่ 18 เมื่อกดปุ่ม เราใช้ TWI_Start_Random_Read และ TWI_Read_Data_From_Buffer เพื่ออ่านข้อมูลกลับ ทุก ๆ ไบต์ที่สามจะแสดงบนไฟ LED ของ Port Expander สุดท้ายไฟ LED จะดับลงเพื่อรอการกดปุ่มถัดไป คุณอาจสงสัยว่าทำไมฉันถึงเลือกเขียน 16 ไบต์ หากคุณอ่านแผ่นข้อมูลอย่างละเอียด คุณจะเห็นว่า 24C16 ทำรอบการเขียนทุกครั้งที่ได้รับ 16 ไบต์ แม้ว่าจะมีการส่งไบต์มากขึ้นก็ตาม ดูเหมือนว่าจะเป็นตัวเลขที่น่าใช้ หากคุณเลือกที่จะเพิ่มสิ่งนี้ คุณจะต้องเปลี่ยนขนาดของ MESSAGEBUF_SIZE นอกจากนี้ คุณจะต้องเปลี่ยนค่า TWI_BUFFER_SIZE ใน TWI_Master.h เนื่องจากโปรแกรมควบคุมคัดลอกข้อมูลจากบัฟเฟอร์ข้อความเพื่อใช้โดยรูทีนบริการขัดจังหวะ ยินดีด้วย! ตอนนี้คุณพร้อมที่จะใช้บัส I2C ในโครงการของคุณเองแล้ว!

ขั้นตอนที่ 7: แหล่งข้อมูลบนเว็บ

นี่คือลิงค์ไปยังแผ่นข้อมูลสำหรับชิ้นส่วนที่ใช้ในการทดลอง คุณควรได้รับสิ่งเหล่านี้อย่างแน่นอนหากคุณไม่ได้อะไรเลย Port ExpanderRamEEPROMBเนื่องจากผู้สร้าง I2C NXP (Philips) มีสิ่งที่ยอดเยี่ยมมากมาย (พวกเขาชอบใช้วงเล็บเหลี่ยมใน URL ของพวกเขา ดังนั้นฉันจึงรวมไว้ที่นี่ไม่ถูกต้อง ขออภัย] ในการไปยังพื้นที่ I2C ให้เลือกอินเทอร์เฟซจากรายการผลิตภัณฑ์ คุณจะสามารถไปที่ไซต์ I2C ของพวกเขาและ เข้าถึงเอกสารข้อมูลและบันทึกของแอปทั้งหมดที่พวกเขาเสนอ คำอธิบายบัส I2C และรายละเอียดทางเทคนิคโดยเฉพาะอยู่ที่นี่ รับเอกสารข้อมูล ATtiny2313 และ ATmega168 (สมุดข้อมูล) จาก Atmel บันทึกแอปพลิเคชัน Atmel อยู่ที่นี่ ดูที่ AVR310 และ AVR315 หยิบโค้ดด้วย ดูที่นี่สำหรับสิ่ง I2C อื่น ๆ อีกมากมาย

ขั้นตอนที่ 8: หมายเหตุสำหรับ Geeks

สำหรับผู้ที่อยากรู้รายละเอียด นี่คือสิ่งที่ควรคำนึงถึงหากคุณดู Atmel Apps Notes และรหัสไดรเวอร์:- วิธีการระบุและสั่งการอุปกรณ์ I2C ไม่ได้เป็นส่วนหนึ่งของข้อกำหนด! นอกเหนือจากแอดเดรสสเลฟและบิตสำหรับอ่าน/เขียน คำสั่ง โหมด ฯลฯ จะไม่ถูกระบุและเป็นข้อมูลเฉพาะสำหรับอุปกรณ์ที่กำหนด เพื่อให้ชัดเจนยิ่งขึ้น โปรดทราบว่ารูปแบบที่ใช้ในตัวอย่าง Atmel ใช้กับตัวอย่างนั้นเท่านั้น และค่อนข้างไม่ได้มาตรฐาน- การใช้งาน USI แตกต่างจากการนำ TWI ไปใช้ในวิธีที่สำคัญบางประการ + ด้วย USI การตอกบัตรมีให้โดยซอฟต์แวร์ ด้วย TWI มีให้โดยเครื่องมือสร้างอัตราบิต + วิธี USI ไม่ใช้การขัดจังหวะ TWI ทำ สิ่งนี้สมเหตุสมผลเนื่องจากตระกูล Mega (โดยใช้ TWI) สามารถทำสิ่งอื่นๆ ได้มากมาย และไม่ควรถูกขัดขวางโดยการถ่ายโอน I2C เวอร์ชันที่ขับเคลื่อนด้วยอินเตอร์รัปต์สำหรับ USI นั้นเป็นไปได้อย่างแน่นอน ไม่ได้ใช้งานในคำแนะนำนี้ + ฮาร์ดแวร์ USI ไม่ได้รับการปรับให้เหมาะสมสำหรับ I2C และสามารถรองรับการถ่ายโอนข้อมูลแบบ 8 บิตเท่านั้น ซึ่งหมายความว่าจำเป็นต้องมีการถ่ายโอนสองครั้งเพื่อส่งบิตที่เก้า (ทั้ง NACK หรือ ACK) ฮาร์ดแวร์ TWI จะจัดการสิ่งนี้โดยอัตโนมัติ ทำให้การใช้งานไดรเวอร์ USI ซับซ้อนขึ้นเล็กน้อย + การตรวจจับข้อผิดพลาดสำหรับ TWI ได้รับการจัดการในฮาร์ดแวร์ USI ต้องการการจัดการในซอฟต์แวร์ซึ่งทำให้บางสิ่งค่อนข้างซับซ้อน + ฮาร์ดแวร์ TWI ควบคุมการกำหนดค่าของพอร์ตโดยตรง ฮาร์ดแวร์ USI ต้องการให้กำหนดค่าบิตพอร์ตก่อนจึงจะสามารถใช้พอร์ตได้ คุณจะเห็นสิ่งนี้ในรูทีน Master_Initialize สำหรับ USI.- Atmel อ้างว่าเป็นไปได้ที่จะใช้การดึงพอร์ต AVR สำหรับการดึงบัส I2C ฉันไม่ได้คิดหาวิธีที่จะทำให้แนวทางนั้นได้ผล การใช้ตัวต้านทานภายนอกสองตัวดูเหมือนเป็นโครงร่างที่ค่อนข้างเรียบง่าย ดังนั้นฉันจึงไม่ได้ใช้เวลามากกับสิ่งนี้

แนะนำ: