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)

khienpzo 27-07-2012 01:43 AM

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

nguyenthangcdt 05-10-2012 03:08 AM

Trích:

Nguyên văn bởi thanhha (Post 4938)
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 !

nguyenthangcdt 06-10-2012 08:44 AM

Trích:

Nguyên văn bởi hoanf (Post 4955)
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

khienpzo 27-11-2012 10:45 AM

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

thegioimoiqb 14-12-2012 10:39 AM

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ỉ.

hatuan296 14-12-2012 11:38 AM

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

thegioimoiqb 14-12-2012 01:57 PM

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

hatuan296 15-12-2012 04:23 AM

Trích:

Nguyên văn bởi thegioimoiqb (Post 80116)
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

thegioimoiqb 15-12-2012 12:43 PM

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. :(

khienpzo 15-12-2012 03:06 PM

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

copchaua 08-03-2013 11:16 AM

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

copchaua 08-03-2013 11:19 AM

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

copchaua 08-03-2013 11:26 AM

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

duydien187 03-06-2013 12:05 PM

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

BDA_6892 02-11-2013 06:01 PM

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.


Múi giờ GMT. Hiện tại là 10:49 AM.

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