ชิปหน่วยความจำคืออะไรและจะตั้งโปรแกรมไมโครวงจรได้อย่างไร วิธีล้าง EEPROM (หน่วยความจำไม่ลบเลือน) โดยใช้หน่วยความจำ eeprom

ครั้งล่าสุดเมื่อฉันเขียน "คำตอบโดยละเอียดสำหรับคำถาม" เกี่ยวกับวิธีการสำรองข้อมูลเฟิร์มแวร์จาก Mega พวกเขาตำหนิฉันที่ไม่พูดถึงการสำรองข้อมูล EEPROM ครั้งนั้นฉันไม่ได้ทำอย่างมีสติเพราะ... ฉันตัดสินอย่างถูกต้องว่าไม่จำเป็นต้องทำให้ทุกอย่างซับซ้อนในขั้นตอนของ "แนวทางสู่กระสุนปืน" เริ่มต้น ความจริงก็คือทุกคนไม่ชัดเจนว่า EEPROM จะไม่กระพริบเมื่อรวบรวมและอัพโหลดเฟิร์มแวร์จาก อาร์ดูโน่ IDE. นั่นคือหมายความว่าไม่มีการอัปโหลดไปยัง EEPROM อย่างแน่นอนเมื่ออัปโหลดเฟิร์มแวร์จาก IDE และการปรับแต่งด้วย EEPROM (หากเปิดใช้งานการใช้งานในเฟิร์มแวร์เลย) จะดำเนินการในระดับที่แตกต่างไปจากเดิมอย่างสิ้นเชิง ดังนั้นการสำรองเฟิร์มแวร์เปลือยโดยไม่ต้อง การปรับเปลี่ยนที่ดีซึ่งอาจ (อาจจะเท่านั้น) ที่สามารถเก็บไว้ใน EEPROM ได้ก็เพียงพอแล้วที่จะบันทึกเฉพาะเฟิร์มแวร์เปล่าเท่านั้น แต่เนื่องจากมีคำถามเกิดขึ้นว่าทำไมไม่ “เคี้ยว” มันล่ะ มาดูกันตามลำดับ EEPROM คืออะไรและทำไมถึงพูดถึงมัน
EEPROM - พื้นที่ (หน่วยความจำแบบอ่านอย่างเดียวที่ตั้งโปรแกรมได้แบบลบได้ด้วยไฟฟ้า) ของหน่วยความจำแบบไม่ลบเลือนของไมโครคอนโทรลเลอร์ซึ่งสามารถเขียนและอ่านข้อมูลได้ มักใช้เพื่อจัดเก็บการตั้งค่าโปรแกรมที่อาจเปลี่ยนแปลงระหว่างการทำงาน และต้องเก็บไว้เมื่อปิดเครื่อง

เครื่องพิมพ์ 3D ใช้ EEPROM อย่างไร
ลองดู Marlin เป็นตัวอย่าง ใน Marlin Firmware เมื่อแกะกล่อง ไม่ได้ใช้ EEPROM พารามิเตอร์ตัวกำหนดค่า (Configuration.h) ซึ่งรวมถึงความสามารถในการใช้งานจะถูกใส่เครื่องหมายความคิดเห็นไว้ตามค่าเริ่มต้น

#กำหนด EEPROM_SETTINGS
#กำหนด EEPROM_CHITCHAT

หากเปิดใช้งานการใช้ EEPROM เครื่องพิมพ์สามารถจัดเก็บและใช้การตั้งค่าต่อไปนี้ (ระบุจากชนชั้นกระฎุมพี):

  • จำนวนก้าวต่อมิลลิเมตร
  • ความเร็วป้อนสูงสุด/ต่ำสุด [มม./วินาที]
  • ความเร่งสูงสุด [มม./วินาที^2]
  • การเร่งความเร็ว
  • การเร่งความเร็วระหว่างการถอยกลับ
  • การตั้งค่าพีไอดี
  • ชดเชยตำแหน่งบ้าน
  • ความเร็วป้อนขั้นต่ำระหว่างการเคลื่อนที่ [มม./วินาที]
  • เวลาส่วนขั้นต่ำ [ms]
  • กระโดดด้วยความเร็วสูงสุด แกน X-Y[มม./วินาที]
  • การกระโดดด้วยความเร็วสูงสุดในแกน Z [มม./วินาที]
คุณสามารถแก้ไขการตั้งค่าเหล่านี้ได้โดยใช้หน้าจอและส่วนควบคุมของเครื่องพิมพ์ เมื่อเปิดใช้งาน EEPROM เมนูควรแสดงรายการต่อไปนี้:
  • เก็บหน่วยความจำ
  • โหลดหน่วยความจำ
  • คืนค่าไม่ปลอดภัย
คุณยังสามารถใช้ GCode เพื่อทำงานโดยตรง (ผ่าน Pronterface)
  • M500 บันทึกการตั้งค่าปัจจุบันใน EEPROM จนกระทั่งสตาร์ทเครื่องครั้งถัดไปหรือสั่ง M501
  • M501 อ่านการตั้งค่าจาก EEPROM
  • M502 รีเซ็ตการตั้งค่าเป็นค่าเริ่มต้นที่ระบุไว้ใน Configurations.h หากคุณรัน M500 หลังจากนั้น ค่าเริ่มต้นจะถูกป้อนลงใน EEPROM
  • M503 แสดงการตั้งค่าปัจจุบัน - ""ที่บันทึกไว้ใน EEPROM""
คุณสามารถอ่านเกี่ยวกับ EEPROM ได้ในเฟิร์มแวร์ Repitier

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

avrdude.exe -p atmega2560 -c การเดินสาย -PCOM5 -b115200 -Ueeprom:r:"printer_eeprom".eep:i

คำสั่งนี้จะอ่านข้อมูล EEPROM ลงในไฟล์ "printer_eeprom.eep" หากสำเร็จ คุณจะเห็นข้อความดังต่อไปนี้บนหน้าจอ

การบันทึกก็ไม่ซับซ้อนและดำเนินการโดยคำสั่งที่คล้ายกันซึ่งจะแตกต่างเฉพาะในคีย์เท่านั้น -ยูไม่ใช่ "r" แต่เป็น "w"

avrdude.exe -p atmega2560 -c การเดินสาย -PCOM5 -b115200 -Ueeprom:w:"printer_eeprom".eep:i

หากสำเร็จ คุณจะเห็นข้อความคล้ายข้อความต่อไปนี้บนหน้าจอ

