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)
-   -   hỏi về giao tiếp I2C (http://www.picvietnam.com/forum/showthread.php?t=2784)

toanck86 05-09-2008 03:22 PM

hỏi về giao tiếp I2C
 
Chào các bạn!
Mình đang gặp khó khăn trong giao tiếp I2C. Bài toán của mình là giao tiếp giữa 2 con PIC 16F877A. Khi mình sử dụng thạch anh 4 Mhz thì nó chạy tốt. Nhưng khi thay con thạch anh 20 Mhz thì không còn chạy được nữa

code master:
Code:

#include <16F877A.H>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use Delay(Clock=20000000)
#use i2c(master, sda=PIN_C4, scl=PIN_C3)

void write_I2C(int8 value, int8 slave_addr)
{
  i2c_start();
  delay_ms(1);
  i2c_write(slave_addr);
  delay_ms(1);
  i2c_write(value);
  delay_ms(1);
  i2c_stop();
}

int8 read_I2C(int8 slave_addr)
{
  int8 value_re;
  i2c_start();
  delay_ms(1);
  i2c_write(slave_addr + 1);
  delay_ms(1);
  value_re = i2c_read(0);
  delay_ms(1);
  i2c_stop();
  return value_re;
}

void main()
{
  int8 value_re=2;
  int8 i;
  const int8 N = 8;
  const int8 slave_addr = 0x10;
  set_tris_b(0x00);
  while(1){
     
        write_I2C(1, slave_addr);
        delay_ms(500);
        value_re = read_I2C(slave_addr);
        output_b(value_re);
        delay_ms(500);
          write_I2C(0, slave_addr);
        delay_ms(500);
        value_re = read_I2C(slave_addr);
        output_b(value_re);
        delay_ms(500);
    }
}

************************************************** ***********
code slave:
Code:

#include <16F877A.H>
#fuses XT,NOWDT,NOPROTECT,NOLVP

#use delay(Clock=20000000)
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0x10)

int8 value = 0x01;

#INT_SSP
void i2c_isr()
{
  int8 state;

  state = i2c_isr_state();
  if(state < 0x80 && state>0)
      value = i2c_read();
  if(state == 0x80){
      i2c_write(value);
  }
}

void main()
{
 
  enable_interrupts(INT_SSP);
  enable_interrupts(GLOBAL);
  set_tris_b(0x00);
  while(1){
      output_b(value);
  }
}

//xin loi vi chua cho code vao khung duoc, mong cac ban thong cam. Giup minh nha!

namqn 05-09-2008 04:32 PM

Với thạch anh 20 MHz, bạn nên dùng HS thay vì XT cho cấu hình bộ dao động.

Thân,

toanck86 07-09-2008 01:06 AM

Chào các bạn!
Mình muốn hỏi thêm các bạn một vấn đề nữa trong giao tiếp I2C. Bài toán của mình vẫn như trên (giao tiếp giữa 2 con PIC 16F877A). Cho hỏi hàm i2c_isr_state() khi nào trả giá trị về 1,2... 0x81,0x82...Mình mới chỉ thành công khi giao tiếp 1 lần truyền 1 byte, còn 2 byte thì không đúng, code truyền 2 byte:
code master:
Code:

#include <16F877A.H>
#include <def_877a.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use Delay(Clock=20000000)
#define use_portd_lcd TRUE
#include <lcd.c>
//#include <toanlcd.c>
#use i2c(master, sda=PIN_C4, scl=PIN_C3)
int8 value_re,value_re1,value_re2;
void write_I2C(int8 value, int8 slave_addr)
{
  i2c_start();
  delay_ms(1);
  i2c_write(slave_addr);
  delay_ms(1);
  i2c_write(value);
  delay_ms(1);
  i2c_stop();
}

void read_I2C(int8 slave_addr)
{
  i2c_start();
  delay_ms(1);
  i2c_write(slave_addr + 1);
  delay_ms(1);
  value_re1 = i2c_read(0);
  delay_ms(1);
  value_re2 = i2c_read(0);
  delay_ms(1);
  i2c_stop();
   
}

void main()
{
  int8 value_re=2;
  int8 i=10;
  const int8 N = 8;
  const int8 slave_addr = 0x10;
  set_tris_b(0x00);
  trisd=0;
  rd3=0;
  LCD_init();
  delay_ms(200);
  lcd_send_byte(0,0x1);
  while(1){
       
        read_I2C(slave_addr);
        lcd_send_byte(0,0x1);
        delay_ms(10);
        lcd_gotoxy(1,1);
        Printf(LCD_putc,"so1:%u\nso2:%u",value_re1,value_re2);
        delay_ms(400);
       
    }
}
//************************************************

