2011-09-21 33 views
6

Tôi đã đăng bài này một vài ngày trước trên Diễn đàn Microchip (here) nhưng câu trả lời duy nhất là dế. Mã I2C bên dưới hoạt động phần lớn thời gian nhưng đôi khi bật nguồn có một va chạm xe buýt (BCLIF) và mô-đun I2C không thể phục hồi sau BCLIF. Các dòng I2C được kéo lên bởi 3,3K ohms. Sử dụng REALICE và breakpoints Tôi có thể thấy rằng i2c_write() đặt lại BCLIF và trả về FALSE khi BCLIF được đặt. Tôi đã sử dụng phạm vi để xác minh rằng xe buýt I2C có lót bằng phẳng. Khởi tạo lại mô-đun I2C PIC18F25K20 (xem init_i2c() bên dưới) khi i2c_write() trả về FALSE không hiệu quả. PIC18F25K20 I2C được kết nối với một thiết bị nô lệ đơn (MCP4018 I2C Digital POT). Tôi đã sử dụng mã này trên các dự án PIC18 trước đó mà không có vấn đề vì vậy tôi thay thế MCP4018 nghi ngờ một phần xấu nhưng thấy không có sự khác biệt. Có cách nào để đặt lại mô-đun I2C PIC18F25K20 khi nó bị khóa không?Làm thế nào để phục hồi từ vụ va chạm xe buýt I2C BCLIF?

void init_i2c(I2C_BAUD_RATE baud_rate, float freq_mhz) 
{ 
    UINT32 freq_cycle; 
    /* Reset i2c */ 
    SSPCON1 = 0; 
    SSPCON2 = 0; 
    PIR2bits.BCLIF = 0; 
    /* Set baud rate */ 
    /* SSPADD = ((Fosc/4)/Fscl) - 1 */ 
    freq_cycle = (UINT32) ((freq_mhz * 1e6)/4.0); 
    if (baud_rate == I2C_1_MHZ) 
    { 
     SSPADD = (UINT8) ((freq_cycle/1000000L) - 1); 
     SSPSTATbits.SMP = 1;  /* disable slew rate for 1MHz operation */ 
    } 
    else if (baud_rate == I2C_400_KHZ) 
    { 
     SSPADD = (UINT8) ((freq_cycle/400000L) - 1); 
     SSPSTATbits.SMP = 0;  /* enable slew rate for 400kHz operation */ 
    } 
    else /* default to 100 kHz case */ 
    { 
     SSPADD = (UINT8) ((freq_cycle/100000L) - 1); 
     SSPSTATbits.SMP = 1;  /* disable slew rate for 1MHz operation */ 
    } 
    /* Set to Master Mode */ 
    SSPCON1bits.SSPM3 = 1; 
    SSPCON1bits.SSPM2 = 0; 
    SSPCON1bits.SSPM1 = 0; 
    SSPCON1bits.SSPM0 = 0; 
    /* Enable i2c */ 
    SSPCON1bits.SSPEN = 1; 
} 
BOOL i2c_write(UINT8 addr, const void *reg, UINT16 reg_size, const void *data, UINT16 data_size) 
{ 
    UINT16 i; 
    const UINT8 *data_ptr, *reg_ptr; 

    /* convert void ptr to UINT8 ptr */ 
    reg_ptr = (const UINT8 *) reg; 
    data_ptr = (const UINT8 *) data; 
    /* check to make sure i2c bus is idle */ 
    while ((SSPCON2 & 0x1F) | (SSPSTATbits.R_W)) 
     ; 
    /* initiate Start condition and wait until it's done */ 
    SSPCON2bits.SEN = 1; 
    while (SSPCON2bits.SEN) 
     ; 
    /* check for bus collision */ 
    if (PIR2bits.BCLIF) 
    { 
     PIR2bits.BCLIF = 0; 
     return(FALSE); 
    } 
    /* format address with write bit (clear last bit to indicate write) */ 
    addr <<= 1; 
    addr &= 0xFE; 
    /* send out address */ 
    if (!write_byte(addr)) 
     return(FALSE); 
    /* send out register/cmd bytes */ 
    for (i = 0; i < reg_size; i++) 
    { 
     if (!write_byte(reg_ptr)) 
      return(FALSE); 
    } 
    /* send out data bytes */ 
    for (i = 0; i < data_size; i++) 
    { 
     if (!write_byte(data_ptr)) 
      return(FALSE); 
    } 
    /* initiate Stop condition and wait until it's done */ 
    SSPCON2bits.PEN = 1; 
    while(SSPCON2bits.PEN) 
     ; 
    /* check for bus collision */ 
    if (PIR2bits.BCLIF) 
    { 
     PIR2bits.BCLIF = 0; 
     return(FALSE); 
    } 
    return(TRUE); 
} 
BOOL write_byte(UINT8 byte) 
{ 
    /* send out byte */ 
    SSPBUF = byte; 
    if (SSPCON1bits.WCOL)  /* check for collision */ 
    { 
     return(FALSE); 
    } 
    else 
    { 
     while(SSPSTATbits.BF) /* wait for byte to be shifted out */ 
      ; 
    } 
    /* check to make sure i2c bus is idle before continuing */ 
    while ((SSPCON2 & 0x1F) | (SSPSTATbits.R_W)) 
     ; 
    /* check to make sure received ACK */ 
    if (SSPCON2bits.ACKSTAT) 
     return(FALSE); 
    return(TRUE); 
} 
+1