อย่างไรและทำไมต้องลบ EEPROM?
เริ่มต้นด้วย "ทำไมทำเช่นนี้?" คุณต้องลบ EEPROM หากเฟิร์มแวร์ก่อนหน้านี้ใช้งานด้วย และอาจมีขยะเหลืออยู่ในหน่วยความจำ ฉันพบผู้คนที่มีปัญหาอยู่ที่ไหนสักแห่งซึ่งหลังจากเปลี่ยนจากเฟิร์มแวร์หนึ่งไปยังอีกเฟิร์มแวร์หนึ่ง (จาก Marlin เป็น Repitier EMNIP) เครื่องพิมพ์ของพวกเขาก็เริ่มทำงานเพื่อที่จะพูดได้ว่า "สร้างสรรค์" นี่เป็นเพราะความจริงที่ว่าเฟิร์มแวร์ที่แตกต่างกันเก็บข้อมูลไว้ใต้ ที่อยู่ที่แตกต่างกัน. และเมื่อคุณพยายามอ่านข้อมูลจากที่อยู่ผิด ความโกลาหลก็เริ่มต้นขึ้น
คุณสามารถลบ EEPROM ได้โดยทางโปรแกรมเท่านั้นจากเฟิร์มแวร์ แต่ในการดำเนินการนี้คุณจะต้องอัปโหลดภาพร่างพิเศษไปยังคอนโทรลเลอร์ชั่วคราว คุณสามารถอ่านเพิ่มเติมเกี่ยวกับสิ่งนี้ได้ในเอกสาร Arduino อย่างเป็นทางการ
หาก EEPROM ถูกลบออกไปแล้วไม่เข้า บอร์ดอาร์ดูโน่และในคอนโทรลเลอร์นามธรรมบางตัวจะต้องเปลี่ยนโค้ดร่างโดยคำนึงถึงขนาดของ EEPROM ในคอนโทรลเลอร์เฉพาะบนบอร์ด ในการดำเนินการนี้ คุณจะต้องเปลี่ยนเงื่อนไขการสิ้นสุดในลูป "For" ตัวอย่างเช่น สำหรับ ATmega328 ซึ่งมีหน่วยความจำ EEPROM ขนาด 1kb วงจรจะมีลักษณะดังนี้:
บทสรุป.
ฉันเดินเล่นมาสักพักแล้ว แต่ทั้งหมดนี้เพื่ออะไรล่ะ? เพื่อสรุปว่าเมื่อสำรองข้อมูลเฟิร์มแวร์ EEPROM ก็สามารถบันทึกได้เช่นกัน แต่เฉพาะในกรณีที่คุณต้องการบันทึกการตั้งค่าเท่านั้น หากคุณพร้อมที่จะสังเวยพวกมันก็อย่าลืมมันซะ นอกจากนี้ หากคุณเปลี่ยนเฟิร์มแวร์ตัวหนึ่งเป็นอีกตัวหนึ่ง หรือเปลี่ยนจากเวอร์ชันหนึ่งไปอีกเวอร์ชันหนึ่ง อย่าขี้เกียจที่จะล้าง EEPROM ก่อนที่จะอัปโหลด เฟิร์มแวร์ใหม่. ในขณะเดียวกัน เราก็ได้เรียนรู้สิ่งใหม่ๆ มากมาย

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

สิ่งสำคัญที่เราต้องรู้ก็คือว่า หน่วยความจำอีพรอมเป็นการดีกว่าที่จะพิจารณาว่าไม่ใช่ "เพียงหน่วยความจำ" แต่เป็นอุปกรณ์ภายในที่แยกจากกันในชิป
อีพรอม พื้นที่ที่อยู่แยกต่างหากซึ่งไม่เกี่ยวข้องกับพื้นที่ที่อยู่ของโปรเซสเซอร์ (FLASH และ SRAM) ในการเข้าถึงข้อมูลตามที่อยู่เฉพาะในหน่วยความจำแบบไม่ลบเลือน คุณจำเป็นต้องดำเนินการ ลำดับที่แน่นอนการดำเนินการโดยใช้รีจิสเตอร์จำนวนหนึ่ง (ที่อยู่รีจิสเตอร์ EEARH และ EEARL, รีจิสเตอร์ข้อมูล EEDR และรีจิสเตอร์ควบคุม EECR)
ตามแผ่นข้อมูล หากต้องการเขียนไบต์ไปยังที่อยู่เฉพาะใน EEPROM คุณต้องดำเนินการดังต่อไปนี้:

  1. รอให้ EEPROM พร้อมที่จะเขียนข้อมูล (บิต EEPE ของการลงทะเบียน EECR ถูกรีเซ็ต)
  2. รอการสิ้นสุดการเขียนไปยังหน่วยความจำ FLASH (รีเซ็ตบิต SELFPRGEN ของการลงทะเบียน SPMCSR) - จะต้องดำเนินการนี้หากมี bootloader อยู่ในโปรแกรม
  3. เขียนลงไป ที่อยู่ใหม่ไปยังทะเบียน EEAR (ถ้าจำเป็น)
  4. เขียนไบต์ข้อมูลลงในการลงทะเบียน EEDR (ถ้าจำเป็น)
  5. ตั้งค่าบิต EEMPE ของการลงทะเบียน EECR เป็นหนึ่ง
  6. ภายในสี่รอบนาฬิกาหลังจากตั้งค่าแฟล็ก EEMPE เราจะเขียนโลจิคัลหนึ่งลงในบิต EEPE ของรีจิสเตอร์ EECR

โปรเซสเซอร์จะข้าม 2 รอบสัญญาณนาฬิกาก่อนที่จะดำเนินการคำสั่งถัดไป
จะต้องดำเนินการจุดที่สองหากมี bootloader ในโปรแกรม - ความจริงก็คือการเขียนไปยัง EEPROM ไม่สามารถดำเนินการพร้อมกันกับการเขียนไปยังหน่วยความจำ FLASH ดังนั้นก่อนที่จะเขียนลงใน EEPROM คุณต้องตรวจสอบให้แน่ใจว่าการเขียนโปรแกรมหน่วยความจำ FLASH เสร็จสมบูรณ์ หากไมโครคอนโทรลเลอร์ไม่มี bootloader ก็จะไม่เปลี่ยนเนื้อหาของหน่วยความจำ FLASH (โปรดจำไว้ว่า avr มีสถาปัตยกรรมของ Harvard: หน่วยความจำโปรแกรม (FLASH) และหน่วยความจำข้อมูล (SRAM) จะถูกแยกออกจากกัน)
ระยะเวลาของรอบการบันทึกขึ้นอยู่กับความถี่ของออสซิลเลเตอร์ RC ภายในของชิป แรงดันไฟฟ้าและอุณหภูมิ โดยปกติสำหรับรุ่น ATmega48x/88x/168x คือ 3.4 ms (!) สำหรับรุ่นเก่าบางรุ่น – 8.5 ms (!!!)
นอกจากนี้ เมื่อเขียนไปยัง EEPROM ปัญหาอาจเกิดขึ้นกับการเรียกการขัดจังหวะระหว่างการดำเนินการตามลำดับของการกระทำข้างต้น - ดังนั้นจึงเป็นการดีกว่าที่จะปิดการใช้งานการขัดจังหวะในขณะที่เขียนไปยัง EEPROM
การอ่านหน่วยความจำแบบไม่ลบเลือนนั้นง่ายกว่าเล็กน้อย:

  1. รอให้ EEPROM พร้อมที่จะอ่านข้อมูล (บิต EEWE ของการลงทะเบียน EECR ถูกรีเซ็ต)
  2. เขียนที่อยู่ลงในทะเบียน EEAR
  3. ตั้งค่าบิต EERE ของการลงทะเบียน EECR เป็นหนึ่ง
  4. เราอ่านข้อมูลจากการลงทะเบียน EEDR (อันที่จริง เมื่อข้อมูลที่ร้องขอถูกย้ายไปยังการลงทะเบียนข้อมูล มันจะเกิดขึ้น ฮาร์ดรีเซ็ตบิต EERE; แต่ไม่จำเป็นต้องตรวจสอบสถานะของบิตนี้เนื่องจากการดำเนินการอ่านจาก EEPROM จะดำเนินการในรอบนาฬิกาเดียวเสมอ)

