การทดลองที่ 3 เทคนิคการเก็บข้อมูล Long, Float ลง EEPROM ด้วยวิธี UNION

การเก็บข้อมูลที่มีขนาดมากกว่า 1 Byte เราสามารถทำได้ประมาณ 3 วิธี

1. ทำการแบ่ง Byte ข้อมูลเป็นส่วนๆ ด้วยการหารเช่นกรณี unsigned int ถ้าเราหารด้วย 256 ก็จะได้ตัวแปร Byte High ถ้าเรา mod ด้วย 256 ก็จะได้ตัวแปร Byte Low จากนั้นก็เอาตัวแปรแต่ละตัวไปเก็บไว้ใน EEPROM วิธีนี้จะเสีย CYCLE ในการประมวลผลไปเปล่าๆ

2. ใช้ Pointer เราประกาศ Pointer เป็น char แล้วก็เลื่อน Pointer ไปทีละ 1 ไบต์ก็จะได้ตัวแปรแต่ละไบต์

3. ใช้ UNION วิธีนี้เป็นวิธีที่ผมใช้บ่อย ก่อนที่จะอธิบายการจัดเก็บ ผมขออธิบาย UNION ก่อนว่า UNION คืออะไร

UNION เป็นการประกาศตัวแปรที่ใช้หน่วยความจำร่วมกัน ตัวแปรที่ประกาศแบบ UNION จะมีหน่วยความจำอยู่ตำแหน่งทับกันหมดทุุกตัว เช่นตัวอย่างตัวแปร Dat_long.word ใช้ตำแหน่งหน่วยความจำเดียวกัน การแก้ไขตัวแปร Dat_long.word ก็จะมีผลกับตัวแปร Dat_long.byte[0-3]

รูปที่ 1 memory จากการใช้คำสั่ง UNION

รูปที่ 2 Schematic ที่ใช้ในการทดลอง 3

การประยุกต์ใช้งานกับหน่วยความจำ เพียงย้ายข้อมูลมาไว้ Float, long แล้ว เอาข้อมูลจากตัวแปร์ array มาเก็บไว้ใน EEPROM

//***************************************************************************//
//Project : union.mcp
//Description : Union
//Device : PIC16F873A
//By : ThaiEmbedded 2006
//Date : 25 Nov 2006
//***************************************************************************//#include <pic.h>
#include <stdio.h>
#include <stdlib.h>

__CONFIG(XT & WDTDIS & PWRTEN & BORDIS & LVPDIS & DEBUGDIS & UNPROTECT);

long ee_buff[2];

union dat_long
{
unsigned char byte[4];
long word;
}Dat_long;
union dat_long Dat_long;
//——————————————————————————//
// Delay (mSec)
//——————————————————————————//
void dmsec (unsigned int Count)
{

unsigned char i;
while (Count)
{
for (i=0;i<=100;i++);
Count–;
}
}
//——————————————————————————//
// Main Program
//——————————————————————————//
void main ()
{
dmsec(200);
TRISB = 0b00000000; //Output mode

ee_buff[0] = 123456;
Dat_long.word = ee_buff[0];
EEPROM_WRITE(0, Dat_long.byte[0]);
EEPROM_WRITE(1, Dat_long.byte[1]);
EEPROM_WRITE(2, Dat_long.byte[2]);
EEPROM_WRITE(3, Dat_long.byte[3]);

dmsec(200);
Dat_long.word = 0;

Dat_long.byte[0] = EEPROM_READ(0);
Dat_long.byte[1] = EEPROM_READ(1);
Dat_long.byte[2] = EEPROM_READ(2);
Dat_long.byte[3] = EEPROM_READ(3);

ee_buff[1] = Dat_long.word;

if(ee_buff[0]==ee_buff[1])
PORTB = 1;
else
PORTB = 3;

while(1); //Loop Forever
}

แบบฝึกหัด

ลองเปลี่ยนตัวแปรจาก Long เป็น float ลอง Compile ดูว่า ให้ผลลัพท์เหมือนเดิมไหม

Download Code การทดลองที่ 3

การทดลองที่ 1 I/O Port 16F87X