Tôi không thể thấy mã nơi các chân SDA và SCL được định cấu hình làm đầu vào. –

+0

Bạn có thể thử trao đổi điều kiện bắt đầu và kiểm tra va chạm bus trong i2c_write() và thực thi hàm này vài lần liên tiếp với một số sự chậm trễ nhỏ giữa khi vấn đề này xảy ra? Chuyện gì xảy ra sau đó? –

+0

Ngoài ra, nó có thể thực sự tiện dụng nếu bạn có dao động với tự động kích hoạt, vì vậy bạn có thể theo dõi hành vi của dòng SDA sau khi bật nguồn là gì. Trạng thái Datasheet: * Nếu ở đầu điều kiện Khởi động, các chân SDA và SCL đã được lấy mẫu thấp hoặc nếu trong điều kiện Khởi động, dòng SCL được lấy mẫu thấp trước khi đường SDA được điều khiển xuống thấp, xảy ra va chạm trên xe buýt, Bus Interrupt Flag Flag, BCLIF, được thiết lập, điều kiện Start bị hủy bỏ và module I2C được reset về trạng thái Idle *. –

Trả lời

7

This Errata cần phải được thêm vào PIC18F25K20 Errata.

PIC18F2455/2550/4455/4550 Rev. A3 Silicon Errata

17 Module: MSSP

Nó đã được quan sát thấy rằng sau một-Power Reset, chế độ I2C có thể không khởi động đúng bởi chỉ cần cấu hình các chân SCL và SDA làm đầu vào hoặc đầu ra . Điều này chỉ được nhìn thấy trong một vài môi trường hệ thống duy nhất .

Một thử nghiệm của một mẫu ý nghĩa thống kê của hệ thống tiền sản xuất, phía bên kia điện áp và phạm vi hiện tại cấp điện các ứng dụng của, nên chỉ ra nếu một hệ thống dễ bị đến vấn đề này.

làm việc xung quanh

Trước khi cấu hình các module cho I2C hoạt động:

  1. Cấu hình SCL và SDA ghim như kết quả đầu ra bằng cách xóa tương ứng bit TRIS của họ.
  2. Lực lượng SCL và SDA thấp bằng cách xóa các bit LAT tương ứng.
  3. Trong khi vẫn giữ các bit LAT rõ ràng, hãy định cấu hình SCL và SDA làm đầu vào bằng cách đặt bit TRIS của chúng.

Sau khi hoàn tất, sử dụng thanh ghi SSPCON1 và SSPCON2 để định cấu hình chế độ I2C thích hợp như trước đây.

+0

Vì vậy, trình tự này có phù hợp với bạn không? –

+0

@AndrejsCainikovs: Có. Nó đã làm việc. Không thể chấp nhận câu trả lời này cho đến ngày mai. – jacknad

2

Lỗi này cũng giống như ocur trên PIC18F26K20/SS (Revision B3), cũng cần được thêm vào errata của nó.

2

Tôi không biết chi tiết cụ thể của bạn nhưng tôi đã gặp sự cố khi vi điều khiển sắp ra khỏi phương thức đặt lại sớm (nhiều trước khi Vdd được ổn định trên bus I2C). Vì vậy, các uController bắt đầu đọc/ghi dữ liệu trước khi mục tiêu có thể hoạt động đúng cách gây ra tất cả các loại vấn đề hoạt động I2C.

Các vấn đề liên quan