Tallenna 2 tavua I2C Slavesta

kamppailen luultavasti yksinkertaisen koodinpalan kanssa kopioida I2C-orjalta saatu 2 tavua taulukkoon, jotta voin sitten muuntaa INT:ksi ja suorittaa matematiikkaa tiedoilla.

Tämä koodi onnistuneesti (I2C-analysaattorini mukaan) lukee 2 peräkkäistä tavua yhdestä rekisteriosoitteesta 16-bittisessä ADC:ssä.

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() ;
    }
}

Joten oletettavasti tarvitsen sitten taulukon (signed char adcarray [2] keräämään / tallentamaan tuloksena olevat lukemat, joten yritin -

*buf++ = data ;

adcarray[] = data ;

adcarray[] = buf ;

'odotettu lauseke' oletettavasti tarkoittaa, että tarvitsen jonkinlaisen for-silmukan täyttääkseni taulukon jokaisella siirrolla, vaikka rivi *buf on jo count 2 -silmukan sisällä.

Apua arvostetaan (C IAR:ssä MSP430:ssa ja ADS1115 ADC:ssä). Terveisin Ralph


c i2c
person Ralph    schedule 07.08.2019    source lähde
comment
Mikä on adcarray tai Value - olet jättänyt näiden muuttujien ilmoitukset pois.   -  person Chris Turner    schedule 07.08.2019
comment
Hei Chris, Arvo on 2 x 8 bitin arvoja, jotka luetaan peräkkäin adc:n 16-bittisestä rekisteristä. Minun täytyy laittaa ne taulukkoon tai mieluiten INT:hen.   -  person Ralph    schedule 07.08.2019
comment
Toiminto ottaa jo osoittimen ja pituusarvon, johon tiedot tallennetaan. Mikset kutsu sitä funktiota taulukkosi osoitteella?   -  person Gerhardh    schedule 07.08.2019
comment
Anna aina täydelliset tiedot virheilmoituksista. Mikä on tarkka teksti ja mille riville se raportoidaan? Katkelma ei ole osa yllä olevaa toimintoa. Toimita aina täydellinen todennettavissa oleva ohjelma ongelman toistamiseksi.   -  person Gerhardh    schedule 07.08.2019
comment
Kuinka varmistat, oletko lukenut tiedot onnistuneesti? Missä vertaat luettuja arvoja I2C-analysaattoriin?   -  person Gerhardh    schedule 07.08.2019
comment
Hei Gerhardh - Olen lisännyt adcdata[count] = data ; heti *buf++ = datan jälkeen; mutta en ole varma, toimiiko se oikein, taulukko näyttää olevan tyhjä   -  person Ralph    schedule 07.08.2019
comment
Minulla on ZeroPlus-logiikkatila-analysaattori, joka näyttää minulle, että 2 tavua luetaan oikein, minun täytyy vain tallentaa ne   -  person Ralph    schedule 07.08.2019
comment
Jatkamme tätä keskustelua chatissa.   -  person Gerhardh    schedule 07.08.2019
comment
Anteeksi, palaan asiaan, minulla on muita suuria ongelmia I2C-koodin kanssa   -  person Ralph    schedule 07.08.2019
comment
Jos taulukossa on kaikki nolla-arvot, funktiosi I2C_SDA_IS_HIGH() näyttää olevan ongelma. Jos haluat laittaa nämä tiedot kokonaislukumuuttujaan, haluat tarkastella verkon ja isännän tavujärjestystä. (linux.die.net/man/3/ntohl)   -  person Sunil Shahu    schedule 07.08.2019
comment
Hei Sunil, huomaa, että I2C-koodissa ei ole mitään vikaa, koska analysaattorini näyttää 2 tavua luettavana peräkkäin ja ne sisältävät odotetut arvot. Ongelmani on, kuinka laitan ne 2 tavua taulukkoon tai int:iin, jotta voin suorittaa matematiikkaa jne (2:n kohteliaisuusnumero)   -  person Ralph    schedule 07.08.2019
comment
Koodisi on vielä melko epätäydellinen. Mikä on Value? Sen pitäisi sisältää 2 tavua, jotka lukee "I2CM_In. What's wrong with the content of Value"? Onko se erilainen kuin mitä näet analysaattorissasi?   -  person Gerhardh    schedule 07.08.2019
comment
Kyllä, hyvin erilaisia, analysaattorissa näkyvät arvot ovat 3E ensimmäiselle tavulle ja f) toiselle. Arvon arvo (IAR:n mukaan) on "tuntematon tai moniselitteinen symboli"   -  person Ralph    schedule 07.08.2019
comment
Olen nyt näyttänyt "kaiken koodin", mutta se todennäköisesti vain hämmentää ihmisiä. Ongelmana on se, että en edelleenkään pysty selvittämään, kuinka voin tallentaa tavut, jotta voin sisällyttää / skaalata niitä jne. Epäilen, että minulta puuttuu jotain yksinkertaista.   -  person Ralph    schedule 07.08.2019
comment
unsigned char Value; Kuinka tämän pitäisi sisältää 2 tavua?   -  person Gerhardh    schedule 07.08.2019
comment
I2C_Read_Register( ADC, 0x00 ) palauttaa 2 tavua (I2C-analysaattorin mukaan), niiden pitäminen on ongelma, johon etsin ratkaisua.   -  person Ralph    schedule 07.08.2019
comment
Minun täytyy lisätä jotain tämän jälkeen *buf++ = tiedot tallentaakseni / säilyttääkseni 2 tavua, mutta en tiedä mitä (taulukot, int jne. eivät näytä toimivan)   -  person Ralph    schedule 07.08.2019
comment
Arvo on TI:n oletetun I2C-esimerkkikoodin varaosa, ei ole yllätys, että se ei toimi useammalla kuin yhdellä tavulla.   -  person Ralph    schedule 07.08.2019
comment
Ongelmana on, että todellinen muuttuja buf on Value, joka varaa vain tavun muistia. Arvon pitäisi luultavasti olla taulukko tai 16-bittinen int, ja funktion I2C_Read_Register pitäisi palauttaa 16-bittinen int. Jos asetat keskeytyskohdan kohtaan *buf++ = data ;, näetkö saman asian, jonka analysaattorisi näkee?   -  person yhyrcanus    schedule 07.08.2019
comment
Kiitos, mutta ratkaistu, hyvin yksinkertainen (tosin sotkuinen) jos count = 0 tai jos count = 1 (välittömästi *buf++ = data) jälkeen tallenna siihen liittyvä tavu erilliseen merkkiin.   -  person Ralph    schedule 07.08.2019


