พฤศจิกายน 21, 2019, 11:22:21 am *
ยินดีต้อนรับคุณ, บุคคลทั่วไป กรุณา เข้าสู่ระบบ หรือ ลงทะเบียน
ส่งอีเมล์ยืนยันการใช้งาน?

เข้าสู่ระบบด้วยชื่อผู้ใช้ รหัสผ่าน และระยะเวลาในเซสชั่น
   หน้าแรก   ช่วยเหลือ เข้าสู่ระบบ สมัครสมาชิก  
หน้า: [1] 2   ลงล่าง
  พิมพ์  
ผู้เขียน หัวข้อ: ตอนนี้ผมมี EEPROM 24LC512 ต่ออยู่กับ ARM LPC1756 ไม่ทราบว่าจะเขียนโปรแกรม เขียนอ่าน ยังไงครับ  (อ่าน 17353 ครั้ง)
0 สมาชิก และ 1 บุคคลทั่วไป กำลังดูหัวข้อนี้
anon1206
Newbie
*
ออฟไลน์ ออฟไลน์

กระทู้: 30


| |
« เมื่อ: พฤษภาคม 22, 2013, 04:42:54 pm »

ตอนนี้ผมมี EEPROM 24LC512 ต่ออยู่กับ ARM LPC1756 ไม่ทราบว่าจะเขียนโปรแกรม เขียนอ่าน ยังไงครับ มี Library ให้ใช้ไหมครับ (ใช้  Keil ครับ)

วงจรตามรูปครับ
SCL ต่อขา P0.1
SCD ต่อขา P0.0

บันทึกการเข้า
ShadowMan
Administrator
Hero Member
*****
ออฟไลน์ ออฟไลน์

เพศ: ชาย
กระทู้: 8272


ShadowWares


| |
« ตอบ #1 เมื่อ: พฤษภาคม 23, 2013, 08:40:58 am »

อ้างถึง
ตอนนี้ผมมี EEPROM 24LC512 ต่ออยู่กับ ARM LPC1756 ไม่ทราบว่าจะเขียนโปรแกรม เขียนอ่าน ยังไงครับ
ส่วนนี้ตอบลำบากครับ แต่มีสองสิ่งที่คุณในฐานะคนเขียนโปรแกรมต้องรู้คือ I2C Protocol ว่าด้วย 24LC512 และการเขียนโปรแกรมใช้งาน I2C Module ของ ARM LPC1756 (หากไม่ใช้ Module สามารถเขียนโปรแกรมสร้างลอจิกของ SDA และ SCL เองได้)

อ้างถึง
มี Library ให้ใช้ไหมครับ (ใช้  Keil ครับ)
คิดว่ามี ลองเข้าไปหา Application Note ใน NXP ดูครับ แต่คิดว่าคงไม่ใช่ Library ที่สร้างมาสำหรับ LPC1756 และ 24LC512 โดยตรง อย่างไรก็ตามสามารนำมาใช้เป็นแนวทางได้
บันทึกการเข้า

By SDW: Do No Wrong Is Do Nothing
          If you want to increase your success rate, double your failure rate
anon1206
Newbie
*
ออฟไลน์ ออฟไลน์

กระทู้: 30


| |
« ตอบ #2 เมื่อ: มิถุนายน 05, 2013, 11:23:39 am »

ตอนนี้ผม เขียนโปรแกรมสร้างลอจิกของ SDA และ SCL เอง
แต่ทำไมตรงที่เป็นตัวแปรแบบบิต ERROR ทุกตัวเลยครับ

