I2C >> Compass

Started by secret07, February 13, 2013, 11:44:57 PM

Previous topic - Next topic

secret07

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

ตอนนี้มันทำงานไปถึงการส่ง Address แล้ว

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

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

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

ปล.2  ไม่มีตังซื้อมาเล่นเอง  :'(  :'( ที่จริงอยากได้ Gyro (เขียนรับใช้ ADC ใช่มะครับเพราะพอเขียนเป็น) แต่รุ่นพี่เค้าใช้ทำโปรเจคอยู่
         เลยมาลองเขียน I2C แทน

#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();
}
}

secret07

อ้อขอถามเพิ่มเติมอีก 2 ประเด็นคือ

1. มันต้องต่อ  pull up ด้วยถูกมั๊ยครับ
2. ในฟังชั่น compass นั้นที่มี ค่า x y z ถ้าสมมุติว่ามันอ่านค่าได้แล้ว จะ return ออกมายังไง 3 ค่าครับ

tha

เราไม่ต้องต่อ R pullup หรอกครับเพราะที่บอร์ดของ HMC5883L มีการต่อไว้อยู่แล้ว ผมดูโค้ดของคุณไม่เป็นแต่ผมเคยทำไว้กับ stm32f103rb ลองเอาโค้ดของผมไปดูก็แล้วกัน