ตอนที่ 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 h10
movwf EEADR
EEDATA ในการบอกว่าเราค่า 1 byte ที่เราจะเขียนที่ DATA EERPOM มีค่าเท่าไหร่ เราจะใส่ค่าดังกล่าวไว้ที่ register ตัวนี้ เช่นถ้าเราต้องการเขียนข้อมูล 1 byte ซึ่งมีค่าเป็น h7D ก็ใช้คำสั่ง
movlw h7D
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 h15 ; ในที่นี้เราจะอ่าน DATA EEPROM ที่ตำแหน่ง 15h
MOVWF EEADR ; ดังนั้นใส่ค่า h15 ลงใน 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 เสร็จก็จะ
Wait_RD: ; รอจนกว่า EECON1,RD จะ clear ซึ่งแสดงว่าอ่านเสร็จแล้ว
BTFSC EECON1,RD ; *** รูปแบบนี้ไม่ดีนักเพราะอาจจะเกิดอาการวนลูปโดยไม่รู้จบ
GOTO Wait_RD ; แต่เพื่อสร้างความเข้าใจในการเขียนจึงเขียนแบบง่ายๆก่อน
BCF STATUS, RP0 ; กลับไปที่ Bank 2 เพื่อทำการอ่านข้อมูลจาก EEDATA register
MOVFW EEDATA ; ตอนนี้เราได้ข้อมูลมาอยู่ที่ w register เรียบร้อยแล้ว
BSF STATUS, RP1 ; เนื่องจาก EEADR อยู่ที่ Bank2 เราต้องเปลี่ยน bank memory ไปอยู่ที่
BCF STATUS, RP0 ; bank2 ก่อน
MOVLW h5 ; ในที่นี้เราจะเขียน DATA EEPROM ที่ตำแหน่ง 5h
MOVWF EEADR ; ดังนั้นใส่ค่า h5 ลงใน EEADR register
MOVLW h30 ; สมมติค่าที่เราจะเขียน เป็น h30
MOVWF EEDATA ; ใส่ค่า h30 ลงใน 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 h55 ; เขียน sequence 55h,AAh เข้าไปยัง EECON2 เพื่อสั่งให้
MOVWF EECON2 ; pic เขียนข้อมูลใน EEDATA ลงใน DATA EEPROM ที่
MOVLW hAA ; ตำแหน่งตามค่า 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 ; แต่เพื่อสร้างความเข้าใจในการเขียนจึงเขียนแบบง่ายๆก่อน
(วิธีที่ 2) หรือตรวจสอบ PIR2,EEIF flag ซึ่งจะเป็น interrupt flag โดยจะ set เมื่อเขียน DATA EEPROM เสร็จเรียบร้อย
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 ก็ได้
หมายเหตุ ( ตรงนี้สำคัญนะครับ อ่านให้ละเอียด )