???????พอร์ตของ PIC16F877 จะประกอบด้วย PORTA, PORTB, PORTC, PORTD และพอร์ตของ PIC16F873 จะประกอบด้วย PORTA, PORTB, PORTC ในแต่ละพอร์ตนอกจากจะเป็น Digital I/O ปกติแล้วบางพอร์ตยังทำงานเป็น analog อินพุต ได้ด้วย ก่อนการใช้งานต้อง config พอร์ตก่อน

หลังจาก Power on Reset แล้วโดยปกติแล้ว PORTA จะกำหนดให้เป็นโหมด Analog

??????โครงสร้างพอร์ตของ PIC จะต่างจาก MCS-51 ตรงที่มี Register ที่กำหนดทิศทางของข้อมูลว่าเป็นอินพุตหรือเอาต์พุต หรือเรียกว่า TRIS Register เช่น TRISA

??????ในการ Compile จะให้ไฟล์เอ้าพุตออกมา อาจจะอยู่ในนามสกุล COF หรือ HEX ให้เข้าไปกำหนดให้เป็น HEX ก่อนโดยการกด Project –> Build Options… –> Project –> Restore Defaults

รูปที่ 1

?

??????ตอนแรกผมกะว่าจะใช้้บอร์ดของ ETT ตัวนี้โปรแกรมผ่าน Parallel Port แต่ Port ผมพัง ผมเลยใช้วิธีถอด IC มาโปรแกรมเอา แล้วทีนี้เกิดการผิดพลาดใส่เจ้า 16F877A กลับด้าน มันเลยลาโลกไปซะ ผมเคยต่อไมโครคอนโทรลเลอร์ของ ATMEL พวก 89C52 และ AVR เวลาต่อกลับขั้ว IC มันก็ร้อนๆนะ แต่ไม่ถึงกับพัง พอมาใช้ PIC + ความสะเพร่าของผม ต่อกลับด้านพังไปหลายตัวแล้ว

??????ผมเลยหาเบอร์ตระกูล 16F87X ที่พอมีอยู่ ก็มี 16F873A น่าจะพอแก้ขัดกันได้ ใครจะใช้ 16F877 ก็เปลี่ยน Device ใน MPLAB ได้เลยนะครับ

รูปที่ 2 บอร์ดทดลอง CP-PIC877 V2.0 ของ ETT

รูปที่ 3 ทำการทดลองใน Proto board

รูปที่ 4 Schematic ที่ใช้ในการทดลอง

สำหรับตัวโหลดที่ใช้ในการทดลองผมทำขึ้นมาเองครับ ผมจะเอาตัวโหลดเสียบที่ Target Board แล้วทำการโปรแกรมผ่านทาง ICD2??

การทดลองนี้เราจะเขียน Code ให้ LED ที่ต่อยู่กับ PORTB ติดเรียงกันไปจาก

ในส่วนของค่า Configure ใน MPLAB เนื่องจากเรากำหนดไว้ใน code แล้ว

บรรทัดนี้ __CONFIG(XT & WDTDIS & PWRTEN & BORDIS & LVPDIS & DEBUGDIS & UNPROTECT);

เราจึงไม่ต้อง Configure ใน MPLAB อีก

//****************************************************************//
//Project : first873.mcp
//Description : I/O Port
//Device : PIC16F873A
//By : ThaiEmbedded 2006
//****************************************************************//

#include <pic.h>
#include <stdio.h>
#include <stdlib.h>

__CONFIG(XT & WDTDIS & PWRTEN & BORDIS & LVPDIS & DEBUGDIS & UNPROTECT);

unsigned char i;
unsigned char dat;
//——————————————————————————//
// Delay (mSec)
//——————————————————————————//
void dmsec (unsigned int Count)
{ unsigned char i;
????? while (Count)
????? {
????? ????? for (i=0;i<=100;i++);
????? ????? Count–;
????? }
}
//——————————————————————————//
// Main Program
//——————————————————————————//
void main ()
{
?????TRISB = 0b00000000; //Output mode
????? while(1) //Loop Forever
????? {
?????????? dat = 0×01;
?????????? for(i=0;i<8;i++)
?????????? {
?????????? ????PORTB = dat;
????? ????? ???dat <<= 1;
????? ????? ???dmsec(500);
?????????? }
????? }
}

Download Code การทดลองที่ 1