หลังจากตั้งค่าบิตใน EERE เป็นหนึ่งแล้ว โปรเซสเซอร์จะข้าม 4 รอบสัญญาณนาฬิกาก่อนที่จะดำเนินการคำสั่งถัดไป
อย่างที่เราเห็นการทำงานด้วย หน่วยความจำไม่ลบเลือน– กระบวนการนี้ใช้เวลานาน หากเราเขียนและอ่านข้อมูลจาก EEPROM บ่อยๆ โปรแกรมก็อาจจะเริ่มทำงานช้าลง

อย่างไรก็ตาม เรากำลังเขียนโปรแกรมในสภาพแวดล้อม IAR และเราโชคดี: งานทั้งหมดที่มีการอ่านและเขียนจาก EEPROM จะเสร็จสิ้นโดยสภาพแวดล้อมการพัฒนา - iar มีตัวดัดแปลง “__eeprom” ซึ่งสร้างตัวแปรในหน่วยความจำแบบไม่ลบเลือน - จากนั้นเราจะต้องอ่านจากตัวแปร "ถาวร" เป็น "ปัจจุบัน" (เมื่อเริ่มต้นคอนโทรลเลอร์) หรือเขียนจากตัวแปร "ปัจจุบัน" เป็น "คงที่" - นั่นคือเมื่อค่าปัจจุบันเปลี่ยนแปลง ค่าของ ต้องเปลี่ยนตัวแปรในหน่วยความจำแบบไม่ลบเลือนด้วย
ตัวแปรใหม่จะมีลักษณะดังนี้:

Eeprom uint16_t EEP_Minอุณหภูมิ;

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

Uint16_t __eeprom *EEP_MinTemperatureAdr;

กลับไปที่ตัวควบคุมเตาและ EEPROM กัน ในกรณีของเราไม่มี EEPROM เครื่องเสมือนแน่นอนว่าเป็นสิ่งที่ไม่คาดหวัง ยิ่งไปกว่านั้น ควรพิจารณาว่าจำเป็นต้องใช้ไลบรารีแยกต่างหากในการทำงานกับหน่วยความจำแบบไม่ลบเลือนหรือไม่ เนื่องจากพวกมัน "กระจัดกระจาย" เกินไปในโปรแกรมการบันทึก การตั้งค่าที่สำคัญ; หากคุณพยายามสร้างไลบรารี่แยกต่างหาก คุณจะต้องทำการอ้างอิงโยง: ในไลบรารีสำหรับ EEPROM ให้เชื่อมต่อไลบรารีของ ADC องค์ประกอบความร้อน และการตั้งค่าส่วนกลาง และในไลบรารีอุปกรณ์ต่อพ่วงเหล่านี้ การเชื่อมต่อไลบรารี EEPROM ไม่ใช่แนวทางที่ดีนัก
อีกทางเลือกหนึ่งคือการเพิ่มตัวแปร eeprom ลงในแต่ละไลบรารีที่คุณต้องการบันทึกการตั้งค่า และบันทึกการตั้งค่าที่เกี่ยวข้องโดยตรงใน เครื่องเสมือน. เราจะใช้ตัวเลือกนี้
ขั้นแรก เรามาแสดงรายการตัวแปรที่เราจำเป็นต้องบันทึกใน EEPROM:

  1. จุดสอบเทียบ
  2. ค่าอุณหภูมิที่ตั้งไว้สูงสุด-ต่ำสุด และขั้นตอนการตั้งอุณหภูมิ
  3. ตั้งค่าอุณหภูมิ
  4. ค่าสัมประสิทธิ์ตัวควบคุม PID

เราไม่บันทึกค่าตัวจับเวลาในครัว - เราจะถือว่าผู้ใช้ต้องตั้งเวลาเตาทุกครั้งหลังจากปิดเครื่อง
การตั้งค่าทั้งหมดนี้กำหนดโดยผู้ใช้โดยการหมุนตัวเข้ารหัส จากนั้นกดปุ่มผู้ใช้สั้นๆ ในเวลาเดียวกัน เราจำได้ว่าจำนวนรอบการอ่าน-เขียนของ EEPROM ยังมีจำกัด ดังนั้นอย่าเขียนทับข้อมูลเดิมอีก (เช่น หากผู้ใช้เลือกค่าเดิมของการตั้งค่าบางอย่างเหมือนเดิม) ดังนั้น ก่อนที่จะเปลี่ยนแปลงตัวแปร __eeprom แต่ละครั้ง เราจะตรวจสอบว่าจำเป็นต้องเขียนใหม่หรือไม่:

// หากค่ามีการเปลี่ยนแปลงให้เขียนทับในหน่วยความจำแบบไม่ลบเลือนหาก (ADCTemperature.atMinTemperatureValue != (uint16_t)VMEncoderCounter.ecntValue) ( ​​​​ADCTemperature.atMinTemperatureValue = (uint16_t)VMEncoderCounter.ecntValue; EEP_MinTemperature = ADCTemperature.atMinTemperatureV alue; )

การอ่านการตั้งค่าจาก EEPROM ก็ทำได้ง่ายเช่นกัน - เมื่อเริ่มต้นการตั้งค่า "ปัจจุบัน" เราก็จะอ่านค่าจากหน่วยความจำแบบไม่ลบเลือน:

ADCTemperature.atMinTemperatureValue = EEP_MinTemperature;

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

eeprom uint16_t EEP_MinTemperature = 20; ... //อาร์เรย์สำหรับจัดเก็บจุดการสอบเทียบในหน่วยความจำแบบไม่ลบเลือน __eeprom TCalibrationData EEP_CalibrationData = ((20, 1300), (300, 4092));

