กรกฎาคม 19, 2018, 08:38:51 am *
ยินดีต้อนรับคุณ, บุคคลทั่วไป กรุณา เข้าสู่ระบบ หรือ ลงทะเบียน
ส่งอีเมล์ยืนยันการใช้งาน?

เข้าสู่ระบบด้วยชื่อผู้ใช้ รหัสผ่าน และระยะเวลาในเซสชั่น
   หน้าแรก   ช่วยเหลือ เข้าสู่ระบบ สมัครสมาชิก  
หน้า: [1]   ลงล่าง
  พิมพ์  
ผู้เขียน หัวข้อ: LPC2138 >> I2C Interface  (อ่าน 5434 ครั้ง)
0 สมาชิก และ 1 บุคคลทั่วไป กำลังดูหัวข้อนี้
secret07
Newbie
*
ออฟไลน์ ออฟไลน์

กระทู้: 11


| |
« เมื่อ: กุมภาพันธ์ 13, 2013, 11:32:13 pm »

มาใหม่อีกครั้งแล้วครับ
งวดนี้ไปยืมเซ็นเซอร์ compass มาเล่นครับ >>> HMC5883L
ตอนนี้มันทำงานไปถึงการส่ง Address แล้ว

printf("Write Address \t"); แสดงมาแล้ว

แต่มันไม่มีการ ACK กลับมาเพื่อที่จะเขียน data ไปอ่ะครับ
ผมดูใน datasheet ของ lpc2138 ที่มันมีตาราง ACK ตรง Master Trans.. กับ Master Reci..เนี้ย
ผมเลือกใช้มาถูกป่าว หรือว่าผมเขียนผิดตรงไหน
ช่วยดูให้หน่อยครับผม

ปล. ตรงช่วงที่คอมเม้นยาววววเลยนั้น  ผมลองเขียนแบบฟังชั่นเดียวอ่ะมันไม่เวิร์ก
      เลยคิดว่าน่าจะเขียนแยกกันจะได้เรียกใช้ง่ายขึ้นหน่อยแต่ก็ติดตรงหลังจากส่ง Address ไปเหมือนกัน

Code:
#include <LPC213X.H>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "uart0.h"

#define Read_Compass 0x3D
#define Write_Compass 0x3C


void Init_PIN(void)
{
PINSEL0 = 0x00000000; // Reset Pinsel 0
PINSEL1 = 0x00000000; // Reset Pinsel 1
PINSEL2 = 0x00000000; // Reset Pinsel 2

PINSEL0 |= (5<<0); // Port0.0 [Uart0 TXD] Bit 1,0 >>> 0,1
// Port0.1 [Uart0 RXD] Bit 3,2 >>> 0,1
PINSEL0 |= (5<<4); // Port0.2 [I2C SCL0] Bit 5,4 >>> 0,1
// Port0.3 [I2C SDA0] Bit 7,6 >>> 0,1
}

void init_i2c0(void)
{
I2C0SCLH = 0x93; // 200k [High 100k]
I2C0SCLL = 0x93; //   [Low  100k] >> I2C = PCLK / 200k = 147 >> 0x93
}

// char read_i2c(void)
// {
// int x_high,x_low,y_high,y_low,z_high,z_low;
// long int x,y,z;
// char data[3];

// I2C0CONCLR = 0x6C; // Clear Register
// I2C0CONSET |= 0x40; // Interface Enable
// I2C0CONSET |= 0x20; // Start

// while((I2C0STAT) != 0x08); // Start Condition
// printf("Start 1 \n");
// I2C0DAT = 0x3C; // write Address
// I2C0CONCLR = 0x28; // [START flag clear bit] and [i2c interrupt clear bit]

// while((I2C0STAT) != 0x18); // ackno
// printf("Write \n");
// I2C0DAT = 0x02; // mode register = Idel mode
// I2C0CONCLR = 0x0C; // Ackno clear and irq clear
//
// while((I2C0STAT) != 0x28); // ackno
// printf("Idel mode \n");
// I2C0DAT = 0x00; // Continuous-Measurement mode
// I2C0CONCLR = 0x0C; // Ackno clear and irq clear

// while((I2C0STAT) != 0x28);
// printf("Write End \n");
// I2C0CONSET |= 0x10;
// I2C0CONCLR = 0x0C; // Ackno clear and irq clear
//
// /**********************************/

// I2C0CONCLR = 0x6C;
// I2C0CONSET |= 0x40;
// I2C0CONSET |= 0x20;

// while((I2C0STAT) != 0x08);
// printf("Start 2 \n");
// I2C0DAT = 0x3D; // Read
// I2C0CONCLR = 0x28;

// while((I2C0STAT) != 0x40); // wait ackno read
// printf("Read \n");
// I2C0CONCLR = 0x0C;

// while((I2C0STAT) != 0x58); // wait ackno data
// printf("Read data x_high \n");
// x_high = I2C0DAT; // x_high byte
// I2C0CONCLR = 0x0C; // Ackno clear and irq clear

// while((I2C0STAT) != 0x58); // wait ackno data
// printf("Read data x_low \n");
// x_low = I2C0DAT; // x_low byte
// I2C0CONCLR = 0x0C; // Ackno clear and irq clear
//
// x = x_low|(x_high<<8);
// /***/
// while((I2C0STAT) != 0x58); // wait ackno data
// printf("Read data y_high \n");
// y_high = I2C0DAT; // y_high byte
// I2C0CONCLR = 0x0C; // Ackno clear and irq clear

// while((I2C0STAT) != 0x58); // wait ackno data
// printf("Read data y_low \n");
// y_low = I2C0DAT; // y_low byte
// I2C0CONCLR = 0x0C; // Ackno clear and irq clear
//
// y = y_low|(y_high<<8);
// /***/
// while((I2C0STAT) != 0x58); // wait ackno data
// printf("Read data z_high \n");
// z_high = I2C0DAT; // z_high byte
// I2C0CONCLR = 0x0C; // Ackno clear and irq clear

// while((I2C0STAT) != 0x58); // wait ackno data
// printf("Read data z_low \n");
// z_low = I2C0DAT; // z_low byte
// I2C0CONCLR = 0x0C; // Ackno clear and irq clear
//
// z = z_low|(z_high<<8);

// I2C0CONSET |= 0x10;
// I2C0CONCLR = 0x0C;
//
// printf("End i2c");

// data[0] = x;
// data[1] = y;
// data[2] = z;
//
// return data[0];
// }

void write_i2c(unsigned char Addr,unsigned char Data)
{
I2C0CONCLR = 0x6C;
I2C0CONSET |= 0x40;
I2C0CONSET |= 0x20;

while((I2C0STAT) != 0x08);
I2C0DAT = Addr;
I2C0CONCLR = 0x28;
printf("Write Address \t");

while((I2C0STAT) != 0x18);
I2C0DAT = Data;
I2C0CONCLR = 0x0C;
printf("Write Data \r\n");

while((I2C0STAT) != 0x28);
I2C0CONSET |= 0x10;
I2C0CONCLR = 0x0C;
}

char read_i2c(unsigned char Addr)
{
long int data;


I2C0CONCLR = 0x6C;
I2C0CONSET |= 0x40;
I2C0CONSET |= 0x20;

while((I2C0STAT) != 0x08);
I2C0DAT = Addr;
I2C0CONCLR = 0x28;
printf("Read Address \t");

while((I2C0STAT) != 0x40);
I2C0CONCLR = 0x0C;
printf("Wait acknowledge \t");

while((I2C0STAT) != 0x58);
data = I2C0DAT;
I2C0CONSET |= 0x10;
I2C0CONCLR = 0x0C;
printf("Read Data \r\n");

return data;
}

