RP Store Tìm linh kiện theo mã, gửi BOM nhận báo giá Gửi BOM

Giao tiếp I2C

Collapse
This is a sticky topic.
X
X
 
  • Giờ
  • Show
Clear All
new posts
  • falleaf
    PIC Bang chủ
    • May 2005
    • 2627

    #1

    Giao tiếp I2C

    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
    Attached Files
    Công ty TNHH Thương mại và Giao nhận R&P
    store.hn@rpc.vn - store.hcm@rpc.vn

    Học PIC như thế nào?
  • bien_van_khat
    ...Damned...
    • Apr 2006
    • 503

    #2
    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 ), 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 ). Không biết mọi người đọc như thế nào nhỉ?
    - Xin đọc trước khi post bài

    Xin đặt code trong thẻ [ code ] [ /code ]

    Comment

    • namqn
      Trưởng lão PIC bang
      • Feb 2006
      • 3020

      #3
      Nguyên văn bởi bien_van_khat View Post
      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 ), 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 ). 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,
      Biển học mênh mông, sức người có hạn.

      Đang gặp vấn đề cần được giúp đỡ? Hãy dành ra vài phút đọc luồng sau:
      http://www.picvietnam.com/forum/showthread.php?t=1263

      Comment

      • falleaf
        PIC Bang chủ
        • May 2005
        • 2627

        #4
        Nguyên văn bởi bien_van_khat View Post
        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 ), 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 ). 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.
        Công ty TNHH Thương mại và Giao nhận R&P
        store.hn@rpc.vn - store.hcm@rpc.vn

        Học PIC như thế nào?

        Comment

        • thanhha
          Nhập môn đệ tử
          • Sep 2006
          • 9

          #5
          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) {}
          }
          Last edited by falleaf; 13-09-2006, 03:49 PM.

          Comment

          • thanhha
            Nhập môn đệ tử
            • Sep 2006
            • 9

            #6
            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!!

            Comment

            • hoanf
              Đệ tử 3 túi
              • Jun 2006
              • 51

              #7
              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

              Comment

              • thanhha
                Nhập môn đệ tử
                • Sep 2006
                • 9

                #8
                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

                Comment

                • hoanf
                  Đệ tử 3 túi
                  • Jun 2006
                  • 51

                  #9
                  Chào bạn.
                  Bạn có thể tải bản V3.249 ở đây


                  hoanf

                  Comment

                  • thanhha
                    Nhập môn đệ tử
                    • Sep 2006
                    • 9

                    #10
                    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 :
                    Attached Files
                    Last edited by thanhha; 14-09-2006, 04:53 PM. Lý do: thêm mạch

                    Comment

                    • falleaf
                      PIC Bang chủ
                      • May 2005
                      • 2627

                      #11
                      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.
                      Công ty TNHH Thương mại và Giao nhận R&P
                      store.hn@rpc.vn - store.hcm@rpc.vn

                      Học PIC như thế nào?

                      Comment

                      • hoanf
                        Đệ tử 3 túi
                        • Jun 2006
                        • 51

                        #12
                        :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
                        Last edited by hoanf; 15-09-2006, 09:00 AM.

                        Comment

                        • hoanf
                          Đệ tử 3 túi
                          • Jun 2006
                          • 51

                          #13
                          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);      
                             }
                          }
                          Last edited by hoanf; 15-09-2006, 11:40 AM.

                          Comment

                          • thanhha
                            Nhập môn đệ tử
                            • Sep 2006
                            • 9

                            #14
                            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 !!
                            Last edited by thanhha; 14-09-2006, 05:11 PM. Lý do: Canh lề

                            Comment

                            • falleaf
                              PIC Bang chủ
                              • May 2005
                              • 2627

                              #15
                              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.
                              Công ty TNHH Thương mại và Giao nhận R&P
                              store.hn@rpc.vn - store.hcm@rpc.vn

                              Học PIC như thế nào?

                              Comment

                              Working...