ในกรณีนี้ คอมไพเลอร์จะเริ่มต้นตัวแปร __eeprom ก่อนที่จะเริ่มทำงานกับฟังก์ชันหลัก หากต้องการรับไฟล์ที่มีหน่วยความจำแบบไม่ลบเลือน (.eep) คุณต้องเข้าไปที่การตั้งค่าต่อไปนี้:
โครงการ->ตัวเลือก..->ตัวเชื่อมโยง->ตัวเลือกพิเศษ
หากไม่ได้ทำเครื่องหมายในช่อง “ใช้ตัวเลือกบรรทัดคำสั่ง” ให้ทำเครื่องหมายในช่องและเพิ่มบรรทัด
-Ointel-มาตรฐาน (XDATA)=.eep
ขั้นแรกเรารวบรวมโปรเจ็กต์ด้วยตัวแปรเริ่มต้น บันทึกไฟล์ eep แยกต่างหาก จากนั้นเราจะลบการเริ่มต้นเมื่อสร้างตัวแปร

เพียงเท่านี้ - เตาของเราพร้อมแล้ว!

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

คำอธิบายของหน่วยความจำ EEPROM

Arduino มอบหน่วยความจำอุปกรณ์ในตัวให้กับผู้ใช้สามประเภท: RAM แบบคงที่ (หน่วยความจำเข้าถึงโดยสุ่มหรือ SRAM - หน่วยความจำเข้าถึงโดยสุ่มแบบคงที่) - จำเป็นสำหรับการบันทึกและจัดเก็บข้อมูลระหว่างการใช้งาน; แฟลชการ์ด - สำหรับบันทึกรูปแบบที่บันทึกไว้แล้ว – สำหรับการจัดเก็บและการใช้ข้อมูลในภายหลัง

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

ตัวย่อย่อมาจาก หน่วยความจำแบบอ่านอย่างเดียวที่ตั้งโปรแกรมได้ซึ่งลบได้ด้วยไฟฟ้า และแปลเป็นภาษารัสเซียตามตัวอักษรว่า หน่วยความจำแบบอ่านอย่างเดียวที่ตั้งโปรแกรมได้ซึ่งลบได้ด้วยไฟฟ้า ผู้ผลิตรับประกันความปลอดภัยของข้อมูลเป็นเวลาหลายทศวรรษหลังจากการไฟฟ้าดับครั้งสุดท้าย (โดยปกติแล้วจะเป็นระยะเวลา 20 ปี ขึ้นอยู่กับอัตราที่ค่าใช้จ่ายของอุปกรณ์ลดลง)

อย่างไรก็ตาม คุณจำเป็นต้องทราบว่าความสามารถในการเขียนซ้ำไปยังอุปกรณ์นั้นมีจำกัดและไม่เกิน 100,000 ครั้ง ดังนั้นขอแนะนำให้ใช้ความระมัดระวังและใส่ใจกับข้อมูลที่ป้อนและไม่เขียนทับอีกครั้ง

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

  • ATmega328 – 1kB
  • ATmega168 และ ATmega8 - 512 ไบต์
  • และ ATmega1280 – 4 kB.

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

การเขียนลง EEPROM ต้องใช้เวลาพอสมควร - ประมาณ 3 มิลลิวินาที. หากปิดเครื่องขณะบันทึก ข้อมูลจะไม่ได้รับการบันทึกเลยหรืออาจถูกบันทึกไม่ถูกต้อง จำเป็นต้องตรวจสอบข้อมูลที่ป้อนเพิ่มเติมเสมอเพื่อหลีกเลี่ยงความล้มเหลวระหว่างการทำงาน การอ่านข้อมูลเร็วขึ้นมากและทรัพยากรหน่วยความจำก็ไม่ลดลง

ห้องสมุด

การทำงานกับหน่วยความจำ EEPROM ดำเนินการโดยใช้ไลบรารีที่สร้างขึ้นเป็นพิเศษสำหรับ Arduino สิ่งสำคัญคือความสามารถในการเขียนและอ่านข้อมูล เปิดใช้งานตามคำสั่ง #รวมEEPROM.h.

  • สำหรับ บันทึก– EEPROM.write(ที่อยู่, ข้อมูล);
  • สำหรับ การอ่าน– EEPROM.read(ที่อยู่)

ในภาพร่างเหล่านี้: ที่อยู่ – อาร์กิวเมนต์ที่มีข้อมูลของเซลล์ที่ป้อนข้อมูลของข้อมูลอาร์กิวเมนต์ที่สอง เมื่ออ่านจะใช้หนึ่งอาร์กิวเมนต์ที่อยู่ซึ่งระบุตำแหน่งที่ควรอ่านข้อมูล

การทำงาน วัตถุประสงค์
อ่าน(ที่อยู่) อ่าน 1 ไบต์จาก EEPROM; ที่อยู่ - ที่อยู่ที่อ่านข้อมูล (เซลล์เริ่มต้นจาก 0)
เขียน(ที่อยู่, ค่า) เขียนค่า (1 ไบต์, ตัวเลขตั้งแต่ 0 ถึง 255) ไปยังหน่วยความจำตามที่อยู่;
อัปเดต (ที่อยู่, ค่า) แทนที่ค่าที่อยู่หากเนื้อหาเก่าแตกต่างจากเนื้อหาใหม่
รับ(ที่อยู่ ข้อมูล) อ่านข้อมูลประเภทที่ระบุจากหน่วยความจำตามที่อยู่
ใส่(ที่อยู่, ข้อมูล) เขียนข้อมูลประเภทที่ระบุลงในหน่วยความจำตามที่อยู่
อีพรอม อนุญาตให้คุณใช้ตัวระบุ "EEPROM" เป็นอาร์เรย์เพื่อเขียนข้อมูลและอ่านจากหน่วยความจำ

การเขียนจำนวนเต็ม

การเขียนจำนวนเต็มไปยังหน่วยความจำ EEPROM แบบไม่ลบเลือนนั้นค่อนข้างง่าย การป้อนตัวเลขเกิดขึ้นเมื่อเปิดใช้งานฟังก์ชัน EEPROM.write(). ข้อมูลที่ต้องการแสดงอยู่ในวงเล็บ ในกรณีนี้ ตัวเลขตั้งแต่ 0 ถึง 255 และตัวเลขที่มากกว่า 255 จะถูกเขียนแตกต่างกัน อันแรกถูกป้อนอย่างง่าย ๆ - ปริมาณของมันใช้เวลา 1 ไบต์นั่นคือหนึ่งเซลล์ หากต้องการเขียนอย่างหลัง คุณต้องใช้ตัวดำเนินการ highByte() สำหรับไบต์สูงสุด และ lowByte() สำหรับไบต์ต่ำสุด

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

3 * 256 + 21 = 789

สำหรับ « การรวมตัวใหม่" ใช้จำนวนเต็มขนาดใหญ่ ฟังก์ชั่นคำ(): int val = คำ (สวัสดี ต่ำ). คุณต้องอ่านว่าจำนวนเต็มสูงสุดสำหรับการบันทึกคือ 65536 (นั่นคือ 2 ยกกำลัง 16) ในเซลล์ที่ยังไม่มีรายการอื่น จอภาพจะแสดงตัวเลข 255 ในแต่ละเซลล์