เช่นในฟังก์ชันเขียนข้อมูล
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bit I2C_write(unsigned char dat)
{
   bit data_bit;      
   unsigned char i;   

   for(i=0;i<8;i++)            /* For loop 8 time(send data 1 byte) */
   {
      data_bit = dat & 0x80;      /* Filter MSB bit keep to data_bit */
      SDA = data_bit;            /* Send data_bit to SDA */
      I2C_clock();               /* Call for send data to i2c bus */
      dat = dat<<1;  
   }

   LPC_GPIO0->FIOSET = SDA ; //SDA = 1;         /* Set SDA */
   I2C_delay();      
   LPC_GPIO0->FIOSET = SCL ; //SCL = 1;         /* Set SCL */
   I2C_delay();

   data_bit = SDA;      /* Check acknowledge */
   LPC_GPIO0->FIOCLR  = SCL; //SCL = 0;         /* Clear SCL */
   I2C_delay();
   return data_bit;   /* If send_bit = 0 i2c is valid */          
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
จุดที่เป็นสีแดงจะขึ้น error
error:  #20: identifier "bit" is undefined
ทุกตัวเลยครับ เกิดจากอะไรครับจะประกาศตัวแปรแบบบิตต้องประกาศอะไรก่อนหรือป่าว
บันทึกการเข้า
ShadowMan
Administrator
Hero Member
*****
ออฟไลน์ ออฟไลน์

เพศ: ชาย
กระทู้: 8272


ShadowWares


| |
« ตอบ #3 เมื่อ: มิถุนายน 05, 2013, 01:11:36 pm »

"bit" ไม่ได้รองรับกับ compiler ทุกตัว
ตรวจสอบดูให้ดีว่า code ที่คุณลอกเขามา เขาใช้เครื่องมือตัวเดียวกันกับคุณจริงหรือไม่
ในเบื้องต้น ให้เปลี่ยน "bit" เป็นชนิดอื่นได้ (และอาจจะต้องปรับปุง code เล็กน้อย)
บันทึกการเข้า

By SDW: Do No Wrong Is Do Nothing
          If you want to increase your success rate, double your failure rate
anon1206
Newbie
*
ออฟไลน์ ออฟไลน์

กระทู้: 30


| |
« ตอบ #4 เมื่อ: มิถุนายน 06, 2013, 08:55:14 pm »

สอบถามในส่วนของ A0 A1 A2 หน่อยครับ ว่า บางวงจรต่อ GND หมด บางวงจรต่อ VCC ที่ A1 ต่างกันยังไงครับ
อย่างเช่นวงจรของผมต่อที่ A1 หมายถึงอะไรครับ

บันทึกการเข้า
วิสิทธิ์ แผ้วกระโทก
Global Moderator
Sr. Member
*****
ออฟไลน์ ออฟไลน์

กระทู้: 307



| |
« ตอบ #5 เมื่อ: มิถุนายน 06, 2013, 09:42:55 pm »

เป็นการกำหนด Chip select bit ของตัว 24LC512 ในกรณีที่คุณต่อมากกว่า 1 ตัว ในวงจรเดียวกัน และอยู่บนเส้นทางเดินสัญญาณ (Bus) เดียวกัน
จะต้องมีตัวบอกให้รู้ ว่าแต่ละตัว ต่างกันอย่างไร นั่นก็คือ กำหนดผ่าน A0,A1,A2 

การต่อเข้ากับ VCC เราจะได้ Logic 1
ต่อเข้า GND เราจะได้ Logic 0

เพราะฉะนั้น ถ้าเราต่อลง GND หมด เราจะได้ Chip select bit = 000

นั่นก็แปลว่า ตอนเราส่ง Control Byte เราต้องส่ง S 1 0 1 0 A2 A1 A0 1 เท่ากับ S 1 0 1 0 0 0 0 1

ลองอ่านดูในดาต้าชีท แล้วเทียบก้ับโค๊ดที่เราเขียนอยู่ครับ
บันทึกการเข้า

anon1206
Newbie
*
ออฟไลน์ ออฟไลน์

กระทู้: 30


| |
« ตอบ #6 เมื่อ: มิถุนายน 07, 2013, 12:30:39 am »

อยู่บนเส้นทางเดินสัญญาณ (Bus) เดียวกัน
อยู่บนเส้นทางเดินสัญญาณ (Bus) เดียวกัน หมายรวมถึงอุปกรณ์ที่ใช้การสื่อสารแบบ I2C ทั้งหมดใช่ไหมครับ

เพราะวงจรผมมี 24LC512 อยู่เพียงตัวเดียว แต่มีอุปกรณ์ที่สื่อสารแบบ I2C อีกตัวคือ DS1307 ซึ่งใช้สาย SCL SDA ตัวเดียวกัน

ผมเข้าใจถูกต้องไหมครับ  shy
บันทึกการเข้า
วิสิทธิ์ แผ้วกระโทก
Global Moderator
Sr. Member
*****
ออฟไลน์ ออฟไลน์

กระทู้: 307



| |
« ตอบ #7 เมื่อ: มิถุนายน 07, 2013, 08:41:43 am »

เข้าใจถูกต้องแล้วครับ


บันทึกการเข้า

anon1206
Newbie
*
ออฟไลน์ ออฟไลน์

กระทู้: 30


| |
« ตอบ #8 เมื่อ: มิถุนายน 07, 2013, 01:40:48 pm »

ตอนนี้ผมใช้ Keil เป็น Compiler ซึ่งไม่สามารถใช้ตัวแปรบบิต(bit) ได้
ผมจึงทำการเป็นจากตัวแปร bit เป็น  char ตามโค้ดครับ
eeprom ใช้ 24LC512 Address But อยู่ที่ 010 คือ S 1 0 1 0 A2 A1 A0 0 = 0xA4


ฟังก์ชัน I2C_write แบบเดิมที่ใช้ตัวแปรบิตไม่ได้
Code:
bit I2C_write(unsigned char dat)
{
   bit data_bit;      
   unsigned char i;  

   for(i=0;i<8;i++)          
   {
      data_bit = dat & 0x80;    
      SDA = data_bit;          
      I2C_clock();              
      dat = dat<<1;  
   }

   LPC_GPIO0->FIOSET = SDA ; //SDA = 1;        
   I2C_delay();      
   LPC_GPIO0->FIOSET = SCL ; //SCL = 1;        
   I2C_delay();

   data_bit = SDA;      /* Check acknowledge */
   LPC_GPIO0->FIOCLR  = SCL; //SCL = 0;         /* Clear SCL */
   I2C_delay();
   return data_bit;   /* If send_bit = 0 i2c is valid */          
}

ฟังก์ชัน I2C_write ที่แก้โดยเปลี่ยน bit เป็น  char
Code:
char I2C_write(unsigned char dat)
{
char data_bit;
unsigned char i;

for(i=0;i<8;i++)
{
data_bit = dat & 0x80;
if(data_bit== 0x80)                                  //  if(data_bit == 1) SDA = 1;
LPC_GPIO0->FIOSET = SDA ; //  
else                                                  //   else  SDA = 0;
LPC_GPIO0->FIOCLR = SDA ;        //
I2C_clock();  
dat = dat<<1;  
}
LPC_GPIO0->FIOSET = SDA ; //SDA = 1;
I2C_delay();
LPC_GPIO0->FIOSET = SCL ; //SCL = 1;
I2C_delay();

data_bit = SDA;   /* Check acknowledge */
LPC_GPIO0->FIOCLR  = SCL; //SCL = 0;
I2C_delay();
if(data_bit == 1)
      UART0_SENT_DATA("ERROR..TT ",10);  // ถ้า data_bit = 1 แสดงว่าเกิดการผิดพลาด
else
check_wr = 1;
}

ผมอยากถามว่าฟังก์ชันที่ผมแก้จะสามารถใช้งานได้ไหมครับ
เพราะผมลองให้โปรแกรมเช็คค่า data_bit ถ้าเป็น 1 จะ ERROR
โดยการส่ง ออกทาง serial port uart0 ไปแสดงบน HyperTerminal จะแสดงค่า ERROR ตลอดเลยครับ


โค้ดในส่วน I2C_clock,i2c_start,i2c_stop และ I2C_write
Code:
void I2C_clock(void)
{
I2C_delay();
LPC_GPIO0->FIOSET = SCL ; //SCL = 1;
I2C_delay();  
LPC_GPIO0->FIOCLR  = SCL; //  SCL = 0;
}
void I2C_start(void)
{
if(SCL)
LPC_GPIO0->FIOCLR  = SCL; //   SCL = 0;
LPC_GPIO0->FIOSET = SDA ; //SDA = 1;        
LPC_GPIO0->FIOSET = SCL ; //SCL = 1;
I2C_delay();
LPC_GPIO0->FIOCLR = SDA ; //SDA = 0;
I2C_delay();
LPC_GPIO0->FIOCLR  = SCL; // SCL = 0;        
}

void I2C_stop(void)
{
if(SCL)
LPC_GPIO0->FIOCLR  = SCL; //SCL = 0;
LPC_GPIO0->FIOCLR = SDA ; //SDA = 0;
I2C_delay();
LPC_GPIO0->FIOSET = SCL ; //SCL = 1;
I2C_delay();
LPC_GPIO0->FIOSET = SDA ; //SDA = 1;
}

char I2C_write(unsigned char dat)
{
char data_bit;
unsigned char i;

for(i=0;i<8;i++) /* For loop 8 time(send data 1 byte) */
{
data_bit = dat & 0x80;
//SDA = data_bit; /* Filter MSB bit keep to data_bit */
if(data_bit== 0x80)
LPC_GPIO0->FIOSET = SDA ; /* Send data_bit to SDA */
else
LPC_GPIO0->FIOCLR = SDA ;
I2C_clock();
dat = dat<<1;  
}

LPC_GPIO0->FIOSET = SDA ; //SDA = 1;
I2C_delay();
LPC_GPIO0->FIOSET = SCL ; //SCL = 1;
I2C_delay();
data_bit = SDA;   /* Check acknowledge */
LPC_GPIO0->FIOCLR  = SCL; //SCL = 0; /* Clear SCL */

I2C_delay();
if(data_bit == 1)
UART0_SENT_DATA("ERROR..TT ",10);
else
check_wr = 1;
//return data_bit; /* If send_bit = 0 i2c is valid */
}


โค้ด Main ในส่วน I2C
Code:
int main(void)
{
    I2C_start();
   I2C_write(0xA4);
   I2C_write(0x00);
   for (i=1;i<=16;i++)
   {
   I2C_write(i);
   }
   I2C_stop();    
   if(check_wr == 1)
   {
   UART0_SENT_DATA("OK..",3);
   }else UART0_SENT_DATA("ERROR",5);

}
บันทึกการเข้า
ShadowMan
Administrator
Hero Member
*****
ออฟไลน์ ออฟไลน์

เพศ: ชาย
กระทู้: 8272


ShadowWares


| |
« ตอบ #9 เมื่อ: มิถุนายน 07, 2013, 02:30:48 pm »

ดู code ผ่านๆ มาสะดุดตาที่:
Code: (c)
data_bit = dat & 0x80;   
if(data_bit==1)

ขอถาม 1 คำถามว่า:
มีค่าอะไร ที่ AND ด้วย 0x80 แล้วได้เท่ากับ 1 ?


หรือจาก:
Code: (c)
data_bit = dat & 0x80;   

data_bit จะมีค่าเท่ากับ 1 เมื่อ dat มีค่าเท่าไร่?
บันทึกการเข้า

By SDW: Do No Wrong Is Do Nothing
          If you want to increase your success rate, double your failure rate
anon1206
Newbie
*
ออฟไลน์ ออฟไลน์

กระทู้: 30


| |
« ตอบ #10 เมื่อ: มิถุนายน 07, 2013, 02:56:58 pm »

ต้องขออภัยครับ พอดีเขียนผิดนะครับ ผมแก้แล้วเป็น if(data_bit== 0x80) แต่ก็ยัง ERROR เหมือนเดิมครับจะมีทางเช็คหรือแก้จากตรงไหนดีครับ
บันทึกการเข้า
ShadowMan
Administrator
Hero Member
*****
ออฟไลน์ ออฟไลน์

เพศ: ชาย
กระทู้: 8272


ShadowWares


| |
« ตอบ #11 เมื่อ: มิถุนายน 07, 2013, 04:45:00 pm »

ok งั้นมาว่ากันต่อ
จาก

Code: (c)
SDA = data_bit;

หมายความว่า ค่าของ SDA ที่เป็นไปได้มีสองค่าคือ 0x80 และ 0x00 ใช่หรือไม่?

ไม่ว่าตำตอบที่ได้จะใช่หรือไม่ใช่ ไม่ใช่ประด็นหลัก ประเด็นหลักคือ SDA มันเปลี่ยนค่าตอนไหน และ มันส่งผลอะไรกับ:
Code: (c)
LPC_GPIO0->FIOSET = SDA;

และ
Code: (c)
LPC_GPIO0->FIOCLR = SDA ;


ผมดู code ของคุณแล้วไมเข้าใจว่าตกลง SDA ของคุณคืออะไร?
ที่มัน print "ERROR" ออกมาก็มาจากสาเหตุเดียวคือ
data_bit = SDA; ซึ่ง SDA จะต้องเท่ากับ 1
แล้วมันเป็น 1 ได้อย่างไร? SDA มันเชื่อมโยงไปไหน?
บันทึกการเข้า

By SDW: Do No Wrong Is Do Nothing
          If you want to increase your success rate, double your failure rate
anon1206
Newbie
*
ออฟไลน์ ออฟไลน์

กระทู้: 30


| |
« ตอบ #12 เมื่อ: มิถุนายน 07, 2013, 06:01:14 pm »

คือผมนำตัวอย่างมาจากเว็บนี้นะครับ http://www.geocities.ws/aon_micro/24cxx.html แล้วนำมาแปลงให้ใช้กับ ARM LPC1756 ที่เขียนด้วย Keil
 ซึ่งของเค้าเช่น SCL = 1;  SDA = 1; หรือ  SCL = 1; SCL = 0;

ผมเลยนำมาแปลงเป็น  LPC_GPIO0->FIOSET = SDA;  ซึ่งคือการเซ็ตให้ logic = 1 และ  LPC_GPIO0->FIOCLR = SDA; คือ logic = 0
ไม่ทราบว่าผมเข้าใจถูกหรือป่าวครับถ้าผิดต้องขอคำแนะนำด้วยครับ

ซึ่ง SDA และ SCL คือขา GPIO ที่ผมนำมาใช้งานคือ

#define SDA 0x00000001  //P0.0
#define SDA 0x00000002  //P0.1

โค้ดตัวอย่างที่นำมาแปลง
Code:
#include <reg51.h>
#include <intrins.h>
#include <stdio.h>
// Define Port
sbit SDA = P1^0;
sbit SCL = P1^2;
sbit LED_R = P2^0; //LED red

// Define Register
unsigned char dat_buff[8];
bit check_wr = 0;

// Function
void init (void)
{
SCON = 0x52;
TMOD = 0x20;
TH1 = 0xfd;
TR1 = 1;

P2 = 0xff;
RST = 0;
SCL = 0;
SDA = 1;
}

void delay (void)
{
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}

void c_high (void)
{
SCL = 1;
delay();
}

void c_low (void)
{
SCL = 0;
delay();
}

void start_i2c (void)
{
SDA = 1;
c_high();
SDA = 0;
delay();
c_low();
}

void stop_i2c (void)
{
SDA = 0;
c_high();
SDA = 1;
}

bit wr_byte (unsigned char x) // Write 1 Byte
{ unsigned char i;
bit outport;
for (i=1;i<=8;i++)
{
outport = x & 0x80; //0x80 = 10000000B
SDA = outport;
x = x<<1;
c_high();
c_low();
}
SDA = 1;
c_high();
outport = SDA; // Check ACK
c_low();
if (outport == 1)
LED_R = 0;// LED red
else
check_wr = 1;
}

unsigned char rd_byte () // Read 1 Byte
{
unsigned char i,dat ;
bit inport;
dat = 0;
SDA = 1; // Important if SDA not set can read 1 byte only !!!
for (i=1;i<=8;i++)
{
c_high();
inport = SDA;
dat = dat<<1;
dat = dat|inport;
c_low();
}
return(dat);
}

// Send ACK
void ack (void)
{
SDA = 0;
_nop_();
c_high();
c_low();


}

// Clear Buffer
void clr_buff (void)
{
unsigned char i;
for (i=1;i<=8;i++)
dat_buff[i] = 0;
}

void delay_s (unsigned int count)
{
unsigned char i;
while (count)
{ for (i=0;i<=255;i++);
count--;}
}

//**************MAIN******************//
void main (void)
{
unsigned char i,j,k;
init();

printf("\nTest 24LCXX Write\n");
start_i2c();
wr_byte(0xa0); //Send write
wr_byte(0x00); //Send address

for (i=1;i<=16;i++)
{
wr_byte(i);
}
stop_i2c();
if (check_wr == 1)
printf("Write OK\n\n");
else
{printf("Write error!!!\n");}

init();
printf("\nTest 24LCXX Read");
start_i2c();
wr_byte(0xa0); //Send write
wr_byte(0x00); //Send address
start_i2c(); //Start again
wr_byte(0xa1); //Send read

for (j=1;j<=8;j++)
{
printf("\n");
for (k=1;k<=8;k++)
{
printf("%02bX ",rd_byte());
ack();
}
}
stop_i2c();

while(1);

}
บันทึกการเข้า
anon1206
Newbie
*
ออฟไลน์ ออฟไลน์

กระทู้: 30


| |
« ตอบ #13 เมื่อ: มิถุนายน 08, 2013, 08:00:15 am »

 cry มีจะแนะนำหรือบอกวิธีการแปลงอย่างโค้ด i2c มาใช้กับ ARM LPC1756 ให้ได้ไหมครับ ว่าต้องเขียนแบบไหน
หรือต้องแก้ตรงจุดไหนบ้าง
เหมือนตัวอย่างเค้าจะเข้าถึงระดับบิตอย่างเดียวเลย
โค้ดตัวอย่าง http://www.geocities.ws/aon_micro/24cxx.html
ตั้งแต่ประกาศ port

// Define Port
sbit SDA = P1^0;
sbit SCL = P1^2;
sbit LED_R = P2^0; //LED red

แล้วผมจะเขียนเปลี่ยนจากบิตมาเป็นแบบไหนแนะนำหน่อยครับ  azn
บันทึกการเข้า
ShadowMan
Administrator
Hero Member
*****
ออฟไลน์ ออฟไลน์

เพศ: ชาย
กระทู้: 8272


ShadowWares


| |
« ตอบ #14 เมื่อ: มิถุนายน 08, 2013, 09:23:48 am »

ในเมื่อคุณ define:
Code: (c)
#define SDA 0x00000001  //P0.0

นั่นหมายความว่า SDA เป็นค่าคงที่มีค่าเท่ากับ 1 ตลอดไป แล้วคุณเขียนโปรแกรมแบบนี้:
Code: (c)
   data_bit = SDA;      /* Check acknowledge */
   LPC_GPIO0->FIOCLR  = SCL; //SCL = 0;
   I2C_delay();
   if(data_bit == 1)
          UART0_SENT_DATA("ERROR..TT ",10);  // ถ้า data_bit = 1 แสดงว่าเกิดการผิดพลาด

data_bit ก็ย่อมเป็น 1 ผลก็ต้องได้ ERROR... ออกมาตลอดไป นั่นเป็นสิ่งที่ถูกต้องแล้ว (แต่คุณไม่อยากได้สิ่งที่ถูกต้องนั้น)

การจรวจสอบการ Acknowledge จาก I2C Devices ไม่ใช่การจับค่าคงที่ใส่ตัวแปร แต่คือการอ่านสถานะลอจิกที่ขา SDA บรรทัดไหนที่ทำสิ่งนี้?

ลอก code เขามาใช้ ไม่ใช่เรื่องเสียหาย แต่ถ้าคุณยังใช้ IO Port ของ MCU ไม่เป็นอันนี้เรื่องใหญ่ครับ
ลองกลับไปเขียนโปรแกรม อ่านค่าจาก Switch แล้วสั่ง LED ให้ติดดับก่อน จากนั้นค่อยมาแก้โจทย์ข้อนี้ต่อน่าจะดีกว่าหรือเปล่า
งานแบบนี้ ยิ่งใจร้อน มันจะยิ่งช้า
บันทึกการเข้า

By SDW: Do No Wrong Is Do Nothing
          If you want to increase your success rate, double your failure rate
หน้า: [1] 2   ขึ้นบน
  พิมพ์  
 
กระโดดไป: