PIC Vietnam

PIC Vietnam (http://www.picvietnam.com/forum/index.php)
-   Giao tiếp USB, CAN, I2C, SPI, USART... (http://www.picvietnam.com/forum/forumdisplay.php?f=45)
-   -   Giao tiếp I2C (http://www.picvietnam.com/forum/showthread.php?t=611)

falleaf 07-09-2006 11:54 PM

Giao tiếp I2C
 
1 Attachment(s)
Bài báo cáo này do Nguyễn Chí Linh thực hiện trong thời gian làm mod của picvietnam, nhưng không hiểu sao vẫn chưa được đăng. Hôm nay thấy bên dientuvietnam thảo luận về vấn đề này, cho nên mới tìm lại bài báo cáo này và gửi lên.

Chúc vui

bien_van_khat 08-09-2006 06:19 PM

Em post 1 bài ngoài vấn để kỹ thuật nhé. Chữ I2C đọc là gì nhỉ? Nguyên gốc của nó là IIC hoặc viết I2C nhưng số 2 viết nhỏ phía trên giống số mũ. Có người đọc là "Ai chu xi" (I 2 C đánh vần tiếng Anh :D), em nghĩ đúng phải đọc là "Double I C", tương tự như IEEE đọc là (I triple E).

Nhưng em thích đọc là I 2 C (đánh vần tiếng Việt :D). Không biết mọi người đọc như thế nào nhỉ?

namqn 08-09-2006 07:14 PM

Trích:

Nguyên văn bởi bien_van_khat (Post 4838)
Em post 1 bài ngoài vấn để kỹ thuật nhé. Chữ I2C đọc là gì nhỉ? Nguyên gốc của nó là IIC hoặc viết I2C nhưng số 2 viết nhỏ phía trên giống số mũ. Có người đọc là "Ai chu xi" (I 2 C đánh vần tiếng Anh :D), em nghĩ đúng phải đọc là "Double I C", tương tự như IEEE đọc là (I triple E).

Nhưng em thích đọc là I 2 C (đánh vần tiếng Việt :D). Không biết mọi người đọc như thế nào nhỉ?

Dân Anh đọc là "ai tu xi", tiếng của họ thì mình cứ đọc theo họ thôi. Đọc "double I C" thì dài hơn "ai tu xi" nên họ không đọc (dân Anh lười lắm), còn tại sao đọc "triple E" thì thử so sánh "I E E E" với "I triple E" xem cái nào dễ đọc hơn (cùng số âm tiết).

Thân,

falleaf 09-09-2006 01:22 PM

Trích:

Nguyên văn bởi bien_van_khat (Post 4838)
Em post 1 bài ngoài vấn để kỹ thuật nhé. Chữ I2C đọc là gì nhỉ? Nguyên gốc của nó là IIC hoặc viết I2C nhưng số 2 viết nhỏ phía trên giống số mũ. Có người đọc là "Ai chu xi" (I 2 C đánh vần tiếng Anh :D), em nghĩ đúng phải đọc là "Double I C", tương tự như IEEE đọc là (I triple E).

Nhưng em thích đọc là I 2 C (đánh vần tiếng Việt :D). Không biết mọi người đọc như thế nào nhỉ?

Thực ra, mọi người vẫn đọc là "Eye two See". Đây là cách đọc chính xác, không sai. Một cách đọc khác là "Eye square See", đây cũng là một cách đọc đúng. Còn "Double Eye See" thì anh chưa nghe đọc bao giờ. Những cách nói này là anh nói chuyện trực tiếp với bọn nước ngoài, và bọn nó dùng như vậy.

Còn "Eye Triple E" là cách đọc được ghi chú trực tiếp trên trang ieee.org. Ở Pháp thì nó lại đọc (anh viết tiếng Việt) "Y troa dsơ" Cũng đồng nghĩa với I và 3 chữ E.

Do vậy, từ nay về sau, thống nhất trên PICVietnam, chúng ta đọc I2C là "Eye two See", chứ không đọc "Eye Square See" (đề phòng trường hợp cần voice chat, sẽ có một ngày đại hội picvietnam online), còn khi viết thì viết I2C cho nhanh, chứ không nên viết rất mất công viết công thức Latex.

Chúc vui.

thanhha 11-09-2006 10:51 AM

Mình dùng lệnh I2C trong CCS có hiệu quả ko ?!
 
Vì mình đang viết thử I2C. Thấy chương trình mẫu(EX_Slave) trong CCS C mô phỏng bộ nhớ ngoài 24xx chuẩn, nên nạp chạy thử thấy: viết từ Master (Ctr Mater lấy ví dụ: EX_EXTEE) ít nhất là 4 lần mới được, còn đọc thì lại ko được. Xem tài liệu thì thấy có rất nhiều bit bẫy tình huống I2C, nhưng các lệnh về I2C trong CCS thì đơn giản và ít. Vậy, có vấn đề gì không.

Code:

#include <16F876A.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)  // Jumpers: 8 to 11, 7 to 12


#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0xa0)

typedef enum {NOTHING, CONTROL_READ,
              ADDRESS_READ, READ_COMMAND_READ} I2C_STATE;

I2C_STATE fState;
BYTE address, buffer[0x10];


#INT_SSP
void ssp_interupt ()
{
  BYTE incoming;

  if (i2c_poll() == FALSE) {
      if (fState == ADDRESS_READ) {  //i2c_poll() returns false on the
        i2c_write (buffer[address]);//interupt receiving the second
        fState = NOTHING;          //command byte for random read operation
      }
  }
  else {
      incoming = i2c_read();

      if (fState == NOTHING){
        fState = CONTROL_READ;
      }
      else if (fState == CONTROL_READ) {
        address = incoming;
        fState = ADDRESS_READ;
      }
      else if (fState == ADDRESS_READ) {
        buffer[address] = incoming;
        fState = NOTHING;
      }
  }
}


void main ()
{
  int i;

  fState = NOTHING;
  address = 0x00;
  for (i=0;i<0x10;i++)
      buffer[i] = 0x00;

  enable_interrupts(GLOBAL);
  enable_interrupts(INT_SSP);

  while (TRUE) {}
}


thanhha 12-09-2006 11:25 AM

Có ai quan tâm vấn đề I2C trong CCS, cho Hà hỏi 1 chút:
i2c_isr_state() hình như không có trong V 3.227. Version này chỉ có các lệnh I2C cho 16F877A là: i2c_start(), i2c_stop(), i2c_read(),i2c_write(), i2c_poll().
Có phải vậy không. Nếu vậy, mình phải tự tạo i2c_irs_state(). Có phải vậy ko?!.

Vì trong Help V4.0,có nói đến i2c_isr_state(), còn Help V3.227 Hà đang dùng thì ko thấy nói đến.
Có ai rành I2C, chỉ giáo giùm chút ít kinh nghiệm.Xin rất cảm ơn!!

hoanf 12-09-2006 12:52 PM

Chào Hà.
Tui cũng đang mò làm I2C trên CCS đây.
Hà nói là phiên bản 3.227 kô có i2c_irs_state(). Vậy sao Hà kô tải V3.249 về làm.
Mình hi vọng tui cả Hà sẽ cùng nghiên cúu vấn đề này.
Chào
hoanf

thanhha 12-09-2006 01:00 PM

Hà đang tìm đường link để tải Version khác cao hơn: V3.242 thì sáng tới giờ ko thấy gì. Vậy, mình tìm thử V3.249 xem sao.

Bạn biết link V3.249 thì hướng dẫn Hà với !!
Rất cảm ơn !!!

Thanhha

hoanf 12-09-2006 02:52 PM

Chào bạn.
Bạn có thể tải bản V3.249 ở đây
http://rapidshare.de/files/32817261/CCSC_3.249.rar

hoanf

thanhha 13-09-2006 01:59 PM

1 Attachment(s)
Hà vừa thử chtr I2c: Master 16F877A, Slave 16F876A, cùng giao tiếp PC để kiểm tra dữ liệu đọc và viết của Master và Slave> Thấy rất tốt ! I2C hay thiệt! Nhiêm vụ bây giờ mình chỉ tạo giao thức dữ liệu, còn chtr service plug&play slave thì thấy hơi khó! Nhưng mònh cố gắn viết thử. Cảm ơn Hoanf, mọi người rất nhiều !!
Code:

**********************************************
Chtr Master, mình thay đổi chút ít từ chtr mẫu EX_EXTEE.
          1.chỉ liên kết 2401.c (thay vì địa chỉ mặc đinh là 0xa0,
mình thay là 0x10).
          2. Vẫn truyền lệnh từ PC
**********************************************
#include <16F877A.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

#include <input.c>
#include <2401.c>


void main() {

  BYTE value, cmd;
  EEPROM_ADDRESS address;

  init_ext_eeprom();

  do {
      do {
        printf("\r\nRead or Write: ");
        cmd=getc();
        cmd=toupper(cmd);
        putc(cmd);
      } while ( (cmd!='R') && (cmd!='W') );

      printf("\n\rLocation: ");

      address = gethex1();

      if(cmd=='R')
        printf("\r\nValue: %X\r\n",READ_EXT_EEPROM( address ) );

      if(cmd=='W') {
        printf("\r\nNew value: ");
        value = gethex();
        printf("\n\r");
        WRITE_EXT_EEPROM( address, value );
      }
  } while (TRUE);
}

Code:

**********************************************
Chtr Slave, thì có thay đổi chút ít từ chtr mẫu EX_Slave:
                  1. giám sát 3 ô nhớ trên PC
                  2. khai báo địa chỉ la 0x10.
**********************************************
#include <16F876A.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0x10)

BYTE address, buffer[0x10];

#INT_SSP
void ssp_interupt ()
{
  BYTE incoming, state;

        state = i2c_isr_state();

        if(state < 0x80)                                          //Master is sending data
        {
                incoming = i2c_read();
                if(state == 1)                                                        //First received byte is address
                        address = incoming;
                if(state == 2)                                                        //Second received byte is data
                        buffer[address] = incoming;
        }
        if(state == 0x80)                                        //Master is requesting data
        {
                i2c_write(buffer[address]);
        }
}

void main ()
{
  enable_interrupts(GLOBAL);
  enable_interrupts(INT_SSP);

  while (TRUE) {
          printf("\r\nValue0: %X\r\n",buffer[0]);
          delay_ms(1000);
          printf("\r\nValue1: %X\r\n",buffer[1]);
          delay_ms(1000);
          printf("\r\nValue2: %X\r\n",buffer[2]);
          delay_ms(1000);
          printf("\r\nValue3: %X\r\n",buffer[3]);
          delay_ms(1000);
}
}

******************************************
Phần mạch điện có File đính kèm :

falleaf 13-09-2006 04:48 PM

Anh đề nghị em post thêm sơ đồ mạch nguyên lý đi kèm. Thực ra không có gì phức tạp cả, chỉ vì bài viết mà chỉ có code không thôi thì nó không sinh động. Hơn nữa, người sau đọc vào không có hình ảnh đi kèm, nhiều khi người ta không hiểu nổi và ngại đọc. Chỉ cần có một cái hình vào, thì bài viết sẽ sinh động hơn nhiều.

Chúc vui.

hoanf 13-09-2006 05:24 PM

:d
 
Chào các bạn và Hà.
Mình mới viết được chương trình giao tiếp I2C đơn giản dùng các hàm của CCS.
Mời các bạn xem và cho nhận xét

Master: truyền dữ liệu cho Slave. Mỗi lần truyền 1 byte.

Code:

#include <16F877A.H>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use Delay(Clock=4000000)

#define SLAVE_ADDRESS 0x10
#use i2c(master, sda=PIN_C4, scl=PIN_C3)

void write_I2C(int8 a)
{
  i2c_start();
  i2c_write(SLAVE_ADDRESS);
  i2c_write(a);
  i2c_stop();
}

void main()
{
  int8 value;
 
  value = 0;
  while(1){
      write_I2C(value);
      value++;
      delay_ms(100);
  }
}


Slave thì chỉ tiến hành kiểm tra có phải Master truyền hay kô. Nếu truyền thì nhận byte dữ liệu và hiển thị lên port_B:
Code:

#include <16F877A.H>
#fuses XT,NOWDT,NOPROTECT,NOLVP

#use delay(Clock=4000000)
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0x10)

int8 value;

#INT_SSP
void i2c_isr()
{
  int8 state;
  int8 address;
  state = i2c_isr_state();
  if(state == 0)
      address = i2c_read();
  else if(state < 0x80)
        value = i2c_read();
}

void main()
{
  enable_interrupts(GLOBAL);
  enable_interrupts(INT_SSP);

  set_tris_b(0x00);
  while(1){
      output_b(value);
  }
}

Thân
hoanf

hoanf 14-09-2006 12:34 PM

Alo
 
Chào các bạn!!
Mình gặp trục trặc khi đọc dữ liệu từ Slave về.
Đây là đoạn code sử dụng cho 2 con PIC 18F877A.

Master: Yêu cầu Slave nhận dữ liệu liên tục (cách nhau 500ms) và nó sẽ hiển thị giá trị nhận được lên Port_b. Dùng leds để quan sát.

Code:

#include <16F877A.H>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use Delay(Clock=4000000)

#define SLAVE_ADDRESS 0x10
#use i2c(master, sda=PIN_C4, scl=PIN_C3)

int8 read_I2C()
{
  int8 value;

  i2c_start();
  i2c_write(SLAVE_ADDRESS + 1);
  value = i2c_read();
  i2c_stop();
  return value;
}

void main()
{
  int8 value;

  set_tris_b(0x00);
 
  while(1){
      value = read_I2C();
      output_b(value);
      delay_ms(500);
  }
}

Slave: Truyền dữ liệu cho master và mỗi lần truyền thì giá trị cần truyền tăng lên 1 đơn vị.
Code:

#include <16F877A.H>
#fuses XT,NOWDT,NOPROTECT,NOLVP

#use delay(Clock=4000000)
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0x10)

int8 value = 0x01;

#INT_SSP
void i2c_isr()
{
  int8 state;
  int8 address;
  state = i2c_isr_state();
  if(state >= 0x80){
      i2c_write(value);
      value++;
  }
}

void main()
{
  enable_interrupts(GLOBAL);
  enable_interrupts(INT_SSP);

  set_tris_b(0x00);
  while(1){
      output_b(value);     
  }
}


thanhha 14-09-2006 04:24 PM

Theo Hà nghĩ, ở Master, khi mình đọc cũng phải chờ xung ACK từ Slave thì chtr ko bị rối.
Bạn thử thêm một chtr con chờ Bus trong <2401.c>:

Code:

//**************code thêm vào*********************
BOOLEAN ext_eeprom_ready()
{
  int1 ack;
  i2c_start();           
  ack = i2c_write(SLAVE_ADDRESS); 
  i2c_stop();
  return !ack;
}
//**********************************************
int8 read_I2C()
{
    int8 value;
    while(!ext_eeprom_ready());                        // code thêm vào
    i2c_start();
    i2c_write(SLAVE_ADDRESS + 1);
    value = i2c_read();
    i2c_stop();
    return (value);
}

void main()
{
    int8 value;

    value = 0x00;
    set_tris_b(0x00);

    while(1){
    value = read_I2C();
    output_b(value);
    delay_ms(500);
    }
}

**********************************************
Thân mến !!

falleaf 14-09-2006 04:49 PM

Các em nhớ đặt chương trình trong thẻ [code]...[/code ] (nhớ viết liền lại)

Như vậy thì mọi người sẽ đọc dễ hơn, và nếu code dài quá thì nó cũng thu gọn lại trong một khung cố định.

Ngoài ra, code cũng có thụt ra thụt vào rõ ràng như trong đoạn code mà tụi em copy. Chú ý điều này khi viết bài.

Chúc vui.

Hoanf, và ThanhHa, như anh nói, giúp anh post một cái hình mạch nguyên lý giao tiếp đúng như trong cái đề tài mà tụi em đang thảo luận, để mọi người dễ theo dõi.

Thanks muchie.


Múi giờ GMT. Hiện tại là 06:54 PM.

Tên diễn đàn: vBulletin Version 3.8.11
Được sáng lập bởi Đoàn Hiệp.
Copyright © PIC Vietnam