Vastaukset (1)


Jos yrität tallentaa tiedot toiseen taulukkoon I2CM_In-funktiolla, käytät sitä väärin.

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 ;
    }
}

Vastaanotetut tiedot on jo tallennettu puskuriin: buf. Sinun tehtäväsi on tarjota puskuri, joka sopii tuloksen tallentamiseen.

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 ;
}

Jos haluat lukea 16-bittisen rekisterin, et voi palauttaa arvoa muodossa unsigned char. Sinun on käytettävä tietotyyppiä, joka mahtuu (vähintään) 2 tavua.

Kerromalla funktiolle, että puskuri on 2 tavua pitkä, aiheutat myös määrittelemätöntä käyttäytymistä.

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

Endiasuudesta riippuen saatat joutua vaihtamaan myös tavujärjestystä:

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
Kiitos, mitä itse käytin (tosin melko kamalaa) oli - if (count == 0) { ADC_Value2 = data ; } if (count == 1) { ADC_Arvo1 = data ; } - person Ralph; 07.08.2019
comment
Tietenkin silloin yrittää yhdistää kaksi erillistä merkkiä int:ksi (matematiikan työskentelyä varten) ei toimi (käytä normaalia vaihtomerkkiä 8 bittiä jäljellä, lisää toinen merkki jne (IAR Workbenchissä), mutta se on toinen tarina - person Ralph; 07.08.2019
comment
Voit yrittää heittää arvon int-arvoon ennen vaihtamista. - person Gerhardh; 07.08.2019