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

                          • vi van pham
                            Trả lời cho Tiếng Anh cho người Việt
                            bởi vi van pham
                            Cám ơn những lời chúc tốt đẹp của em.

                            Việc em làm giống như chê sếp dốt, chẳng những không có miếng xôi nào để ăn mà còn chịu nhiều trù dập lên bờ , xuống ruộng.

                            Hãy tránh vết xe đổ của tui đi. Dành thời gian lo cho gia đình....
                            hôm nay, 02:00
                          • nhathung1101
                            Trả lời cho Tiếng Anh cho người Việt
                            bởi nhathung1101
                            Ngoại ngữ là không thể thiếu, nhất là làm việc với công nghệ.

                            Nhưng học để tán gái hay để đọc datasheet, manual là chuyện cần quan tâm.

                            Và đọc ở nguồn nào đáng tin cậy, chứ cứ lên tictok hay facebook học lỏm thì...
                            Hôm qua, 22:18
                          • dinhthuong80
                            Trả lời cho Tiếng Anh cho người Việt
                            bởi dinhthuong80
                            Bác nói rất khách quan và chính xác. Ngoại ngữ là chìa khóa thăng tiến dù làm gì. Chả thế mà nay nước mình dạy tiếng Anh từ tiểu học.

                            Nhớ hồi năm 2006 em ra Hải Phòng, Hải Dương tìm việc, thời đó ở Bình Dương lương công...
                            Hôm qua, 14:51
                          • dinhthuong80
                            Trả lời cho Tiếng Anh cho người Việt
                            bởi dinhthuong80
                            Cảm ơn bạn, ĐT cũng có ý nghĩ như vậy.

                            Thực ra, lỗi của hãng đó ( gọi là hãng vì không chỉ một model sản phẩm) là về phần cứng, ĐT tuy không biết về lập trình phần mềm nhưng cũng thấy rằng sẽ chẳng khó khăn gì đáng...
                            Hôm qua, 14:39
                          • dinhthuong80
                            Trả lời cho Tiếng Anh cho người Việt
                            bởi dinhthuong80
                            Dạ, bác bảy mấy tuổi đời rồi cũng không kém bố cháu bao nhiêu. Tuổi nghề thì bác cũng đáng tuổi cha chú.

                            Nhưng 2 điều trên thì chưa hẳn đã đáng quí và đáng tôn trọng bằng việc bác rất nhiệt tình chia sẻ kinh nghiệm chuyên...
                            Hôm qua, 14:28
                          • bqviet
                            Trả lời cho Tiếng Anh cho người Việt
                            bởi bqviet
                            Đúng, nếu chú tâm thì chỉ cần mỗi tiếng Việt là đã khá đủ để làm đa số công việc thông thường, ở thời đại ngày nay khi tài liệu sách vở phương tiện thông tin liên lạc đã nhiều. Nhưng cũng chính ở thời nay giao lưu các nước nhiều...
                            21-02-2025, 20:26
                          • mèomướp
                            Trả lời cho Tiếng Anh cho người Việt
                            bởi mèomướp
                            Dạ cháu nghĩ chú dinh... cứ mạnh dạn gửi thư đi ạ, chú có thể gửi bằng văn bản in chuyển phát nhanh sẽ có giá trị hơn. Vấn đề chưa hẳn là cần hãng làm gì đó, mà chỉ đơn giản là mình cảm thấy nhẹ lòng vì đã làm những việc bản...
                            21-02-2025, 12:32
                          • vi van pham
                            Trả lời cho Tiếng Anh cho người Việt
                            bởi vi van pham
                            Những lần hắt hơi sổ mũi làm tôi mệt lã, phải dùng rượu uống để ngũ. Tôi cũng đang uống rượu 1 mình, viết vài dòng này cho em ( có lẽ dt chỉ bằng tuổi em tôi).

                            Dinh thuong dang đi vào vết xe đổ của tôi. Càng chứng minh, có...
                            20-02-2025, 21:31
                          • bqviet
                            Trả lời cho Hỏi về cách hàn linh kiện ( giúp tớ với )
                            bởi bqviet
                            Thiết nghĩ thi thoảng bác lên đây chia xẻ ít kinh nghiệm cũng vui rồi. Còn chuyện con người sinh lão bệnh tử là thường, sống cùng với quy luật đó thôi. Bqv nhớ trước đây bác từng kể về chuyện rang chì ô-xít bằng chảo để phục hồi bình điện, đấy cũng là thành quả đáng nể phục ở thời kỳ thiếu thốn đó.
                            20-02-2025, 17:22
                          • dinhthuong80
                            Trả lời cho Tiếng Anh cho người Việt
                            bởi dinhthuong80
                            Tiếng Anh, Đình Thường phải nói là rất tệ, khiến việc giao tiếp đời thường thôi cũng khó chứ nói gì về kĩ thuật.

                            Nhân tiện, nhờ các bạn, các bác xem giúp thư ĐT viết thế này liệu có thể gửi tới địa chỉ nhận hay chăng,...
                            20-02-2025, 11:52
                          Đang tải...
                          X