การเขียนตัวเลขและสตริงทศนิยม

จำนวนจุดลอยตัวและจำนวนสตริงเป็นรูปแบบหนึ่งของการเขียนจำนวนจริงโดยแสดงแทนด้วยแมนทิสซาและเลขชี้กำลัง ตัวเลขดังกล่าวถูกเขียนลงในหน่วยความจำ EEPROM แบบไม่ลบเลือนโดยการเปิดใช้งานฟังก์ชัน EEPROM.ใส่(), การอ่านตามลำดับ – EEPROM.get().

เมื่อทำการเขียนโปรแกรมค่าตัวเลขทศนิยมจะถูกกำหนดให้เป็นทศนิยมเป็นที่น่าสังเกตว่านี่ไม่ใช่คำสั่ง แต่เป็นตัวเลข ประเภทอักขระ (ประเภทอักขระ) – ใช้เพื่อแสดงสตริง กระบวนการเขียนตัวเลขบนจอภาพเริ่มต้นโดยใช้ setup() การอ่าน - การใช้ loop()

ในระหว่างกระบวนการ ค่า ovf ซึ่งหมายถึง "ล้น" และ nan ซึ่งหมายถึง "ขาดหายไป" อาจปรากฏบนหน้าจอมอนิเตอร์ ค่าตัวเลข" ซึ่งหมายความว่าข้อมูลที่เขียนลงในเซลล์ไม่สามารถทำซ้ำเป็นตัวเลขทศนิยมได้ สถานการณ์นี้จะไม่เกิดขึ้นหากคุณรู้ได้อย่างน่าเชื่อถือว่าเซลล์ใดบันทึกข้อมูลประเภทใด

ตัวอย่างโครงการและภาพร่าง

ตัวอย่างหมายเลข 1

แบบร่างจะเขียนอักขระสูงสุด 16 ตัวจากพอร์ตอนุกรมและส่งออกอักขระ 16 ตัวจาก EEPROM ในลักษณะวนซ้ำ ด้วยเหตุนี้ข้อมูลจึงถูกเขียนลงใน EEPROM และตรวจสอบเนื้อหาของหน่วยความจำแบบไม่ลบเลือน

// ตรวจสอบการทำงานของ EEPROM #include ฉัน, d; การตั้งค่าเป็นโมฆะ () ( Serial.begin (9600); // เริ่มต้นพอร์ต, ความเร็ว 9600 ) void loop () ( // อ่าน EEPROM และส่งออกข้อมูล 16 รายการไปยังพอร์ตอนุกรม Serial.println (); Serial.print ("EEPROM = " ); i= 0; ในขณะที่(i< 16) { Serial.print((char)EEPROM.read(i)); i++; } // проверка есть ли данные для записи if (Serial.available() != 0) { delay(50); // ожидание окончания приема данных // запись в EEPROM i= 0; while(i < 20) { d= Serial.read(); if (d == -1) d= " "; // если символы закончились, заполнение пробелами EEPROM.write(i, (byte)d); // запись EEPROM i++; } } delay(500); }

ตัวอย่างหมายเลข 2

เพื่อความเข้าใจที่ดีขึ้น เราสามารถสร้างภาพร่างเล็กๆ ที่จะช่วยทำความเข้าใจวิธีการทำงานกับหน่วยความจำแบบไม่ลบเลือนได้ เรานับเซลล์ทั้งหมดของความทรงจำนี้ หากเซลล์ไม่ว่าง - ส่งออกไปยังพอร์ตอนุกรม จากนั้นเติมช่องว่างลงในเซลล์ จากนั้นเราป้อนข้อความผ่านมอนิเตอร์พอร์ตอนุกรม เราเขียนลงใน EEPROM และอ่านเมื่อเปิดครั้งต่อไป

#รวม ที่อยู่ int = 0; // ที่อยู่ eeprom int read_value = 0; // ข้อมูลที่อ่านจาก eeprom char serial_in_data; // ข้อมูลพอร์ตอนุกรม int led = 6; // บรรทัด 6 สำหรับ LED int i; การตั้งค่าเป็นโมฆะ () ( pinMode (led, OUTPUT); // บรรทัด 6 ได้รับการกำหนดค่าเป็นเอาต์พุต Serial.begin (9600); // อัตรารับส่งข้อมูลบนพอร์ตอนุกรม 9600 Serial.println (); Serial.println ("ข้อความก่อนหน้าใน EEPROM : -"); สำหรับ (ที่อยู่ = 0; ที่อยู่< 1024; address ++) // считываем всю память EEPROM { read_value = EEPROM.read(address); Serial.write(read_value); } Serial.println(); Serial.println("WRITE THE NEW TEXT: "); for(address = 0; address < 1024; address ++) // заполняем всю память EEPROM пробелами EEPROM.write(address, " "); for(address = 0; address < 1024;) // записываем пришедшие с последовательного порта данные в память EEPROM { if(Serial.available()) { serial_in_data = Serial.read(); Serial.write(serial_in_data); EEPROM.write(address, serial_in_data); address ++; digitalWrite(led, HIGH); delay(100); digitalWrite(led, LOW); } } } void loop() { //---- мигаем светодиодом каждую секунду -----// digitalWrite(led, HIGH); delay(1000); digitalWrite(led, LOW); delay(1000); }

ตัวอย่างหมายเลข 3

เขียนจำนวนเต็มสองตัวลงในหน่วยความจำ อ่านจาก EEPROM และส่งออกไปยังพอร์ตอนุกรม ตัวเลขตั้งแต่ 0 ถึง 255 ใช้หน่วยความจำ 1 ไบต์โดยใช้ฟังก์ชัน EEPROM.write()ถูกเขียนลงในเซลล์ที่ต้องการ สำหรับตัวเลขที่มากกว่า 255 จะต้องแบ่งเป็นไบต์โดยใช้ ไบต์สูง()และ ไบต์ต่ำ()และเขียนแต่ละไบต์ลงในเซลล์ของตัวเอง จำนวนสูงสุดในกรณีนี้คือ 65536 (หรือ 2 16)

#รวม // เชื่อมต่อไลบรารี EEPROM เป็นโมฆะการตั้งค่า () ( int smallNum = 123; // จำนวนเต็มตั้งแต่ 0 ถึง 255 EEPROM.write (0, smallNum); // เขียนตัวเลขลงในเซลล์ 0 int bigNum = 789; // แยกตัวเลข > 255 คูณ 2 ไบต์ (สูงสุด 65536) ไบต์ hi = highByte(bigNum); // ไบต์สูง ไบต์ต่ำ = lowByte(bigNum); // ไบต์ต่ำ EEPROM.write(1, hi); // เขียนไบต์สูงของ EEPROM ไปที่เซลล์ 1 .write(2, low); // เขียนไบต์ต่ำไปที่เซลล์ 2 Serial.begin(9600); // เตรียมใช้งานพอร์ตอนุกรม ) void loop() ( for (int addr=0; addr<1024; addr++) { // для всех ячеек памяти (для Arduino UNO 1024) byte val = EEPROM.read(addr); // считываем 1 байт по адресу ячейки Serial.print(addr); // выводим адрес в послед. порт Serial.print("\t"); // табуляция Serial.println(val); // выводим значение в послед. порт } delay(60000); // задержка 1 мин }