void compass_read(void)
{
int x_high,x_low,y_high,y_low,z_high,z_low;
long int x,y,z;

write_i2c(Write_Compass,0x02);
printf("Set Idel Mode Complete\n");
write_i2c(Write_Compass,0x00);
printf("Set Continous-Measurement Complete\n");

x_high = read_i2c(Read_Compass);
printf("Read X_High Complete\n");
x_low  = read_i2c(Read_Compass);
printf("Read X_Low Complete\n");
y_high = read_i2c(Read_Compass);
printf("Read Y_High Complete\n");
y_low  = read_i2c(Read_Compass);
printf("Read Y_Low Complete\n");
z_high = read_i2c(Read_Compass);
printf("Read Z_High Complete\n");
z_low  = read_i2c(Read_Compass);
printf("Read Z_Low Complete\n");

x = x_low|(x_high<<8);
printf("Value X = %d",(int)x);
y = y_low|(y_high<<8);
printf("Value Y = %d",(int)y);
z = z_low|(z_high<<8);
printf("Value Z = %d",(int)z);
}

int main(void)
{
Init_PIN();
init_uart0(38400);
init_i2c0();

while(1)
{
printf("\r\nStart Interface I2C \n\r");
compass_read();
}
}
บันทึกการเข้า
ShadowMan
Administrator
Hero Member
*****
ออฟไลน์ ออฟไลน์

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


ShadowWares


| |
« ตอบ #1 เมื่อ: กุมภาพันธ์ 14, 2013, 12:08:11 pm »

อ้างถึง
ผมดูใน datasheet ของ lpc2138 ที่มันมีตาราง ACK ตรง Master Trans.. กับ Master Reci..เนี้ย
ผมเลือกใช้มาถูกป่าว หรือว่าผมเขียนผิดตรงไหน

จากที่คุณได้อ่าน Datasheet มา และได้เขียน code ไปด้วยตัวเองนั้น ตรงไหนบ้างที่คุณสงสัย เฉพาะเจาะจงมาหน่อยครับ ว่าบรรทัดไหนที่ข้องใจหรือสงสัย ขอแบบเนื้อๆ เน้นๆ
Code ของคุณเต็มไปด้วยขยะ และมีส่วนที่ไม่เกี่ยวข้องกับปัญหามากมาย อะไรที่ไม่เกี่ยวกับคำถามไม่มีความจำเป็นใดๆ ต้องแถมมา

http://www.nxp.com/documents/application_note/AN10369.pdf
บันทึกการเข้า

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

กระทู้: 11


| |
« ตอบ #2 เมื่อ: กุมภาพันธ์ 19, 2013, 06:51:48 am »

ตอนนี้ลองอ่านค่าเฉพาะ x มันออกเลข 72 ตลอดเลย

***  x_low   เป็น 72
        x_high  เป็น   0

ไม่แน่ใจว่ามันอ่านตรง   Register output ของ X    MSB และ LSB หรือป่าว
ใน Compass_refresh อ่ะ
ค่ามันไม่ยอมเปลี่ยนเลยโชว์แต่เลข 72

Code:
#include <LPC213X.H>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "uart0.h"

#define Read_Compass 0x3D
#define Write_Compass 0x3C

/****************/
/*** Init_PIN ***/
/****************/
void Init_PIN(void)
{
PINSEL0 = 0x00000000; // Reset Pinsel 0
PINSEL1 = 0x00000000; // Reset Pinsel 1
PINSEL2 = 0x00000000; // Reset Pinsel 2

PINSEL0 |= (5<<0); // Port0.0 [Uart0 TXD] Bit 1,0 >>> 0,1
// Port0.1 [Uart0 RXD] Bit 3,2 >>> 0,1
PINSEL0 |= (5<<4); // Port0.2 [I2C SCL0] Bit 5,4 >>> 0,1
// Port0.3 [I2C SDA0] Bit 7,6 >>> 0,1
}

/*****************/
/*** Write_I2C ***/
/*****************/
void write_i2c(unsigned char Addr,unsigned char Data)
{
I2C0CONCLR = 0x6C; // I2C interface Disable. && START flag Clear bit.
I2C0CONSET |= 0x40; // I2C interface enable.
I2C0CONSET |= 0x20; // START flag.

while((I2C0STAT) != 0x08);                 // A START condition has been transmitted.
I2C0DAT = Addr;
I2C0CONCLR = 0x28; // START flag Clear bit. && I2C interrupt Clear bit.

while((I2C0STAT) != 0x18);                 // SLA+W has been transmitted; ACK has been received.
I2C0DAT = Data;
I2C0CONCLR = 0x0C; // I2C interrupt Clear bit. && Assert acknowledge Clear bit.

while((I2C0STAT) != 0x28);                 // Data byte in I2DAT has been transmitted; ACK has been received.
I2C0CONSET |= 0x10;         // STOP flag.
I2C0CONCLR = 0x0C; // I2C interrupt Clear bit. && Assert acknowledge Clear bit.
}

