struggling with what is probably a straightforward piece of code to copy 2 bytes received from an I2C slave into an array so I can then convert to INT and perform maths on the data.
This code successfully (according to my I2C analyser) reads 2 consecutive bytes from one register address on a 16bit ADC.
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() ;
}
}
So, presumably I then need an array (unsigned char adcarray [2] to collect / store the resulting reads, so I tried -
*buf++ = data ;
adcarray[] = data ;
adcarray[] = buf ;
'expected an expression' presumably means I need some form of for loop to populate the array on each pass, even though the *buf line is already inside a count 2 loop.
Assistance appreciated (C in IAR on MSP430 and ADS1115 ADC). Regards, Ralph
If you try to store the data in another array with the I2CM_In function, you are using it wrong.
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 ;
}
}
The data received is already stored in a buffer: buf
. It is your job to provide a buffer that is suitable to store the result.
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 ;
}
If you want to read a register with 16 bit, you cannot return the value as an unsigned char
. You must use a data type capable of holding (at least) 2 bytes.
By telling the function that the buffer is 2 bytes long, you also cause undefined behaviour.
static uint16_t I2C_Read_Register( char Device_Address, char Register_Address )
{
uint16_t Value ;
...
I2CM_In( &Value, 2 ) ;
...
return Value ;
}
Depending on the endianess you might also need to switch byte order:
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 ;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.