ตัวอย่างหมายเลข 4

การเขียนตัวเลขและสตริงทศนิยม - วิธีการ EEPROM.ใส่(). การอ่าน - EEPROM.get().

#รวม // เชื่อมต่อการตั้งค่าโมฆะของไลบรารี () ( int addr = 0; // ที่อยู่ float f = 3.1415926f; // หมายเลขจุดลอยตัว (ประเภทลอย) EEPROM.put (addr, f); // เขียนตัวเลข f ไปยังที่อยู่ addr addr += sizeof(float); // คำนวณชื่อถ่านเซลล์หน่วยความจำว่างถัดไป = "Hello, SolTau.ru!"; // สร้างอาร์เรย์ของอักขระ EEPROM.put (addr, name); // เขียนอาร์เรย์ ถึง EEPROM Serial.begin (9600); // การเริ่มต้นพอร์ตอนุกรม) void loop() ( สำหรับ (int addr=0; addr<1024; addr++) { // для всех ячеек памяти (1024Б=1кБ) Serial.print(addr); // выводим адрес в послед. порт Serial.print("\t"); // табуляция float f; // переменная для хранения значений типа float EEPROM.get(addr, f); // получаем значение типа float по адресу addr Serial.print(f, 5); // выводим с точностью 5 знаков после запятой Serial.print("\t"); // табуляция char c; // переменная для хранения массива из 20 символов EEPROM.get(addr, c); // считываем массив символов по адресу addr Serial.println(c); // выводим массив в порт } delay(60000); // ждём 1 минуту }

ตัวอย่างหมายเลข 5

การใช้ EEPROM เป็นอาร์เรย์

#รวม การตั้งค่าเป็นโมฆะ () ( EEPROM = 11; // เขียน EEPROM เซลล์ที่ 1 = 121; // เขียน EEPROM เซลล์ที่ 2 = 141; // เขียน EEPROM เซลล์ที่ 3 = 236; // เขียนเซลล์ที่ 4 Serial .begin (9600 ); ) void loop() ( for (int addr=0; addr<1024; addr++) { Serial.print(addr); Serial.print("\t"); int n = EEPROM; // считываем ячейку по адресу addr Serial.println(n); // выводим в порт } delay(60000); }

ทำงานร่วมกับ EEPROM

ตามที่กล่าวไว้ข้างต้น หน่วยความจำ EEPROM นั้นมีจำกัด เพื่อยืดอายุการใช้งานของหน่วยความจำแบบไม่ลบเลือน แทนที่จะใช้ฟังก์ชัน write() ควรใช้ฟังก์ชันอัปเดตจะดีกว่า ในกรณีนี้ การเขียนใหม่จะดำเนินการเฉพาะกับเซลล์ที่มีค่าแตกต่างจากเซลล์ที่เขียนใหม่เท่านั้น

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

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

มีหลายสถานการณ์ที่ EEPROM มีข้อมูลที่ไม่ถูกต้อง:

  1. เมื่อเปิดใช้งานครั้งแรกยังไม่มีรายการใดๆ
  2. ในระหว่างไฟฟ้าดับที่ไม่สามารถควบคุมได้ ข้อมูลบางส่วนหรือทั้งหมดจะไม่ถูกบันทึกหรือจะถูกบันทึกอย่างไม่ถูกต้อง
  3. หลังจากเสร็จสิ้นรอบการเขียนข้อมูลที่เป็นไปได้ใหม่

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

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

โปรแกรมเมอร์ที่มีประสบการณ์จะเพิ่ม "เอกสิทธิ์หรือ" เพิ่มเติมให้กับโค้ดนี้ เช่น E5h หากค่าทั้งหมดเท่ากับศูนย์ และระบบรีเซ็ตข้อมูลเดิมโดยไม่ตั้งใจ เคล็ดลับนี้จะเปิดเผยข้อผิดพลาด

นี่เป็นหลักการพื้นฐานของการทำงานกับหน่วยความจำ EEPROM แบบไม่ลบเลือนสำหรับไมโครคอนโทรลเลอร์ Arduino สำหรับบางโครงการควรใช้หน่วยความจำประเภทนี้เท่านั้น มันมีทั้งข้อดีและข้อเสีย หากต้องการเชี่ยวชาญวิธีการเขียนและการอ่าน ควรเริ่มจากงานง่ายๆ ก่อน

ไมโครคอนโทรลเลอร์ทั้งหมดของตระกูล Mega มีหน่วยความจำแบบไม่ลบเลือน ( อีพรอมหน่วยความจำ). ปริมาตรของหน่วยความจำนี้มีตั้งแต่ 512 ไบต์ในรุ่น ATmega8x ถึง 4 KB ในรุ่นเก่า อีพรอมหน่วยความจำตั้งอยู่ในพื้นที่ที่อยู่ของตัวเองและเช่นเดียวกับ RAM จะถูกจัดเรียงเป็นเส้นตรง ที่จะทำงานร่วมกับ อีพรอมหน่วยความจำใช้รีจิสเตอร์ I/O สามรายการ: รีจิสเตอร์ที่อยู่, รีจิสเตอร์ข้อมูล และรีจิสเตอร์ควบคุม

ทะเบียนที่อยู่

ทะเบียนที่อยู่ อีพรอมหน่วยความจำ EEAR (การลงทะเบียนที่อยู่ EEPROM)ตั้งอยู่ทางกายภาพในสอง รถบ้าน EARH:EARL, ตั้งอยู่ริม
ที่อยู่ $1F ($3F) และ $1E ($3E) ตามลำดับ การลงทะเบียนนี้เต็มไปด้วยที่อยู่ของเซลล์ที่จะเข้าถึง การลงทะเบียนที่อยู่สามารถเขียนและอ่านได้ ขณะเดียวกันในทะเบียน อีร์ฮมีการใช้เฉพาะบิตที่มีนัยสำคัญน้อยที่สุดเท่านั้น (จำนวนบิตที่เกี่ยวข้องขึ้นอยู่กับระดับเสียง อีพรอมหน่วยความจำ). รีจิสเตอร์บิตที่ไม่ได้ใช้ อีร์ฮอ่านอย่างเดียวและมี "0"

การลงทะเบียนข้อมูล

