ตอนที่ 9 วิธีอ่านและเขียน DATA EEPROM ใน 16F87X

 

ก่อนอื่นเรามาดูกันก่อนว่า PIC ในตระกูล PIC16F87X มีหน่วยความจำ DATA EEPROM เท่าไหร่กันบ้าง

ชนิดของ PIC

ขนาดหน่วยความจำ EEPROM

ตำแหน่ง Address ที่เข้าถึงได้

PIC16F870

64 bytes

0h – 3Fh

PIC16F871

64 bytes

0h – 3Fh

PIC16F872

64 bytes

0h - 3Fh

PIC16F873

128 bytes

0h – 7Fh

PIC16F874

128 bytes

0h – 7Fh

PIC16F876

256 bytes

0h – FFh

PIC16F877

256 bytes

0h – FFh

Register อะไรที่ต้องใช้ในการเขียน DATA EEPROM บ้าง

EEADR ในการอ้างตำแหน่ง address ของ DATA EEPROM ที่เราต้องการเขียน เราจะใส่ค่าตำแหน่ง address ที่เราต้องการเขียนเข้าไปที่ register ตัวนี้ เช่นถ้าเราการต้องเขียน DATA EEPROM ที่ตำแหน่ง 10h ก็ใช้คำสั่ง

movlw h’10’

movwf EEADR

EEDATA ในการบอกว่าเราค่า 1 byte ที่เราจะเขียนที่ DATA EERPOM มีค่าเท่าไหร่ เราจะใส่ค่าดังกล่าวไว้ที่ register ตัวนี้ เช่นถ้าเราต้องการเขียนข้อมูล 1 byte ซึ่งมีค่าเป็น h’7D’ ก็ใช้คำสั่ง

movlw h’7D’

movwf EEDATA

EECON1 เป็น register ที่ใช้ควบคุมการอ่านเขียน จะมี ขนาด 8 control bit จะอธิบายทีละบิตดังนี้

Bit No

คำอธิบาย

Bit 7 (ซ้ายสุด) EEPGD

ถ้าเป็น 1 หมายถึงว่าเราจะ อ่าน/เขียน PROGRAM EEPROM