การทดลองที่ 3 เทคนิคการเก็บข้อมูล Long, Float ลง EEPROM ด้วยวิธี UNION

การเก็บข้อมูลที่มีขนาดมากกว่า 1 Byte เราสามารถทำได้ประมาณ 3 วิธี

1. ทำการแบ่ง Byte ข้อมูลเป็นส่วนๆ ด้วยการหารเช่นกรณี unsigned int ถ้าเราหารด้วย 256 ก็จะได้ตัวแปร Byte High ถ้าเรา mod ด้วย 256 ก็จะได้ตัวแปร Byte Low จากนั้นก็เอาตัวแปรแต่ละตัวไปเก็บไว้ใน EEPROM วิธีนี้จะเสีย CYCLE ในการประมวลผลไปเปล่าๆ

2. ใช้ Pointer เราประกาศ Pointer เป็น char แล้วก็เลื่อน Pointer ไปทีละ 1 ไบต์ก็จะได้ตัวแปรแต่ละไบต์

3. ใช้ UNION วิธีนี้เป็นวิธีที่ผมใช้บ่อย ก่อนที่จะอธิบายการจัดเก็บ ผมขออธิบาย UNION ก่อนว่า UNION คืออะไร

UNION เป็นการประกาศตัวแปรที่ใช้หน่วยความจำร่วมกัน ตัวแปรที่ประกาศแบบ UNION จะมีหน่วยความจำอยู่ตำแหน่งทับกันหมดทุุกตัว เช่นตัวอย่างตัวแปร Dat_long.word ใช้ตำแหน่งหน่วยความจำเดียวกัน การแก้ไขตัวแปร Dat_long.word ก็จะมีผลกับตัวแปร Dat_long.byte[0-3]

รูปที่ 1 memory จากการใช้คำสั่ง UNION

รูปที่ 2 Schematic ที่ใช้ในการทดลอง 3

การประยุกต์ใช้งานกับหน่วยความจำ เพียงย้ายข้อมูลมาไว้ Float, long แล้ว เอาข้อมูลจากตัวแปร์ array มาเก็บไว้ใน EEPROM

//*******************************************************************//
//Project : union.mcp
//Description : Union
//Device : PIC16F873A
//By : ThaiEmbedded 2006
//Date : 25 Nov 2006
//*******************************************************************//

#include <pic.h>
#include <stdio.h>
#include <stdlib.h>

__CONFIG(XT & WDTDIS & PWRTEN & BORDIS & LVPDIS & DEBUGDIS & UNPROTECT);

long ee_buff[2];

union dat_long
{
?????unsigned char byte[4];
?????long word;
}Dat_long;
union dat_long Dat_long;
//——————————————————————————//
// Delay (mSec)
//——————————————————————————//
void dmsec (unsigned int Count)
{?????

?????unsigned char i;
?????while (Count)
?????{
??????????for (i=0;i<=100;i++);
??????????Count–;
?????}
}
//——————————————————————————//
// Main Program
//——————————————————————————//
void main ()
{
?????dmsec(200);
?????TRISB = 0b00000000; //Output mode

?????ee_buff[0] = 123456;
?????Dat_long.word = ee_buff[0];
?????EEPROM_WRITE(0, Dat_long.byte[0]);
?????EEPROM_WRITE(1, Dat_long.byte[1]);
?????EEPROM_WRITE(2, Dat_long.byte[2]);
?????EEPROM_WRITE(3, Dat_long.byte[3]);

?????dmsec(200);
?????Dat_long.word = 0;

?????Dat_long.byte[0] = EEPROM_READ(0);
?????Dat_long.byte[1] = EEPROM_READ(1);
?????Dat_long.byte[2] = EEPROM_READ(2);
?????Dat_long.byte[3] = EEPROM_READ(3);

?????ee_buff[1] = Dat_long.word;

?????if(ee_buff[0]==ee_buff[1])
??????????PORTB = 1;
?????else
??????????PORTB = 3;

?????while(1); //Loop Forever????????
}

?

แบบฝึกหัด

ลองเปลี่ยนตัวแปรจาก Long เป็น float ลอง Compile ดูว่า ให้ผลลัพท์เหมือนเดิมไหม

Download Code การทดลองที่ 3