Giao tiếp I2C

Collapse
This is a sticky topic.
X
X
 
  • Giờ
  • Show
Clear All
new posts
  • khienpzo
    Đệ tử 5 túi
    • Sep 2010
    • 107

    #196
    Giao tiếp I2C điều khiển động cơ DC

    Em có một đề tài về I2C rất mong được sự chia sẻ của các anh chị đi trước ạ . EM có 2 PIC 16f877a giao tiếp I2C để điều khiển tốc độ or vị trí động cơ DC . PICA : Bàn phím nhập thông số tốc độ or vị trí (góc quay) . PICB : điều khiển động cơ DC và hiển thị thông số trên led 7 đoạn. Em mới bắt tay vào làm nên còn nhiều bỡ ngỡ mong các anh chị chỉ giáo . Em xin chân thành cảm ơn

    Comment

    • nguyenthangcdt
      Đệ tử 1 túi
      • Apr 2012
      • 16

      #197
      Nguyên văn bởi thanhha View Post
      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 !!
      bạn ơi cho mình hỏi là tai sao trong hàm "read_i2c()" tai sao i2c_write(SLAVE_ADDRESS + 1) ! mình khboong hiểu chỗ " SLAVE_ADDRESS + 1 " BẠN LAMMFOWN GIẢI THÍCH HỘ MÌN ĐƯỢC KHÔNG ! VÀ NẾU BẠN CÓ CHƯƠNG TRÌNH NÀO MÀ VBIEECJ ĐỌC VÀ TRUYỀN DỮ LIỆU ĐỒNG THỜI THÌ CHO MÌNH XIN THAM KHẢO NHÉ ! MÌNH CẢM ƠN CẬU TRƯỚC NHÉ HJ !

      Comment

      • nguyenthangcdt
        Đệ tử 1 túi
        • Apr 2012
        • 16

        #198
        Nguyên văn bởi hoanf View Post
        Chào các bạn!!
        Cho mình post sơ đồ và code của minh lên đây cho các bạn coi và có gì góp ý cho mình nha.

        Đây là đoạn code Master: Master truyền một mảng cho Slave và nhận về mảng mà đã chuyển cho Slave để hiển thị lên port_b(kiểm tra hihi...) giống echo.

        Code:
        #include <16F877A.H>
        #fuses XT,NOWDT,NOPROTECT,NOLVP
        #use Delay(Clock=4000000)
        
        #use i2c(master, sda=PIN_C4, scl=PIN_C3, force_hw)
        
        void write_I2C(int8 value, int8 slave_addr)
        {
           i2c_start();
           i2c_write(slave_addr);
           i2c_write(value);
           i2c_stop();
        }
        
        int8 read_I2C(int8 slave_addr)
        {
           int8 value_re;
           i2c_start();
           i2c_write(slave_addr + 1);
           value_re = i2c_read(0);
           i2c_stop();
           return value_re;
        }
        
        void main()
        {
           int8 value_re;
           int8 i;
           const int8 N = 8;
           const int8 DIGITS[N] ={ 0b11111111,
                                   0b11111110,
                                   0b11111100,
                                   0b11111000,
                                   0b11110000,
                                   0b11100000,
                                   0b11000000,
                                   0b10000000,
                                  };
           const int8 slave_addr = 0x10;
        
           set_tris_b(0x00);
           while(1){
              for(i = 0; i<8; i++){
                 write_I2C(DIGITS[i], slave_addr);
                 delay_ms(500);
                 value_re = read_I2C(slave_addr);
                 output_b(value_re);
              }
           }
        }
        Còn đây là đoạn code Slave:

        Code:
        #include <16F877A.H>
        #fuses XT,NOWDT,NOPROTECT,NOLVP
        
        #use delay(Clock=4000000)
        #use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0x10, force_hw)
        
        int8 value = 0x01;
        
        #INT_SSP
        void i2c_isr()
        {
           int8 state;
        
           state = i2c_isr_state();
           if(state < 0x80)
              value = i2c_read();
           if(state == 0x80){
              i2c_write(value);
           }
        }
        
        void main()
        {
           enable_interrupts(GLOBAL);
           enable_interrupts(INT_SSP);
        
           set_tris_b(0x00);
           while(1){
              output_b(value);
           }
        }
        minhf copy rooif paste vao nhuwng khoong chayj banj ah

        Comment

        • khienpzo
          Đệ tử 5 túi
          • Sep 2010
          • 107

          #199
          Có ai viết vòng lặp đọc dữ liệu 2 Slave về Master chạy ok rồi không ạ ? Cho mình tham khảo với

          Comment

          • thegioimoiqb
            Nhập môn đệ tử
            • Mar 2012
            • 3

            #200
            Mấy anh ơi, cho em hỏi: Chương trình của em tự viết không nói. em đưa y nguyên ct của đồng chí hoanf vào CCS 4.038 rùi mà PIN RC3 và RC4 cứ nhấp nháy hoài. master không nhận được dữ liệu từ slave. Mong các bác sớm chỉ rõ cho e. (nói thật vì cái đồ án, e mất ngủ cả đêm nay rùi mà vẫn chưa tìm ra lỗi tại sao. Có khi viết lại toàn bộ asm mà cũng chung một kết quả _ thi thoảng truyền được địa chỉ nhận về được ack nhưng đến lượt đọc thì im lim)
            đây là code của master:
            #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)
            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);
            //LCD_gotoxy(1,1);
            //printf(LCD_putc,"gtri: %3u",value);
            delay_ms(500);
            }
            }
            đây là code của slave:
            #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);
            }
            }

            NÓ không chạy, em bắt đầu tin vào ma quỷ rùi đây. Sao máy các anh chạy máy em lại không? hay tại trình biên dịch nhỉ.

            Comment

            • hatuan296
              Làm quen với PIC
              • Oct 2005
              • 160

              #201
              Bạn kiểm tra xem 2 con điện trở kéo lên của các chân SDA , SCL có bị lỏng không

              Comment

              • thegioimoiqb
                Nhập môn đệ tử
                • Mar 2012
                • 3

                #202
                Em đang mô phỏng bằng protues thôi anh ah. Có tin được thằng PROTUES k anh nhị.

                Comment

                • hatuan296
                  Làm quen với PIC
                  • Oct 2005
                  • 160

                  #203
                  Nguyên văn bởi thegioimoiqb View Post
                  Em đang mô phỏng bằng protues thôi anh ah. Có tin được thằng PROTUES k anh nhị.
                  Mô phỏng về thời gian , timer ,vv... thì không chính xác lắm đâu . Tốt nhất là bạn dùng bread board để test

                  Comment

                  • thegioimoiqb
                    Nhập môn đệ tử
                    • Mar 2012
                    • 3

                    #204
                    thanks u ! ko mô phỏng trên phần mềm dùng phần cứng thì hơi đau phần cứng do các lỗi.

                    Comment

                    • khienpzo
                      Đệ tử 5 túi
                      • Sep 2010
                      • 107

                      #205
                      Mô phỏng chạy nhưng ra phần cứng chưa chắc chạy đâu bạn. Thân

                      Comment

                      • copchaua
                        Nhập môn đệ tử
                        • Sep 2011
                        • 5

                        #206
                        đã viết code nhận và gửi 2 byte cho từ 1 master và 2 slave chạy good

                        Comment

                        • copchaua
                          Nhập môn đệ tử
                          • Sep 2011
                          • 5

                          #207
                          Các bạn lưu ý khi dùng Pic 18F4431 và trình dịch CCS thì khi giao tiếp I2C mặc dù trên code viết cho cả master và slaver dùng chân C4 và C5 nhưng khi ráp mạch thực tế thì trên master chúng ta nối chân C4,C5 và slaver là D2 và D3 thì mới chạy được nhé. Cái này không biết lỗi gì chắc là do CCS

                          Comment

                          • copchaua
                            Nhập môn đệ tử
                            • Sep 2011
                            • 5

                            #208
                            Code hoàn chỉnh đã test mạch thực tế giao tiếp giữa 1 master và 2 slaver, truyền và nhận 2 byte luôn, các bạn có thể tham khảo. Master sẽ gửi 1 số int16 (gừi từ 0, mỗi lần gửi xong tăng lên 1 đơn vị) xuống slave, slaver nhận được và gửi trở lại master. các bạn nhớ dùng Rs232 dọc về máy tính dể kiểm tra chính xác nhé

                            Code master:
                            #include <18f4431.h>
                            #include <def_4331.h>
                            #device 18f4431*=16 ADC=10
                            #include <stdlib.h> //tien xu li khi su dung ham ATOI()
                            #include <stdio.h> // for printf() call
                            #fuses nowdt,noprotect,nolvp,xt,put,hs
                            #use delay(clock=20000000)
                            #use rs232(baud=19200,parity=N,xmit=PIN_C6,rcv=PIN_C7,b its=8)
                            #define slave_address_1 0x10
                            #define slave_address_2 0x20
                            #use i2c(master, sda=PIN_C4, scl=PIN_C5)
                            #use fast_io(b)
                            #use fast_io(c)
                            #use fast_io(d)
                            #use fast_io(a)


                            void write_slave_1(int16 a)
                            { int8 hi,lo;
                            hi=make8(a,1);
                            lo=make8(a,0);
                            i2c_start();
                            i2c_write(slave_address_1);
                            delay_ms(1);
                            i2c_write(hi);
                            delay_ms(1);
                            i2c_write(lo);
                            i2c_stop();
                            }

                            void write_slave_2(int16 b)
                            {
                            int8 hi,lo;
                            hi=make8(b,1);
                            lo=make8(b,0);
                            i2c_start();
                            i2c_write(slave_address_2);
                            delay_ms(1);
                            i2c_write(hi);
                            delay_ms(1);
                            i2c_write(lo);
                            i2c_stop();
                            }


                            int16 read_slave_1()
                            {
                            int16 value_re_1;
                            int8 hi,lo;
                            i2c_start();
                            i2c_write(slave_address_1 + 1);
                            hi = i2c_read(1);
                            lo = i2c_read(0);
                            i2c_stop();
                            value_re_1 = make16(hi,lo);
                            return value_re_1;
                            }


                            int16 read_slave_2()
                            {
                            int16 value_re_2;
                            int8 hi,lo;
                            i2c_start();
                            i2c_write(slave_address_2 + 1);
                            hi = i2c_read(1);
                            lo = i2c_read(0);
                            i2c_stop();
                            value_re_2 = make16(hi,lo);
                            return value_re_2;
                            }



                            void main()
                            {
                            int16 value,value_re_1,value_re_2;
                            value = 0;

                            while(1)
                            {
                            write_slave_1(value);
                            write_slave_2(-value);
                            value++;
                            delay_ms(500);
                            value_re_1=read_slave_1();
                            value_re_2=read_slave_2();
                            printf("%ld",value_re_1);
                            printf(" ");
                            printf("%ld",value_re_2);
                            printf(" ");
                            delay_ms(100);
                            }
                            }

                            Code slaver 1:

                            #include <18f4431.h>
                            #include <def_4331.h>
                            #device 18f4431*=16 ADC=10
                            #include <stdlib.h> //tien xu li khi su dung ham ATOI()
                            #include <stdio.h> // for printf() call
                            #fuses nowdt,noprotect,nolvp,xt,put,hs
                            #use delay(clock=20000000)
                            #use rs232(baud=19200,parity=N,xmit=PIN_C6,rcv=PIN_C7,b its=8)
                            #use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C5, address=0x10)
                            #use fast_io(b)
                            #use fast_io(c)
                            #use fast_io(d)
                            #use fast_io(a)

                            boolean a;
                            int16 value;
                            int8 hi,lo;

                            #INT_SSP
                            void i2c_isr()
                            {
                            int8 state;
                            state = i2c_isr_state();
                            if (state<= 0x80)
                            {
                            if(state == 1 )
                            { hi = i2c_read(1);

                            }
                            if(state == 2)
                            { lo = i2c_read(1);
                            a=true;
                            }
                            }

                            if (state >= 0x80)
                            {
                            if(state==0x80)
                            i2c_write(hi);
                            if(state==0x81)
                            i2c_write(lo);
                            }

                            }



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

                            a=false;

                            while(1)
                            {
                            if (a==true)
                            {value=make16(hi,lo);
                            printf("%ld",value);
                            printf(" ");
                            a=false;
                            }
                            }
                            }


                            Code slave 2:

                            #include <18f4431.h>
                            #include <def_4331.h>
                            #device 18f4431*=16 ADC=10
                            #include <stdlib.h> //tien xu li khi su dung ham ATOI()
                            #include <stdio.h> // for printf() call
                            #fuses nowdt,noprotect,nolvp,xt,put,hs
                            #use delay(clock=20000000)
                            #use rs232(baud=19200,parity=N,xmit=PIN_C6,rcv=PIN_C7,b its=8)
                            #use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C5, address=0x20)
                            #use fast_io(b)
                            #use fast_io(c)
                            #use fast_io(d)
                            #use fast_io(a)

                            boolean a;
                            int16 value;
                            int8 hi,lo;

                            #INT_SSP
                            void i2c_isr()
                            {
                            int8 state;
                            state = i2c_isr_state();
                            if (state<= 0x80)
                            {
                            if(state == 1 )
                            { hi = i2c_read(1);

                            }
                            if(state == 2)
                            { lo = i2c_read(1);
                            a=true;
                            }
                            }

                            if (state >= 0x80)
                            {
                            if(state==0x80)
                            i2c_write(hi);
                            if(state==0x81)
                            i2c_write(lo);
                            }
                            }



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

                            a=false;

                            while(1)
                            {
                            if (a==true)
                            {value=make16(hi,lo);
                            printf("%ld",value);
                            printf(" ");
                            a=false;
                            }
                            }
                            }


                            CHÚC CÁC BẠN MAY MẮN

                            Comment

                            • duydien187
                              Nhập môn đệ tử
                              • May 2013
                              • 6

                              #209
                              cac bac cho em hoi la e dung con 16f685 hok co ngat SSP cho giao tiep I2C.e lai dang lam cai gaio tiep I2C giua 16f685 va PCF8583.. bac nao biet chi giao em vs. thanhks all

                              Comment

                              • BDA_6892
                                Nhập môn đệ tử
                                • May 2013
                                • 1

                                #210
                                i2c

                                mình viết y chang nhưng sao không mô phỏng được
                                chỗ code của slave , cuối cùng là output_b chứ hả, mình thấy giá trị output của slave lúc nào cũng là value=0x01 ban đầu.....không có sự thay đổi nên chắc chưa có giao tiếp giữa slave và master.

                                Comment

                                Working...