Thông báo

Collapse
No announcement yet.

Chuan Giao Tiep I2c

Collapse
X
 
  • Lọc
  • Giờ
  • Show
Clear All
new posts

  • Chuan Giao Tiep I2c

    Chao Cac Bac
    Em Dang Tim Hieu Van De Ghep Noi 8051 Voi Eprom Ngoai Nhu Con
    24c01 Nhung Dang Gap Mot Kho Khan Do La Chuan Giao Tiep I2c
    Bac Nao Biet Ve Van De Nay Xin Giup Em Voi
    Neu Co Chuong Trinh Minh Hoa Thi Cang Tot(viet Bang Asm)

  • #2
    Ak, tai sao ko len Atmel kiem, code day ra do, sua chut la chay veo veo

    Comment


    • #3
      #include <at89x52.h>
      #include <intrins.h>

      sbit SCL = P1^1; //
      sbit SDA = P1^0; //
      //--------------------------------------------------------
      void i2c_start(void);// send start sequence
      void init(void);
      void i2c_stop(void);// send stop sequence
      unsigned char i2c_read(char ack);
      bit i2c_write(unsigned char d);
      void i2c_dly(void);
      //-------------------------------Ham main
      //--------------------------------------------------------
      void delay (void)
      {
      _nop_ ();
      }

      void scl_high (void)
      { //tin hieu scl len high
      SCL = 1;
      delay ();
      }

      void scl_low (void)
      { //tin hieu scl xuong low
      SCL = 0;
      delay ();
      }

      void i2c_start (void) { // bat dau bang lenh start
      SDA = 1;
      SCL = 1;
      SDA = 0;
      delay ();
      SCL = 0;
      SDA = 1;
      }
      void i2c_stop (void) { // ket thuc boi lenh stop
      SDA = 0;
      SCL = 1;
      delay ();
      SDA = 1;
      }
      bit i2c_write (unsigned char dulieu) { //ham nay goi 1 byte den 24c04
      unsigned char i; // neu ket qua (bit ack) = 0:du lieu truyen dung
      bit databit; // con bang 1 thi sai.
      for (i=0;i<=7;i++) {
      databit = dulieu & 0x80;
      SDA = databit;
      dulieu = dulieu << 1;
      scl_high ();
      scl_low ();
      }
      SDA = 1;
      scl_high ();
      databit = SDA;
      scl_low ();
      return (databit);
      }
      unsigned char i2c_read () { // ham nay nhan 1 byte tu ds1307
      unsigned char i,dulieu;
      bit bitdulieu;
      dulieu = 0;
      for (i=0;i<=7;i++) {
      scl_high ();
      bitdulieu = SDA;
      dulieu = dulieu << 1;
      dulieu = dulieu | bitdulieu;
      scl_low ();

      }
      SDA = 0;
      scl_high ();
      scl_low ();
      SDA = 1;
      return (dulieu);
      }


      void main()
      {
      P1=P2=P3=0xFF;
      if (i2c_read()==0x01) P2_0=0;
      else P2_1=0;
      while(1)
      {
      i2c_start(); // send start sequence
      i2c_write(0xD0); // Gui dia chi cua 24C04 voi bit RW = 0
      i2c_write(0x01); // Dia chi vi tri ROM can ghi du lieu
      i2c_stop();
      }
      }
      /*
      void main()
      {
      unsigned char byte1,byte2,byte3,address_for_firstbyte_read;
      while(1)
      {
      // Ghi du lieu vao 24C04
      i2c_start(); // send start sequence
      i2c_write(0xD0); // Gui dia chi cua 24C04 voi bit RW = 0
      i2c_write(0x01); // Dia chi vi tri ROM can ghi du lieu
      i2c_write(byte1); // Cac byte tiep theo, thanh ghi xac dinh dia chi se tu tang len 1
      i2c_write(byte2);
      i2c_write(byte3);
      i2c_write(0xAA);
      i2c_stop();
      i2c_start();
      i2c_write(0xD0);
      i2c_write(address_for_firstbyte_read);
      i2c_start(); // send a restart sequence
      i2c_write(0xD1); // set bit R/W - Read from 24C04
      byte1 = i2c_read();
      byte2 = i2c_read();
      byte3 = i2c_read();
      i2c_stop(); // send stop sequence
      }
      }*/
      SHARE KHO PHIM LỚN

      Comment


      • #4
        bạn xem datasheet của 24c01 để biết điều kiện start, stop, read, write của nó
        Chúc bạn thành công

        Comment


        • #5
          Cái này các bạn đã thảo luận rồi, bạn coi lại mấy chủ đề trước đó ấy, cũng rõ lắm, cứ làm theo đó là chạy. Còn muốn tự viết thì chịu khó coi lại datasheet của nó (mất vài ngày). Có thể kết hợp cả 2 cách trên.
          !e

          Comment


          • #6
            Giaosucan
            CHương trình của cậu hàm i2c_read() có đọc được nhiều byte liên tiếp không vậy.
            Last edited by encoder; 11-08-2006, 18:13.
            CUNG CẤP PSOC, MẠCH NẠP
            CHUYỂN ĐỔI USB <-> RS485 AutoBaud
            RS232 <-> RS485 MultiBaud
            MẠCH NẠP USBPPI S7-200
            Mobile: 0906076116
            Email:

            Comment


            • #7
              Đọc dược đấy, tuy nhiên nên thêm phần check ACK và NotACK để biết việc đọc byte cuối trong chuỗi byte cần đọc.

              bit i2c_write (unsigned dulieu) { //ham nay goi 1 byte den 24c04
              unsigned char i; // neu ket qua (bit ack) = 0:du lieu truyen dung
              bit databit; // con bang 1 thi sai.
              for (i=0;i<=7;i++) {
              databit = dulieu & 0x80;
              SDA = databit;
              dulieu = dulieu << 1;
              scl_high ();
              delay();
              scl_low ();
              }
              SDA = 1;
              scl_high ();
              databit = SDA;// Kiểm tra ACK xem salve nhận đúng chưa
              scl_low ();
              return (databit);
              }

              unsigned char i2c_read () { // ham nay nhan 1 byte tu ds1307
              unsigned char i,dulieu;
              bit bitdulieu;
              dulieu = 0;
              for (i=0;i<=7;i++) {
              scl_high ();
              bitdulieu = SDA;
              dulieu = dulieu << 1;
              dulieu = dulieu | bitdulieu;
              scl_low ();

              }
              SDA = 0; // Đoạn chương trình trả về ACK
              scl_high ();// Để chuẩn nên khai báo unsigned char i2c_read(bit ACK_NACK);
              scl_low ();// và dùng SDA = ACK_NACK;
              SDA = 1;
              return (dulieu);
              }
              Ethernet-RS232, PIC Webserver, RFID Reader
              CallerID, Cảnh báo BTS, ...
              0988006696
              linhnc308@gmail.com
              http://linhnc308.blogspot.com

              Comment


              • #8
                Nguyên văn bởi giaosucan
                #include <at89x52.h>
                #include <intrins.h>

                sbit SCL = P1^1; //
                sbit SDA = P1^0; //
                bit i2c_write (unsigned char dulieu) { //ham nay goi 1 byte den 24c04
                unsigned char i; // neu ket qua (bit ack) = 0:du lieu truyen dung
                bit databit; // con bang 1 thi sai.
                for (i=0;i<=7;i++) {
                databit = dulieu & 0x80;
                SDA = databit;
                dulieu = dulieu << 1;
                scl_high ();
                scl_low ();
                }
                SDA = 1;
                scl_high ();
                databit = SDA;
                scl_low ();
                return (databit);
                }
                unsigned char i2c_read () { // ham nay nhan 1 byte tu ds1307
                unsigned char i,dulieu;
                bit bitdulieu;
                dulieu = 0;
                for (i=0;i<=7;i++) {
                scl_high ();
                bitdulieu = SDA;
                dulieu = dulieu << 1;
                dulieu = dulieu | bitdulieu;
                scl_low ();

                }
                SDA = 0;
                scl_high ();
                scl_low ();
                SDA = 1;
                return (dulieu);
                }


                void main()
                {
                P1=P2=P3=0xFF;
                if (i2c_read()==0x01) P2_0=0;
                else P2_1=0;
                while(1)
                {
                i2c_start(); // send start sequence
                i2c_write(0xD0); // Gui dia chi cua 24C04 voi bit RW = 0
                i2c_write(0x01); // Dia chi vi tri ROM can ghi du lieu
                i2c_stop();
                }
                }
                /*
                void main()
                {
                unsigned char byte1,byte2,byte3,address_for_firstbyte_read;
                while(1)
                {
                // Ghi du lieu vao 24C04
                i2c_start(); // send start sequence
                i2c_write(0xD0); // Gui dia chi cua 24C04 voi bit RW = 0
                i2c_write(0x01); // Dia chi vi tri ROM can ghi du lieu
                i2c_write(byte1); // Cac byte tiep theo, thanh ghi xac dinh dia chi se tu tang len 1
                i2c_write(byte2);
                i2c_write(byte3);
                i2c_write(0xAA);
                i2c_stop();
                i2c_start();
                i2c_write(0xD0);
                i2c_write(address_for_firstbyte_read);
                i2c_start(); // send a restart sequence
                i2c_write(0xD1); // set bit R/W - Read from 24C04
                byte1 = i2c_read();
                byte2 = i2c_read();
                byte3 = i2c_read();
                i2c_stop(); // send stop sequence
                }
                }*/

                Tôi có một vài thắc mắc trong mấy đoạn code đã được post lên, mong các cao nhân giải đáp thắc mắc giùm:
                1/ Trong đoạn của hàm MAIN như trích dưới đây:
                void main()
                {
                unsigned char byte1,byte2,byte3,address_for_firstbyte_read;
                while(1)
                {
                // Ghi du lieu vao 24C04
                i2c_start(); // send start sequence
                i2c_write(0xD0); // Gui dia chi cua 24C04 voi bit RW = 0
                i2c_write(0x01); // Dia chi vi tri ROM can ghi du lieu
                i2c_write(byte1); // Cac byte tiep theo, thanh ghi xac dinh dia chi se tu tang len 1
                i2c_write(byte2);
                i2c_write(byte3);
                i2c_write(0xAA);
                i2c_stop();
                i2c_start();
                i2c_write(0xD0);
                i2c_write(address_for_firstbyte_read);
                i2c_start(); // send a restart sequence
                i2c_write(0xD1); // set bit R/W - Read from 24C04
                byte1 = i2c_read();
                byte2 = i2c_read();
                byte3 = i2c_read();
                i2c_stop(); // send stop sequence
                }
                }

                Sau thủ tục khởi đầu (i2c_start)-đã thực hiện là đến byte "lệnh"-(DEVICE ADDRESS) bao gồm 8-bit: 1010-A2-A1-A0-R/W. Giả sử địa chỉ "cứng" của EEPROM là 0 (trường hợp chỉ có 1 chú duy nhất) thì giá trị tham số truyền cho (i2c_write(...)) sẽ là:
                - 0xA0 thay vì 0xD0 (lệnh ghi vào EEPROM: 1-0-1-0-0-0-0-0 --> R/W=0)
                - 0xA1 thay vì 0xD1 (lệnh đọc từ EEPROM: 1-0-1-0-0-0-0-1 --> R/W=1)

                Nếu 0xD0 --> giá trị truyền lần lượt sẽ là 1-1-0-1-0-0-0-0 (4 bit đầu không đúng 1010)
                Nếu 0xD1 --> giá trị truyền lần lượt sẽ là 1-1-0-1-0-0-0-1


                2/. Về vấn đề kiểm soát xung báo nhận:

                Trích datasheet:
                ACKNOWLEDGE: All addresses and data words are serially transmitted to and from the
                EEPROM in 8-bit words. The EEPROM sends a zero to acknowledge that it has
                received each word. This happens during the ninth clock cycle.

                Như vậy sau mỗi thao tác ghi/đọc vao EEPROM đều cần thiết phải kiểm soát xung báo nhận (ACK) từ EEPROM gửi về (Slave-->Master)
                Theo ý kiến của tôi trong đoạn cuối mỗi hàm (i2c_write) và (i2c_read) có thể sửa lại như sau được không:
                Thay vì đoạn:
                SDA = 1;
                scl_high ();
                databit = SDA;
                scl_low ();
                return (databit);

                Để kiểm tra xung báo nhận ACK (ở xung clock thứ 9), nếu EEPROM vẫn "bận", chưa thực hiện xong các thao tác (ghi/hoặc đọc) thì liên tục kiểm tra xung báo ACK cho đến khi ACK=0 thì mới thực hiện (ghi/hoặc đọc) các byte tiếp theo (thay vì return)
                databit = SDA;
                while(databit)
                {
                scl_high ();
                databit = SDA;
                scl_low ();
                }

                Trên đây là 2 thắc mắc của tôi, rất mong được giải đáp, đặc biệt là các tác giả đã thành công và có kinh nghiệm với I2C Bus

                Comment


                • #9
                  bit i2c_write (unsigned char dulieu) { //ham nay goi 1 byte den 24c04
                  unsigned char i; // neu ket qua (bit ack) = 0:du lieu truyen dung
                  bit databit; // con bang 1 thi sai.
                  for (i=0;i<=7;i++) {
                  databit = dulieu & 0x80;
                  SDA = databit;
                  dulieu = dulieu << 1;
                  scl_high ();
                  scl_low ();
                  }
                  SDA = 1;
                  scl_high ();
                  databit = SDA;
                  scl_low ();
                  return (databit);
                  }

                  Chao bac Giaosucan, e co the viet ham i2c_write cua bac lai nhu the nay co duoc khong nhe. Mong cac bac cho y kien:

                  bit i2c_write (unsigned char dulieu) { //ham nay ghi 1 byte den 24c04
                  unsigned char i; // neu ket qua (bit ack) = 0:du lieu truyen dung
                  bit databit; // con bang 1 thi sai.
                  for (i=0;i<=7;i++) {
                  if(dulieu & 0x80)
                  SDA=1;
                  else SDA=0;
                  dulieu = dulieu << 1;
                  scl_high ();
                  scl_low ();
                  }
                  SDA = 1;
                  scl_high ();
                  databit = SDA;
                  scl_low ();
                  return (databit);
                  }

                  Comment


                  • #10
                    Nguyên văn bởi thuaimi Xem bài viết
                    Tôi có một vài thắc mắc trong mấy đoạn code đã được post lên, mong các cao nhân giải đáp thắc mắc giùm:
                    1/ Trong đoạn của hàm MAIN như trích dưới đây:
                    void main()
                    {
                    unsigned char byte1,byte2,byte3,address_for_firstbyte_read;
                    while(1)
                    {
                    // Ghi du lieu vao 24C04
                    i2c_start(); // send start sequence
                    i2c_write(0xD0); // Gui dia chi cua 24C04 voi bit RW = 0
                    i2c_write(0x01); // Dia chi vi tri ROM can ghi du lieu
                    i2c_write(byte1); // Cac byte tiep theo, thanh ghi xac dinh dia chi se tu tang len 1
                    i2c_write(byte2);
                    i2c_write(byte3);
                    i2c_write(0xAA);
                    i2c_stop();
                    i2c_start();
                    i2c_write(0xD0);
                    i2c_write(address_for_firstbyte_read);
                    i2c_start(); // send a restart sequence
                    i2c_write(0xD1); // set bit R/W - Read from 24C04
                    byte1 = i2c_read();
                    byte2 = i2c_read();
                    byte3 = i2c_read();
                    i2c_stop(); // send stop sequence
                    }
                    }

                    Sau thủ tục khởi đầu (i2c_start)-đã thực hiện là đến byte "lệnh"-(DEVICE ADDRESS) bao gồm 8-bit: 1010-A2-A1-A0-R/W. Giả sử địa chỉ "cứng" của EEPROM là 0 (trường hợp chỉ có 1 chú duy nhất) thì giá trị tham số truyền cho (i2c_write(...)) sẽ là:
                    - 0xA0 thay vì 0xD0 (lệnh ghi vào EEPROM: 1-0-1-0-0-0-0-0 --> R/W=0)
                    - 0xA1 thay vì 0xD1 (lệnh đọc từ EEPROM: 1-0-1-0-0-0-0-1 --> R/W=1)

                    Nếu 0xD0 --> giá trị truyền lần lượt sẽ là 1-1-0-1-0-0-0-0 (4 bit đầu không đúng 1010)
                    Nếu 0xD1 --> giá trị truyền lần lượt sẽ là 1-1-0-1-0-0-0-1


                    2/. Về vấn đề kiểm soát xung báo nhận:

                    Trích datasheet:
                    ACKNOWLEDGE: All addresses and data words are serially transmitted to and from the
                    EEPROM in 8-bit words. The EEPROM sends a zero to acknowledge that it has
                    received each word. This happens during the ninth clock cycle.

                    Như vậy sau mỗi thao tác ghi/đọc vao EEPROM đều cần thiết phải kiểm soát xung báo nhận (ACK) từ EEPROM gửi về (Slave-->Master)
                    Theo ý kiến của tôi trong đoạn cuối mỗi hàm (i2c_write) và (i2c_read) có thể sửa lại như sau được không:
                    Thay vì đoạn:
                    SDA = 1;
                    scl_high ();
                    databit = SDA;
                    scl_low ();
                    return (databit);

                    Để kiểm tra xung báo nhận ACK (ở xung clock thứ 9), nếu EEPROM vẫn "bận", chưa thực hiện xong các thao tác (ghi/hoặc đọc) thì liên tục kiểm tra xung báo ACK cho đến khi ACK=0 thì mới thực hiện (ghi/hoặc đọc) các byte tiếp theo (thay vì return)
                    databit = SDA;
                    while(databit)
                    {
                    scl_high ();
                    databit = SDA;
                    scl_low ();
                    }

                    Trên đây là 2 thắc mắc của tôi, rất mong được giải đáp, đặc biệt là các tác giả đã thành công và có kinh nghiệm với I2C Bus
                    Mình cũng đồng ý với bạn về việc xung ACK ở tác vụ write và cũng sử dụng phuơng pháp đọc ACK và việc này đều thành công,nhưng cần lưu ý bạn là đối với trường hợp cụ thể là AT24C04 thì thời gian bận là sau khi Chip phát xung ACK lúc đó EEPROM mới ghi các dữ liệu vào trong ram không mất nội dung Twr( time write cycle) nên việc bạn đọc xung ACK cũng không có ý nghĩa sau khi truyền data.
                    Code:
                    	//thả nổi cổng
                    	SDA=1;
                    	SCL=1;
                    	//
                    	delay_i2c();
                    	while(SCL==0);//đợi xung ACK từ phía slave
                    	ACK=SDA;
                    	SCL=0;//pull down all line

                    Sông dài, Thuyền lớn, Biển rộng bao la.
                    Tháo neo ngôn ngữ, lèo lái con thuyền kiến thức nhân loại.

                    Comment


                    • #11
                      qua dai dong sao cac bac khong viet theo DATASHEET cua no co fai do don khong

                      Comment


                      • #12
                        bac GIAO SU CAN oi em van chua hieu tai sao bac lai fai lam la "tha noi cong "
                        ma bac da lam voi SPI chua bao cho em voi

                        Comment


                        • #13
                          Xin trả lời dùm mình với

                          for (i=0;i<=7;i++) {
                          databit = dulieu & 0x80;
                          SDA = databit;
                          dulieu = dulieu << 1;
                          scl_high ();
                          scl_low ();
                          }
                          Mọi người có thể giải thích rõ hơn cho mình đoạn code này ko, đặc biệt databit=dulieu&0x80.
                          xin cảm ơn

                          Comment

                          Về tác giả

                          Collapse

                          trongnghia85 Tìm hiểu thêm về trongnghia85

                          Bài viết mới nhất

                          Collapse

                          Đang tải...
                          X