ถ้าเป็น 0 หมายถึงเราจะ อ่าน/เขียน DATA EEPROM (ในตอนนี้เราจะให้บิตนี้เป็น 0 เพราะเราต้องการอ่าน/เขียน DATA EEPROM

Bit 6 – 4

ยังไม่ถูกใช้

Bit 3 (WRERR)

จะบอกสถานะการเขียน ข้อมูลเข้าไปใน EEPROM สำเร็จหรือไม่ ถ้าเป็น 1 แสดงว่าการเขียนที่ไบต์นั้นล้มเหลว แต่ถ้าเป็น 0 แสดงว่าการเขียนของเราสำเร็จ

Bit 2 (WREN)

เป็นบิตที่กำหนดว่าอนุญาตให้มีการเขียน DATA EEPROM หรือไม่

ถ้าเป็น 1 หมายถึง เรากำหนดให้สามารถเขียน DATA EEPROM

ถ้าเป็น 0 หมายถึง เรากำหนดไม่อนุญาตให้เขียน DATA EEPROM

Bit 1 (WR)

เป็นบิตควมคุมการเขียน คือก่อนที่เราจะทำการเขียน DATA EEPROM เราจะกำหนดบิตนี้ให้เป็น 1 เมื่อ PIC ทำการเขียน EEPROM เสร็จสิ้น ก็จะทำการ set บิตนี้ให้กลายเป็น 0 ทำให้เรารู้ว่าการเขียนนั้นเสร็จสิ้นแล้ว

Bit 0 (RD)

เป็นบิตควมคุมการอ่าน คือก่อนที่เราจะทำการอ่าน DATA EEPROM เราจะกำหนดบิตนี้ให้เป็น 1 เมื่อ PIC ทำการเขียน EEPROM เสร็จสิ้น ก็จะทำการ set บิตนี้ให้กลายเป็น 0 ทำให้เรารู้ว่าการอ่านเสร็จสิ้นแล้วเราสามารถดูข้อมูลที่เกิดจากการอ่านได้ที่ EEDATA

 

EECON2 จะใช้ในการเขียน DATA EEPROM คือหลังจากเราบอก ตำแหน่งและข้อมูลที่จะเขียนเรียบร้อยแล้ว เมื่อเราจะทำการเขียนเราจะส่ง ไบต์ 55 และ ตามด้วย AA ไปยัง EECON2 เมื่อ PIC ได้รับ sequence ของไบต์ 55, AA ก็จะทำการเขียนข้อมูลของเราไปยังตำแหน่งที่เรากำหนด (เดี๋ยวจะอธิบายใน code จะเข้าใจได้มากกว่า)

อีกอย่างที่ต้องอธิบาย คือตำแหน่งของ Register เหล่านี้

EEDATA (address 10Ch) memory อยู่ที่ Bank2

EEADR (address 10Dh) memory อยู่ที่ Bank2

EECON1 (address 18Ch) memory อยู่ที่ Bank3

EECON2 (address 18Dh) memory อยู่ที่ Bank3

สังเกตได้ว่า register จะอยู่คนละ bank ดังนั้นเวลาจะใส่ค่าลงใน register พวกนี้จะมีการเขียน code สลับ bank ไปมาให้สังเกตดีๆ

การอ่าน DATA EEPROM

BSF STATUS, RP1 ; เนื่องจาก EEADR อยู่ที่ Bank2 เราต้องเปลี่ยน bank memory ไปอยู่ที่

BCF STATUS, RP0 ; bank2 ก่อน

MOVLW h’15’ ; ในที่นี้เราจะอ่าน DATA EEPROM ที่ตำแหน่ง 15h

MOVWF EEADR ; ดังนั้นใส่ค่า h’15’ ลงใน EEADR register

BSF STATUS, RP0 ; เปลี่ยน เป็น Bank 3 เพราะเราจะเขียนค่า EECON1

BCF EECON1, EEPGD ; clear EEPGD bit บอกว่าเราจะอ่าน/เขียน DATA EEPROM

BSF EECON1, RD ; set RD bit เป็น 1 เพราะเมื่อ pic อ่าน DATA EEPROM เสร็จก็จะ

; clear เป็น 0 ซึ่งเราจะได้เอาไว้คอยตรวจสอบว่าอ่านเสร็จหรือยัง

Wait_RD: ; รอจนกว่า EECON1,RD จะ clear ซึ่งแสดงว่าอ่านเสร็จแล้ว

BTFSC EECON1,RD ; *** รูปแบบนี้ไม่ดีนักเพราะอาจจะเกิดอาการวนลูปโดยไม่รู้จบ

GOTO Wait_RD ; แต่เพื่อสร้างความเข้าใจในการเขียนจึงเขียนแบบง่ายๆก่อน

BCF STATUS, RP0 ; กลับไปที่ Bank 2 เพื่อทำการอ่านข้อมูลจาก EEDATA register

MOVFW EEDATA ; ตอนนี้เราได้ข้อมูลมาอยู่ที่ w register เรียบร้อยแล้ว

การเขียน DATA EEPROM

BSF STATUS, RP1 ; เนื่องจาก EEADR อยู่ที่ Bank2 เราต้องเปลี่ยน bank memory ไปอยู่ที่

BCF STATUS, RP0 ; bank2 ก่อน

MOVLW h’5’ ; ในที่นี้เราจะเขียน DATA EEPROM ที่ตำแหน่ง 5h

MOVWF EEADR ; ดังนั้นใส่ค่า h’5’ ลงใน EEADR register

MOVLW h’30’ ; สมมติค่าที่เราจะเขียน เป็น h’30’

MOVWF EEDATA ; ใส่ค่า h’30’ ลงใน EEDATA

BSF STATUS, RP0 ; เปลี่ยน เป็น Bank 3 เพราะเราจะเขียนค่า EECON1

BCF EECON1, EEPGD ; clear EEPGD bit บอกว่าเราจะอ่าน/เขียน DATA EEPROM

BSF EECON1, WREN ; set WREN bit บอกว่าอนุญาตให้เขียน DATA EEPROM ได้

BCF INTCON, GIE ; Disable Interrupt ( Microchip เค้าแนะนำไว้ )

MOVLW h’55’ ; เขียน sequence 55h,AAh เข้าไปยัง EECON2 เพื่อสั่งให้

MOVWF EECON2 ; pic เขียนข้อมูลใน EEDATA ลงใน DATA EEPROM ที่

MOVLW h’AA’ ; ตำแหน่งตามค่า EEADR

MOVWF EECON2 ; Write AAh

BSF EECON1, WR ; Set WR bit เพื่อเริ่มการเขียน

BSF INTCON, GIE ; ให้ Enable Interrupts เหมือนเดิม

(วิธีที่ 1) เราจะใช้วิธี ตรวจสอบ EECON1,WR flag

Wait_WR: ; รอจนกว่า EECON1,WD จะ clear ซึ่งแสดงว่าเขียนเสร็จแล้ว

BTFSC EECON1,WR ; *** รูปแบบนี้ไม่ดีนักเพราะอาจจะเกิดอาการวนลูปโดยไม่รู้จบ

GOTO Wait_WR ; แต่เพื่อสร้างความเข้าใจในการเขียนจึงเขียนแบบง่ายๆก่อน

BCF EECON1, WREN ; กำหนดไม่ให้เขียน EEPROM

(วิธีที่ 2) หรือตรวจสอบ PIR2,EEIF flag ซึ่งจะเป็น interrupt flag โดยจะ set เมื่อเขียน DATA EEPROM เสร็จเรียบร้อย

BCF STATUS, RP1 ; เนื่องจาก PIR2 อยู่ที่ Bank0 เราต้องเปลี่ยน bank memory BCF STATUS, RP0 ; ไปอยู่ที่ Bank0 ก่อน

Wait_WR: ; รอจนกว่า PIR2,EEIF จะ set ซึ่งแสดงว่าเขียนเสร็จแล้ว

BTFSS PIR2,EEIF ; *** รูปแบบนี้ไม่ดีนักเพราะอาจจะเกิดอาการวนลูปโดยไม่รู้จบ

GOTO Wait_WR ; แต่เพื่อสร้างความเข้าใจในการเขียนจึงเขียนแบบง่ายๆก่อน

BCF PIR2,EEIF ; Clear flag ทิ้ง

BSF STATUS, RP1 ; เนื่องจาก EECON1 อยู่ที่ Bank3 เราต้องเปลี่ยน bank

BSF STATUS, RP0 ; memory ไปอยู่ bank3 ก่อน

BCF EECON1, WREN ; กำหนดไม่ให้เขียน EEPROM

เอาหล่ะครับ Code ข้างบนนี่ก็เป็นการอธิบายแบบเบื้องต้นเลยครับ ใครที่เป็นเซียนแล้วก็ขออภัยด้วยนะครับที่อธิบายซะเยิ้นเย้อ จาก code ข้างบนนี้ ผมได้เขียน project ตัวอย่าง ขึ้นมาให้แล้วสามารถ download ได้ที่ pic source code นะครับ ผมทำไว้ให้ download แล้ว แต่ดัดแปลงไปนิดหน่อย เพื่อให้ใช้งานได้จริงๆ คือ เขียนเป็น module read/write เวลาจะใช้ก็ส่งค่า data กับ address ที่เราต้องการเขียน โดยผ่านตัวแปรไปให้ module เพื่อจัดการให้เรา มือใหม่ๆ ลองทำความเข้าใจดูนะครับ ถ้าสงสัยก็เมล์มาถามหรือ post ไว้ที่ webboard ก็ได้

หมายเหตุ ( ตรงนี้สำคัญนะครับ อ่านให้ละเอียด )

  1. เวลาลองให้ลองเป็น simulator mode จะดีกว่าครับเพราะ อย่างแรก ประหยัดจำนวนครั้งในการ program ครับ เพราะตัว flash เองก็มีอายุการโปรแกรมเหมือนกันครับ (จำไม่ได้ว่ากี่ครั้ง) แล้วก็ไม่ต้องต่อ hardware ด้วยครับ แล้วพอลองได้จริงแล้ว ค่อยใช้ MPLAB-ICD อีกทีก็ได้ครับ
  2. เวลาใช้ MPLAB-ICD ในการ Read/Write EEPROM ไม่สามารถ RUN single step ในช่วงการเขียน EEROM ได้นะครับ ถ้าจะหยุดก็ต้องไป set break point หลัง code ทำการเขียน EEPROM เสร็จแล้ว
  3. ตอนที่ผมทดลอง module Read/Write EEPROM ด้วย MPLAB-ICD (V5.4) ปรากฏว่า ในการอ่านหรือเขียน EEPROM เจ้า EEPROM desktop มันไม่ยอม update เล่นเอางงซะนานว่าทำไมเขียนไม่เข้า ทั้งๆที่ตอน simulate ก็ใช้ได้ ผมก็เลยใช้วิธีเขียนเข้าไปแล้วอ่านกลับมาปรากฏว่าข้อมูลตรงกัน ก็ไม่รู้ว่าเป็น bug หรือปล่าว (V5.31 ก็เป็นครับ) ทั้งที่เมื่อก่อนสมัยผมใช้ V5.11 มัน update ให้ ดังนั้นเวลาเพื่อนๆ ลองทดลองดู แล้วเป็นเหมือนผม หรือมีวิธีแก้อย่างไร ที่ผมไม่ทราบก็ช่วยบอกกันด้วยนะครับ เดี๋ยวผมคงจะ mail ไปถามทาง microchip ดู
  4. จบแล้วครับ

 

 

BACK