Ruani 2 bajt nga I2C Slave

duke luftuar me atë që është ndoshta një pjesë e drejtpërdrejtë e kodit për të kopjuar 2 bajt të marra nga një skllav I2C në një grup, në mënyrë që më pas të mund të konvertohem në INT dhe të kryej matematikë mbi të dhënat.

Ky kod me sukses (sipas analizuesit tim I2C) lexon 2 bajt të njëpasnjëshëm nga një adresë regjistri në një ADC 16 bit.

void ADC_Initialise( void )
{
    _DINT() ;                              // disable all maskable interrupts

    I2C_SCL_HIGH() ;
    I2C_SCL_OUTPUT() ;
    I2C_SDA_HIGH() ;
    I2C_SDA_OUTPUT() ;

    I2C_Write_Register_3B( ADC, 0x01, 0xC0, 0x83) ;  // Write 2 bytes to ADC Config Register

    for(i=0; i < 10000; i++);

    I2C_Read_Register( ADC, 0x00 );      // Read the 2 byte ADC value

    for(i=0; i < 10000; i++);
    _EINT() ;                             // re-enable the interrupts
}

static unsigned char I2C_Read_Register( char Device_Address, char Register_Address )

{
    unsigned char Value ;

    I2CM_Start( ) ;

    if( I2CM_Out( Device_Address << 1 ) )    //send write control byte + chip address
        return 0 ;

    else if( I2CM_Out( Register_Address ) )  //send register number
        return 0 ;

    I2CM_Start( ) ;                          // Restart

    if( I2CM_Out(( Device_Address << 1 ) | 0x01 ))      //send read control byte + chip address
    return 0 ;

    I2CM_In( &Value, 2 ) ;                    //RJ  6.8.19 input 2 byte ADC value to 'buf'

//      return Value ;                          //rj placed after IC2M_In
    I2CM_Stop( ) ;

    return Value ;                              //rj placed after IC2M_Stop
}


static void I2CM_In( unsigned char* buf, int count )
{
    unsigned char data ;

    for( ; count--; )  // How do I store these 2 bytes in a char[] or INT
    {
            data = 0 ;
            I2C_SDA_INPUT() ;

        volatile unsigned int i = 0 ;

        for( ; i < 8 ; ++i )
        {
            //Set Clock High
            I2C_SCL_HIGH() ;              

            //shift the bit over
            data <<= 1 ;

            if( I2C_SDA_IS_HIGH() )
            {
                data |= 0x01 ;
            }
            //Set Clock Low
            brief_pause( 0x04 ) ;
            I2C_SCL_LOW() ;
        }
        //put the input data byte into the buffer, inc buffer pointer
        *buf++ = data ;

        //take sda to output ack
        I2C_SDA_OUTPUT() ;

        //Set Clock High
        I2C_SCL_HIGH() ;

        //Set Clock Low
        brief_pause( 0x04 ) ;
        I2C_SCL_LOW() ;
    }
}

Pra, me sa duket më duhet një grup (char adcarray i panënshkruar [2] për të mbledhur / ruajtur leximet që rezultojnë, kështu që u përpoqa -

*buf++ = data ;

adcarray[] = data ;

adcarray[] = buf ;

'pritet një shprehje' me sa duket do të thotë se më duhet një formë e ciklit for për të mbushur grupin në çdo kalim, edhe pse vija *buf është tashmë brenda një cikli numërimi 2.

Ndihma e vlerësuar (C në IAR në MSP430 dhe ADS1115 ADC). Të fala, Ralph


c i2c
person Ralph    schedule 07.08.2019    source burimi
comment
Çfarë është adcarray ose Value - ju keni lënë jashtë deklaratat për ato variabla.   -  person Chris Turner    schedule 07.08.2019
comment
Përshëndetje Chris, Vlera është vlera 2 x 8 bit të lexuara radhazi nga një regjistër 16 bit në adc. Më duhet t'i vendos ato në një grup ose në mënyrë ideale në një INT.   -  person Ralph    schedule 07.08.2019
comment
Funksioni tashmë merr një tregues dhe një vlerë gjatësie ku të dhënat do të ruhen. Pse të mos e thërrisni atë funksion me adresën e grupit tuaj?   -  person Gerhardh    schedule 07.08.2019
comment
Ju lutemi jepni gjithmonë informacion të plotë rreth mesazheve të gabimit. Cili është teksti i saktë dhe për çfarë rreshti raportohet? Fragmenti nuk është pjesë e funksionit të mësipërm. Ju lutemi jepni gjithmonë një program të plotë të verifikueshëm për të riprodhuar problemin tuaj.   -  person Gerhardh    schedule 07.08.2019
comment
Si të verifikoni nëse i keni lexuar me sukses të dhënat? Ku i krahasoni vlerat e lexuara me analizuesin I2C?   -  person Gerhardh    schedule 07.08.2019
comment
Përshëndetje Gerhardh - Kam shtuar adcdata[count] = data ; menjëherë pas të dhënave *buf++ = ; por nuk jam i sigurt se po funksionon siç duhet, grupi duket të jetë bosh   -  person Ralph    schedule 07.08.2019
comment
Unë kam një analizues të gjendjes logjike ZeroPlus i cili më tregon se 2 bajt lexohen saktë, më duhet vetëm t'i ruaj ato   -  person Ralph    schedule 07.08.2019
comment
Le të të vazhdojmë këtë diskutim në chat.   -  person Gerhardh    schedule 07.08.2019
comment
më falni, do të kthehem tek ju, kam probleme të tjera kryesore me kodin I2C   -  person Ralph    schedule 07.08.2019
comment
Nëse grupi i ka të gjitha vlerat zero, atëherë funksioni juaj I2C_SDA_IS_HIGH() duket se është problem. Nëse dëshironi t'i vendosni këto të dhëna në variablin Integer, dëshironi të shikoni në rendin e bajtit të rrjetit dhe hostit. (linux.die.net/man/3/ntohl)   -  person Sunil Shahu    schedule 07.08.2019
comment
Përshëndetje Sunil, vini re se nuk ka asgjë të keqe me kodin I2C pasi analizuesi im tregon 2 bajt që lexohen në sekuencë dhe ato përmbajnë vlerat e pritura. Problemi im është se si t'i vendos ato 2 bajt në një grup ose int në mënyrë që të mund të kryej matematikë etj (numri i komplimentit të 2-së)   -  person Ralph    schedule 07.08.2019
comment
Kodi juaj është ende mjaft i paplotë. Çfarë është Value? Duhet të përmbajë 2 bajt të lexuar nga 'I2CM_In. What's wrong with the content of Value'? A është ndryshe nga ajo që shihni në analizuesin tuaj?   -  person Gerhardh    schedule 07.08.2019
comment
Po, shumë të ndryshme, vlerat e treguara në analizues janë 3E për bajtin e parë dhe f) për të dytin. Vlera e vlerës (sipas IAR) është 'simbol i panjohur ose i paqartë'   -  person Ralph    schedule 07.08.2019
comment
Unë kam treguar tani 'të gjithë kodin', por kjo ka të ngjarë të ngatërrojë njerëzit, çështja është se unë ende nuk mund të kuptoj se si t'i ruaj bajtet në mënyrë që të mund t'i ndërtoj / shkallëzoj ato etj. Dyshoj se po më mungon diçka e thjeshtë.   -  person Ralph    schedule 07.08.2019
comment
unsigned char Value; Si duhet të mbajë kjo 2 bajt?   -  person Gerhardh    schedule 07.08.2019
comment
I2C_Read_Register( ADC, 0x00 ) kthen 2 bajt (sipas analizuesit I2C), mbajtja e tyre është problemi për të cilin po kërkoj një zgjidhje.   -  person Ralph    schedule 07.08.2019
comment
Më duhet të shtoj diçka pas kësaj *buf++ = të dhëna për të ruajtur / mbajtur 2 bajt, por nuk e di se çfarë (arrays, ints etj nuk duket se funksionojnë)   -  person Ralph    schedule 07.08.2019
comment
Vlera është një rikthim nga kodi i supozuar i shembullit I2C i TI, nuk është çudi për mua që nuk funksionon me më shumë se një bajt.   -  person Ralph    schedule 07.08.2019
comment
Problemi është se ndryshorja aktuale prapa buf është Value, e cila shpërndan vetëm një bajt memorie. Vlera duhet të jetë ndoshta një grup ose një int 16 bit, dhe funksioni I2C_Read_Register duhet të kthejë një int 16 bit. Nëse vendosni një pikë ndërprerjeje në *buf++ = data ;, a shihni të njëjtën gjë që sheh analizuesi juaj?   -  person yhyrcanus    schedule 07.08.2019
comment
Faleminderit, por u zgjidh, një shumë e thjeshtë (megjithëse e çrregullt) nëse numërimi = 0 ose nëse numërimi = 1 (menjëherë pas *buf++ = të dhëna) atëherë ruajeni bajtin e lidhur në një shkronjë të veçantë.   -  person Ralph    schedule 07.08.2019


Përgjigjet (1)


Nëse përpiqeni t'i ruani të dhënat në një grup tjetër me funksionin I2CM_In, po i përdorni gabimisht.

static void I2CM_In( unsigned char* buf, int count )
{
    unsigned char data ;

    for( ; count--; )
    {
        ....
        //put the input data byte into the buffer, inc buffer pointer
        *buf++ = data ;
    }
}

Të dhënat e marra janë ruajtur tashmë në një buffer: buf. Është detyra juaj të siguroni një tampon që është i përshtatshëm për të ruajtur rezultatin.

static unsigned char I2C_Read_Register( char Device_Address, char Register_Address )
{
    unsigned char Value ;
...
    I2CM_In( &Value, 2 ) ;  // << Value is 1 byte!
...
  return Value ;
}

Nëse dëshironi të lexoni një regjistër me 16 bit, nuk mund ta ktheni vlerën si unsigned char. Ju duhet të përdorni një lloj të dhënash që mund të mbajë (të paktën) 2 bajt.

Duke i thënë funksionit që buferi është 2 bajt i gjatë, ju gjithashtu shkaktoni sjellje të padefinuar.

static uint16_t I2C_Read_Register( char Device_Address, char Register_Address )
{
    uint16_t Value ;
...
    I2CM_In( &Value, 2 ) ;
...
    return Value ;
}

Në varësi të endianitetit, mund t'ju duhet gjithashtu të ndërroni rendin e bajtit:

static uint16_t I2C_Read_Register( char Device_Address, char Register_Address )
{
    uint8_t tmp_Value[2] ;
...
    I2CM_In( tmp_Value, 2 ) ;
    uint16_t Value;

#if MSB_FIRST
    Value = ((uint16_t)tmp_Value[0]) << 8 || tmp_Value[1];
#else // LSB_FIRST
    Value = ((uint16_t)tmp_Value[1]) << 8 || tmp_Value[0];
#endif
...
    return Value ;
}
person Gerhardh    schedule 07.08.2019
comment
Faleminderit, ajo që përdora në të vërtetë (edhe pse mjaft e tmerrshme) ishte - nëse (count == 0) { ADC_Value2 = data ; } if (numërimi == 1) { ADC_Value1 = të dhëna ; } - person Ralph; 07.08.2019
comment
Sigurisht, atëherë përpjekja për të kombinuar dy shkronja të veçanta në një int (për punën në matematikë) nuk funksionon (duke përdorur karakterin e parë të ndryshimit standard 8 bit majtas, shtoni karakterin e dytë etj (në IAR Workbench) por kjo është një histori tjetër - person Ralph; 07.08.2019
comment
Ju mund të përpiqeni të transferoni vlerën në int përpara se ta zhvendosni. - person Gerhardh; 07.08.2019