การลงทะเบียนข้อมูล อีพรอมหน่วยความจำ EEDR (การลงทะเบียนข้อมูล EEPROM)อยู่ที่ $1D ($3D) เมื่อเขียนถึงทะเบียนนี้ จะมีการโหลดข้อมูลที่ควรวางไว้ อีพรอมและเมื่ออ่านข้อมูลจะอ่านจาก อีพรอม.

ควบคุมการลงทะเบียน

ควบคุมการลงทะเบียน อีพรอมหน่วยความจำ EECR (การลงทะเบียนควบคุม EEPROM)อยู่ที่ $1C ($3C) ทะเบียนนี้ใช้สำหรับ
การควบคุมการเข้าถึง อีพรอมหน่วยความจำ. คำอธิบายแสดงอยู่ในตารางด้านล่าง:

ปลดประจำการ ชื่อ คำอธิบาย
7..4 - ไม่ได้ใช้ อ่านว่า "0"
3 น่าขนลุก เปิดใช้งานการขัดจังหวะจาก EEPROM บิตนี้จะควบคุมการสร้างการขัดจังหวะที่เกิดขึ้นเมื่อรอบการเขียน EEPROM เสร็จสิ้น หากบิตนี้ถูกตั้งค่าเป็น "1" การขัดจังหวะจะถูกเปิดใช้งาน (หาก I แฟล็กของรีจิสเตอร์
SREG ยังถูกตั้งค่าเป็น "1") เมื่อบิต EEWE ถูกล้าง (ดูเพิ่มเติมใน
ตาราง) การขัดจังหวะจะถูกสร้างขึ้นอย่างต่อเนื่อง
2 อีมเว การควบคุมสิทธิ์การเขียนใน EEPROM สถานะของบิตนี้จะกำหนดการทำงานของแฟล็กการเปิดใช้งานการเขียน EEWE หากบิตนี้ถูกตั้งค่าเป็น "1" ดังนั้นเมื่อเขียนไปยังบิต EEWE "1" ข้อมูลจะถูกเขียนไปยัง EEPROM มิฉะนั้น การตั้งค่า EEWE เป็น "1" จะไม่มีผลใดๆ หลังจากการติดตั้งซอฟต์แวร์ บิต EEMWE จะถูกรีเซ็ตโดยฮาร์ดแวร์ผ่านทาง
4 รอบเครื่อง
1 อี๊ อนุญาตให้เขียนไปยัง EEPROM เมื่อบิตนี้ตั้งค่าเป็น "1" ข้อมูลจะถูกเขียนไปยัง EEPROM (หาก EEMWE เท่ากับ "1")
0 อีเร อ่านสิทธิ์จาก EEPROM หลังจากตั้งค่าบิตนี้เป็น "1" ข้อมูลจะถูกอ่านจาก EEPROM เมื่ออ่านเสร็จแล้ว บิตนี้จะถูกรีเซ็ตโดยฮาร์ดแวร์

ในการเขียนหนึ่งไบต์ไปยัง EEPROM คุณต้องมี:

1. รอจนกระทั่ง EEPROM พร้อมที่จะเขียนข้อมูล (รอจนกว่าการตั้งค่าสถานะ EEWE ของการลงทะเบียน EECR จะถูกรีเซ็ต)

2. รอให้การเขียนลงในหน่วยความจำโปรแกรม FLASH เสร็จสิ้น (รอจนกระทั่งรีเซ็ตแฟล็ก SPMEN ของรีจิสเตอร์ SPMCR)

3. โหลดไบต์ข้อมูลลงในรีจิสเตอร์ EEDR และที่อยู่ที่ต้องการลงในรีจิสเตอร์ EEAR (หากจำเป็น)

4. ตั้งค่าสถานะ EEMWE ของการลงทะเบียน EECR เป็น “1”

5. เขียนบันทึกลงในบิต EEWE ของรีจิสเตอร์ EECR "1" สำหรับ 4 รอบเครื่อง หลังจากติดตั้งบิตนี้แล้ว โปรเซสเซอร์
ข้าม 2 รอบเครื่องก่อนดำเนินการคำสั่งถัดไป

หากต้องการอ่านหนึ่งไบต์จาก EEPROM คุณต้องมี:

1. ตรวจสอบสถานะของธง EEWE ความจริงก็คือในขณะที่ดำเนินการเขียนในหน่วยความจำ EEPROM (ตั้งค่าสถานะ EEWE) ไม่สามารถดำเนินการอ่านหน่วยความจำ EEPROM หรือเปลี่ยนการลงทะเบียนที่อยู่ได้

2. โหลดที่อยู่ที่ต้องการลงในทะเบียน EEAR

3. ตั้งค่าบิต EERE ของรีจิสเตอร์ EECR เป็น “1”

เมื่อข้อมูลที่ร้องขอถูกวางลงในการลงทะเบียนข้อมูล EEDR การรีเซ็ตฮาร์ดแวร์ของบิตนี้จะเกิดขึ้น อย่างไรก็ตาม ไม่จำเป็นต้องตรวจสอบสถานะของบิต EERE เพื่อพิจารณาว่าการดำเนินการอ่านเสร็จสมบูรณ์เมื่อใด เนื่องจากการดำเนินการอ่านจาก EEPROM จะเสร็จสิ้นในรอบเครื่องเดียวเสมอ นอกจากนี้ หลังจากตั้งค่าบิต EERE เป็น "1" แล้ว โปรเซสเซอร์จะข้ามรอบเครื่อง 4 รอบก่อนที่จะเริ่มคำสั่งถัดไป

สภาพแวดล้อม AVR Studio GCC มีไลบรารีมาตรฐานสำหรับการทำงานกับ EEPROM ซึ่งเปิดใช้งานโดยการเชื่อมต่อไฟล์ . หน้าที่หลักคือ eeprom_read_byte(), eeprom_write_byte(), eeprom_read_word(), eeprom_write_word()ตัวอย่างเช่น ลองเขียนโปรแกรมสำหรับมินิเคาน์เตอร์จาก 0 ถึง 9 โดยที่เมื่อคุณกดปุ่มหนึ่งค่าจะถูกเพิ่มเข้าไป และอีกปุ่มหนึ่งจะเก็บค่านี้ไว้ในหน่วยความจำ ไมโครคอนโทรลเลอร์ Atmega8 ทำงานจากเครื่องกำเนิดสัญญาณนาฬิกาภายในที่มีความถี่ 8 MHz ตัวบ่งชี้เจ็ดส่วนหลักเดียวที่มีขั้วบวกทั่วไปเชื่อมต่อกับพอร์ต B ผ่านตัวต้านทานจำกัดกระแส R1-R7 ขั้วบวกทั่วไปเชื่อมต่อกับแหล่งจ่ายไฟบวก แผนภาพแสดงด้านล่าง:

ขั้นแรก เราเชื่อมต่อไลบรารีที่จำเป็นสำหรับการทำงาน รวมถึง EEPROM กำหนดตัวแปร ตัวแปร "s" เก็บค่าสำหรับการแสดงผลบนตัวบ่งชี้ เมื่อคุณกดปุ่ม SB1 ค่านี้จะเพิ่มขึ้นทีละหนึ่ง แต่ไม่เกิน 10 ตัวแปร eeprom_var จะโต้ตอบกับ EEPROM เมื่อเปิดเครื่อง EEPROM จะถูกอ่านข้อมูลการอ่านจะถูกกำหนดให้กับตัวแปร "s" โดยอิงตามนี้ตัวเลขจำนวนหนึ่งจะปรากฏบนตัวบ่งชี้ เมื่อคุณกด SB2 ข้อมูลจากตัวแปร “s” จะถูกเขียนไปยัง EEPROM และตัวบ่งชี้จะกะพริบหนึ่งครั้ง

#รวม #รวม #รวม #define d0 ~(0x3F) // 0 #define d1 ~(0x06) // 1 #define d2 ~(0x5B) // 2 #define d3 ~(0x4F) // 3 #define d4 ~(0x66) // 4 #define d5 ~(0x6D) // 5 #define d6 ~(0x7D) // 6 #define d7 ~(0x07) // 7 #define d8 ~(0x7F) // 8 #define d9 ~(0x6F) // 9 ถ่านที่ไม่ได้ลงนาม; ถ่าน eeprom_var EEMEM ที่ไม่ได้ลงนาม; // กำหนดตัวแปรใน EEPROM int main (เป็นโมฆะ) ( DDRB = 0xFF; // พอร์ต B เพื่อเอาต์พุต PORTB = 0xFF; DDRD = 0x00; // พอร์ต D เพื่ออินพุต PORTD = 0xFF; // เปิดตัวต้านทานแบบดึงขึ้น s = eeprom_read_byte(&eeprom_var ); // อ่านไบต์จาก EEPROM แล้วใส่ไว้ใน "s" ในขณะที่(1) ( if((PIND&(1<< PD0)) == 0) // если кнопка SB1 нажата { while((PIND&(1 << PD0)) == 0){} // ждем отпускания кнопки s++; // увеличиваем "s" на единицу _delay_ms(200); } if(s == 10) // Когда дойдет до 10 обнуляем "s" { s = 0; } if((PIND&(1 << PD1)) == 0) // если кнопка SB2 нажата { while((PIND&(1 << PD1)) == 0){} // ждем отпускания кнопки DDRB = 0xFF; // мигаем индикатором _delay_ms(200); DDRB = 0x00; _delay_ms(200); DDRB = 0xFF; eeprom_write_byte(&eeprom_var, s); // записываем "s" в EEPROM _delay_ms(200); } if(s==0) // Выводим цифры на индикатор PORTB = d0; if(s==1) PORTB = d1; if(s==2) PORTB = d2; if(s==3) PORTB = d3; if(s==4) PORTB = d4; if(s==5) PORTB = d5; if(s==6) PORTB = d6; if(s==7) PORTB = d7; if(s==8) PORTB = d8; if(s==9) PORTB = d9; } }

ความคิดเห็น

0 แอนตันชิป 05/02/2556 22:15 น

ฉันพูดแม็กซ์:

บางทีฉันอาจสับสนบางอย่าง แต่ถ้าคุณมีตัวบ่งชี้ OA ตัวต้านทานหนึ่งตัวบนสาย 5V ก็เพียงพอแล้ว เหตุใดจึงติดตั้งตัวต้านทาน จำกัด กระแสหลังจากองค์ประกอบที่ควรป้องกันจากกระแสสูง??


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

0 แอนตันชิป 15/05/2556 11:16 น

ฉันพูด gydok:

จะเขียนอาร์เรย์สองมิติลงใน eeprom ได้อย่างไร?


รหัส:
#รวม // รวมห้องสมุดด้วย

EEMEM สีถ่านที่ไม่ได้ลงนาม=((1, 2, 3), // ประกาศอาร์เรย์ใน EEPROM
{4, 5, 6}};

eeprom_write_byte(&สี, 1); // เขียนองค์ประกอบอาร์เรย์ไปยัง EEPROM
eeprom_write_byte(&สี, 2);
eeprom_write_byte(&สี, 3);
eeprom_write_byte(&สี, 4);
eeprom_write_byte(&สี, 5);
eeprom_write_byte(&สี, 6);

อุณหภูมิถ่านที่ไม่ได้ลงนาม
อุณหภูมิ = eeprom_read_byte(&สี); // แยกองค์ประกอบอาร์เรย์จาก EEPROM แถวที่ 2() คอลัมน์ที่ 1() เช่น หมายเลข 4

การรีเซ็ตหน่วยความจำ EEPROM

ตัวอย่างจะวนซ้ำเซลล์หน่วยความจำทั้งหมดและเขียนค่าศูนย์ลงไป

// การเชื่อมต่อไลบรารีเพื่อทำงานกับ EEPROM #include "EEPROM.h" การตั้งค่าเป็นโมฆะ() ( // ผ่านเซลล์ทั้งหมด (ไบต์) แล้วเขียนค่าศูนย์ลงไป for (int i = 0; i< EEPROM.length(); i++) EEPROM.update(i, 0); } void loop() { // Пустой цикл... }


รีเซ็ตเป็นค่าจากโรงงาน

หากคุณต้องการคืนหน่วยความจำกลับเป็นการตั้งค่าจากโรงงาน คุณจะต้องแทนที่ 0 ด้วย 255 เช่น เขียนไม่ใช่ศูนย์ แต่เป็นตัวเลข 255 ดังนั้นในอนาคตเมื่อใช้ฟังก์ชัน isNaN() จึงสามารถตรวจสอบได้ว่ามีการเขียนลงในหน่วยความจำ EEPROM หรือไม่

// การเชื่อมต่อไลบรารีเพื่อทำงานกับ EEPROM #include "EEPROM.h" การตั้งค่าเป็นโมฆะ() ( // ตรวจดูทุกเซลล์ (ไบต์) แล้วเขียนตัวเลข 255 ลงไป for (int i = 0; i< EEPROM.length(); i++) EEPROM.update(i, 255); } void loop() { // Пустой цикл... }

บอกเราเกี่ยวกับเรา

ข้อความ

หากคุณมีประสบการณ์ในการทำงานกับ Arduino และมีเวลาสำหรับการสร้างสรรค์จริงๆ เราขอเชิญชวนให้ทุกคนมาเป็นผู้เขียนบทความที่เผยแพร่บนพอร์ทัลของเรา สิ่งเหล่านี้อาจเป็นบทเรียนหรือเรื่องราวเกี่ยวกับการทดลองกับ Arduino ก็ได้ คำอธิบายของเซ็นเซอร์และโมดูลต่างๆ เคล็ดลับและคำแนะนำสำหรับผู้เริ่มต้น เขียนและโพสต์บทความของคุณบน