2011-09-21 30 views
6

मैंने इसे कुछ दिन पहले माइक्रोचिप फोरम (here) पर पोस्ट किया था, लेकिन एकमात्र प्रतिक्रिया क्रिकेट रही है। नीचे आई 2 सी कोड ज्यादातर समय काम करता है लेकिन कभी-कभी पावर-अप पर बस टक्कर (बीसीएलआईएफ) होता है और आईसी 2 मॉड्यूल बीसीएलआईएफ के बाद ठीक होने में असमर्थ है। आई 2 सी लाइनों को 3.3 के ओएचएमएस द्वारा खींचा जाता है। रीयलिस और ब्रेकपॉइंट्स का उपयोग करके मैं देख सकता हूं कि i2c_write() बीसीएलआईफ़ को रीसेट करता है और बीसीएलआईफ़ सेट होने पर गलत होता है। मैंने यह सत्यापित करने के लिए एक दायरा का उपयोग किया है कि I2C बस में फ्लैट-रेखांकित है। PIC18F25K20 I2C मॉड्यूल को पुन: प्रारंभ करना (नीचे init_i2c() देखें) जब i2c_write() लौटाता है FALSE मदद नहीं करता है। PIC18F25K20 I2C एक एकल दास डिवाइस (एमसीपी 4018 आई 2 सी डिजिटल पीओटी) से जुड़ा हुआ है। मैंने पिछले पीआईसी 18 परियोजनाओं पर बिना किसी मुद्दे के इस कोड का उपयोग किया है, इसलिए मैंने एमसीपी 4018 को खराब हिस्से पर संदेह करने के लिए बदल दिया लेकिन कोई फर्क नहीं पड़ता। क्या यह लॉक होने पर PIC18F25K20 I2C मॉड्यूल को रीसेट करने का कोई तरीका है?आईसी 2 बस टक्कर बीसीएलआईएफ से कैसे ठीक हो सकता है?

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

मैं कोड जहां SDA और SCL पिन आदानों के रूप में विन्यस्त कर रहे हैं नहीं देख सकता। –

+0

आप() i2c_write में बस टक्कर के लिए शुरू हालत को शुरू करने तथा पहली जांच का आदान प्रदान कोशिश करते हैं और दोनों के बीच जब यह समस्या तब होती है में कुछ छोटे देरी के साथ एक पंक्ति में इस समारोह कई बार निष्पादित कर सकते हैं? फिर क्या होता है? –

+0

इसके अलावा, यदि आपके पास ऑटो-ट्रिगर के साथ ऑसिलोस्कोप है, तो यह वास्तव में आसान हो सकता है, ताकि आप पावर-अप के बाद एसडीए लाइन के व्यवहार की निगरानी कर सकें। डेटापत्रक कहता है: * प्रारंभ हालत की शुरुआत में, SDA और SCL पिन पहले से ही कम नमूने दिए जाते हैं, या यदि प्रारंभ हालत दौरान, SCL लाइन कम नमूना से पहले SDA लाइन कम संचालित है, एक बस की टक्कर होती है, बस टक्कर इंटरप्ट फ्लैग, बीसीएलआईएफ सेट है, स्टार्ट हालत निरस्त हो गई है और आई 2 सी मॉड्यूल अपने निष्क्रिय राज्य * में रीसेट हो गया है। –

उत्तर

7

This Errata को PIC18F25K20 इरेटा में जोड़ा जाना आवश्यक है।

PIC18F2455/2550/4455/4550 रेव ए 3 सिलिकॉन Errata

17 मॉड्यूल: MSSP

यह देखा गया है एक पॉवर-ऑन रीसेट, I2C मोड का पालन नहीं कर ठीक से से प्रारंभ हो सकता है कि बस एससीएल और एसडीए पिन को इनपुट या आउटपुट के रूप में कॉन्फ़िगर करना। यह केवल कुछ अद्वितीय सिस्टम वातावरण में देखा गया है।

पूर्व उत्पादन प्रणालियों के एक सांख्यिकीय महत्वपूर्ण नमूना का एक परीक्षण, वोल्टेज और आवेदन बिजली की आपूर्ति की वर्तमान श्रृंखला में, यह इंगित करना चाहिए अगर एक प्रणाली अतिसंवेदनशील इस मुद्दे पर है।

आसपास काम I2C ऑपरेशन के लिए मॉड्यूल को विन्यस्त करने से पहले:

  1. कॉन्फ़िगर उनके इसी TRIS बिट्स को साफ़ करके आउटपुट के रूप में SCL और SDA पिन।
  2. संबंधित एलएटी बिट्स को साफ़ करके एससीएल और एसडीए फोर्स कम करें।
  3. एलएटी बिट्स को स्पष्ट रखते हुए, एससीएल और एसडीए को अपने TRIS बिट्स सेट करके इनपुट के रूप में कॉन्फ़िगर करें।

इसके पूर्ण होते ही, SSPCON1 का उपयोग करें और SSPCON2 के रूप में करने से पहले उचित I2C मोड कॉन्फ़िगर करने के लिए पंजीकृत करता है।

+0

तो, क्या यह अनुक्रम आपके लिए काम करता है? –

+0

@AndrejsCainikovs: हाँ। इसने काम कर दिया। कल तक इस जवाब को स्वीकार नहीं कर सकते हैं। – jacknad

2

यह वही बग PIC18F26K20/SS (संशोधन बी 3) पर भी लग रहा है, इसे इसके इरेटा में भी जोड़ा जाना चाहिए।

2

मुझे आपके विनिर्देशों को नहीं पता है, लेकिन एक बार जब मैं माइक्रोकंट्रोलर रीसेट तरीके से बाहर आ रहा था (आईसीटी बस पर स्थिरता से पहले) से बाहर निकल रहा था, तो मैं एक समस्या में भाग गया। इसलिए यूकंट्रोलर ने लक्ष्य को ठीक से काम करने से पहले डेटा को पढ़ना/लिखना शुरू कर दिया था, जिससे सभी प्रकार के I2C परिचालन मुद्दों का कारण बन गया।