code slave:
#include <16F877A.H>
#fuses HS,NOWDT,NOPROTECT,NOLVP

#use delay(Clock=20000000)
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0x10)
int8 bang[]={3,4,5,6};
int8 value = 0x01,valueh=0,valuel=0;

#INT_SSP
void i2c_isr()
{
  int8 state;
  state = i2c_isr_state();
  if(state >= 0x80)i2c_write(bang[state - 0x80]);
   
}

void main()

  enable_interrupts(INT_SSP);
  enable_interrupts(GLOBAL);
  set_tris_b(0x00);
  while(1);
}

/*kết quả nhận được là trên màn hình LCD: so1:3; so2:255.
Giúp mình nha!
// mình vẫn chưa cho code vào trong khung được:D

namqn 07-09-2008 02:36 AM

Trích:

Nguyên văn bởi toanck86 (Post 18686)
...
// mình vẫn chưa cho code vào trong khung được:D

Bạn đọc hướng dẫn trong luồng sau:
http://www.picvietnam.com/forum/showthread.php?t=2610

Thân,

toanck86 08-09-2008 10:32 AM

Chào các bạn!
Mình đã giải quyết được vấn đề trên. Mình gửi 4 số từ Master đến Slave và nhận lại về 4 số đó, cho hiển thị lên LCD. Ai có cách khác thì post lên cho mọi người cùng tham khảo nhé
code master:
Code:

#include <16F877A.H>
#include <def_877a.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use Delay(Clock=20000000)
#define use_portd_lcd TRUE
#include <lcd.c>
//#include <toanlcd.c>
#use i2c(master, sda=PIN_C4, scl=PIN_C3)
int8 value_re,value_re1=0,value_re2=0,value_re3=0,value_re4=0;
void write_I2C(int8 value1,int8 value2,int8 value3,int8 value4,int8 slave_addr)
{
  i2c_start();
  i2c_write(slave_addr);
  i2c_write(value1);
  i2c_write(value2);
  i2c_write(value3);
  i2c_write(value4);
  i2c_start();
  i2c_write(slave_addr);
  i2c_stop();
}

void read_I2C()
{
  i2c_start();
  i2c_write(0x11);
  value_re1 = i2c_read();
  value_re2 = i2c_read();
  value_re3 = i2c_read();
  value_re4 = i2c_read();
  i2c_start();
  i2c_write(0x11);
  i2c_stop();
}

void main()
{
  int8 value_re=2;
  int8 i=10;
  const int8 N = 8;
  const int8 slave_addr = 0x10;
  set_tris_b(0x00);
  trisd=0;
  rd3=0;
  LCD_init();
  delay_ms(200);
  lcd_send_byte(0,0x1);
  while(1){
        write_I2C(1,2,3,4,0x10);
        delay_ms(10);
        read_I2C();
        lcd_send_byte(0,0x1);
        delay_ms(1);
        lcd_gotoxy(1,1);
        Printf(LCD_putc,"so1:%u so2:%u\nso3:%u so4:%u",value_re1,value_re2,value_re3,value_re4);
        delay_ms(500);
       
        write_I2C(5,6,7,8,0x10);
        delay_ms(10);
        read_I2C();
        lcd_send_byte(0,0x1);
        delay_ms(1);
        lcd_gotoxy(1,1);
        Printf(LCD_putc,"so1:%u so2:%u\nso3:%u so4:%u",value_re1,value_re2,value_re3,value_re4);
        delay_ms(500);
    }
}

code slave:
Code:

#include <16F877A.H>
#fuses HS,NOWDT,NOPROTECT,NOLVP

#use delay(Clock=20000000)
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0x10)
int8 bang[4];
int8 value = 0x01,valueh=0,valuel=0;
int8 state;
#INT_SSP
void i2c_isr()
{
  state = i2c_isr_state();
  if(state >=0x80)i2c_write(bang[state-0x80]);
  else if(state>0)bang[state-1]=i2c_read();
}

void main()

  enable_interrupts(INT_SSP);
  enable_interrupts(GLOBAL);
  set_tris_b(0x00);
  while(1);
}


success.tl 24-10-2009 06:02 PM

...............
void main()
{
int8 value_re=2;
int8 i=10;
const int8 N = 8;
const int8 slave_addr = 0x10;
set_tris_b(0x00);
trisd=0;
rd3=0;
...............
Các bạn cho mình hỏi trong chương trình của bạn toanck86:
* Biến i, N dùng để làm gì?
* rd3=0 có ý nghĩa gì vậy nhỉ?


Múi giờ GMT. Hiện tại là 11:12 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