/****************/
/*** Read_I2C ***/
/****************/
char read_i2c(unsigned char Addr)
{
long int data;

I2C0CONCLR = 0x6C; // I2C interface Disable. && START flag Clear bit.
I2C0CONSET |= 0x40; // I2C interface enable.
I2C0CONSET |= 0x20; // START flag.

while((I2C0STAT) != 0x08);                 // A START condition has been transmitted.
I2C0DAT = Addr;
I2C0CONCLR = 0x28; // START flag Clear bit. && I2C interrupt Clear bit.

while((I2C0STAT) != 0x40);                 // SLA+R has been transmitted; ACK has been received.
I2C0CONCLR = 0x0C; // I2C interrupt Clear bit. && Assert acknowledge Clear bit.

while((I2C0STAT) != 0x58);                 // Data byte has been received; NOT ACK has been returned.
data = I2C0DAT;

I2C0CONSET |= 0x10; // STOP flag.
I2C0CONCLR = 0x0C; // I2C interrupt Clear bit. && Assert acknowledge Clear bit.

return data;
}

/****************/
/*** Init_I2C ***/
/****************/
void init_i2c0(void)
{
I2C0SCLH = 0x93; // 200k [High 100k]
I2C0SCLL = 0x93;         //      [Low  100k] >> I2C = PCLK / 200k = 147 >> 0x93

write_i2c(Write_Compass,0x00); // Config Register A
write_i2c(Write_Compass,0x70); // 8-average, 15 Hz default, normal measurement

write_i2c(Write_Compass,0x01); // Config Register B
write_i2c(Write_Compass,0xA0); // Gain=5, or any other desired gain

write_i2c(Write_Compass,0x02); // Mode
write_i2c(Write_Compass,0x00); // Continuous-measurement mode

delay_ms(6); // Wait 6 ms or monitor status register or DRDY hardware interrupt pin
}

/***********************/
/*** Compass_refresh ***/
/***********************/
int Compass_refresh(void)
{
int x_high,x_low;
long int x;

write_i2c(Write_Compass,0x03); // Data Output X MSB Register
x_high = read_i2c(Read_Compass); // Read X_high

write_i2c(Write_Compass,0x04); // Data Output X LSB Register
x_low  = read_i2c(Read_Compass); // Read X_low

x = x_low|(x_high<<8); // Value X

return (int)x;
}

/********************/
/*** Main_Program ***/
/********************/
int main(void)
{
Init_PIN();
init_uart0(38400);

init_i2c0();

printf("\r\nStart Interface I2C \n\r");

while(1)
{
printf("X = %d \n",Compass_refresh());            // Read Compass
delay_ms(200);
}
}

ปล.ช่วงนี้การบ้านเยอะไม่ได้นั่งเขียนแก้เลย เพิ่งจะว่างเอง
บันทึกการเข้า
ShadowMan
Administrator
Hero Member
*****
ออฟไลน์ ออฟไลน์

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


ShadowWares


| |
« ตอบ #3 เมื่อ: กุมภาพันธ์ 19, 2013, 08:45:58 am »

เท่าที่เห็น code ของคุณไม่ได้เป็นไปตามที่ datasheet บอกไว้
คุณควรอ่าน datasheet และทำการเขียนโปรแกรมไปตามตามที่เขาบอกมา ลองอ่านหัวข้อ OPERATIONAL EXAMPLES ดู และจะดีมากถ้าอ่านให้หมดทุกหัวข้อ

การทำตาม datasheet เป็นส่วนประกอบหนึ่งเท่านั้น ส่วนประกอบอื่นๆ ที่ไม่แพ้กันคือ การ setup MCU รวมไปถึงวงจรด้วย ไม่สามารถมองข้ามส่วนใดส่วนหนึ่งได้
บันทึกการเข้า

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