CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

I2C Write

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Blackjackmaster



Joined: 14 May 2023
Posts: 30

View user's profile Send private message

I2C Write
PostPosted: Tue Jul 11, 2023 1:06 pm     Reply with quote

This is to write to ALS31313 Register.

I am not sure why I am receiving an invalid overload function for i2c_read and Stream must be a constant in the valid range. Should I be using the i2c_transfer_in? Items in bold are the errors.

Code:
int16 I2C_write(int8 nAddr, int8 nRegAddr, int32 nValue=0 , int8 nSize=0 );
int16 I2C_read(int8 nAddr, int8 nRegAddr, int32& nValue, int8 nSize);
int16 I2C_read(int8 nAddr, int32& nValue, int8 nSize);

void LowPower()                                                 //setting each sensor to full loop mode
{
  i2c_write(nDevAddr, [b]0x35[/b], 0x2C413534, 4);  //Enable customer writing to sensor - Default code from manufacturer
 int16 nError;
 int16 nJunk = 0;
  i2c_write( 0x27, [b]nRegData[/b], 4); //Read data from 0X27 Register
  nRegData &= ~(0x11 << 2);    // clear, set full loop mode and Set to sleep
  nRegData |= 0x02 << 2;
  nRegData |= 0x02 ;                              //Puts it into low power duty cycle mode
  i2c_transfer_in(0x27, nRegData, 4);         // Write bits back to sensor
  nError = i2c_read(0x27, [b]4[/b]);
  if (!nError) {
    Adress_Array1[Counter] = nDevAddr;
    Counter = Counter + 1;
    SizeArray[i] = SizeArray[i] + 1;
  }
}
dyeatman



Joined: 06 Sep 2003
Posts: 1933
Location: Norman, OK

View user's profile Send private message

PostPosted: Tue Jul 11, 2023 2:16 pm     Reply with quote

What version of compiler are you using where I2c takes those parameters?

Here is what my manual says:

i2c_read( )
Syntax:
data = i2c_read();
data = i2c_read(ack);
data = i2c_read(stream, ack);

Parameters:
ack -Optional, defaults to 1
0 indicates do not ack
1 indicates to ack
2 slave only, indicates to not release clock at end of read. Use when i2c_isr_state()
returns 0x80
stream - specify the stream defined in #USE I2C
_________________
Google and Forum Search are some of your best tools!!!!
Ttelmah



Joined: 11 Mar 2010
Posts: 19503

View user's profile Send private message

PostPosted: Wed Jul 12, 2023 12:51 am     Reply with quote

Also the other critical thing is that stream names do have to be constants.
You can't use a variable to address streams. Search here. If you want to
use a variable for a stream name, you have to do this yourself, by
passing the variable, and having select case statements to then
select the required constant stream.

He seems to have shown his own overloads for the inbuilt functions,
passing the device address where the stream name should be. This is
then resulting in the compiler thinking this variable is the stream name.
If you want to change the structure of the functions for your own use,
then give your functions your own names, rather than using the same
names as the internal functions... Sad

Looking at the declarations, I think he is copying code from another
compiler/processor, and trying to use these functions in CCS.
No. You need to rewrite what you are doing to use the CCS functions,
not 'hope' that you can make these other declarations work...
Blackjackmaster



Joined: 14 May 2023
Posts: 30

View user's profile Send private message

I2C Write
PostPosted: Wed Jul 12, 2023 8:23 am     Reply with quote

Hello,

Yes, I am working towards converting Arduino code.

I am using:
IDE 5.115
PCB 5.115
PCM 5.115
PCH 5.115

In my situation is this how the code will look:
Access Mode Address Data
Customer Access 0x35 0x2C413534

int16 nRegData;
i2c_write (96); //Device address this is always the first line
i2c_write(0x35); // This is the device register
ic2_write(0x2C413534); // Enable writing to Register
i2c_write(4); // 50= ms
The read is a different register:
i2c_read(0x27);
nRegData &= (0x11 << 2); // clear, set full loop mode and Set to sleep
nRegData |= 0x02 << 2;
nRegData |= 0x02 ;
i2c_read(RegData);
i2c_read(4);// 50= ms


Is this the same order all the time?
Device Address
Register
Data
How does the complier know the sequence?

Address Bits Name Description
0x27
31:7 Reserved Reserved
6:4 Low-Power Mode Count Max
Sets max counter for inactive time during low-power duty cycle mode. ALS31313 offers 8 discrete
time frames for inactive time. See Application Information section on low-power modes.
3:2 I2C Loop-Mode Sets I2C readback mode to single read, fast loop, or full loop mode. See Application Information
section on readback modes.
1:0 Sleep Sets device operating mode to full active, ultralow power sleep mode, or low-power modes


Address Bits Value tINACTIVE (typ) (ms)
0x27 6:4
0 0.5 ms
1 1 ms
2 5 ms
3 10 ms
4 50 ms
5 100 ms
6 500 ms
7 1000 ms
Ttelmah



Joined: 11 Mar 2010
Posts: 19503

View user's profile Send private message

PostPosted: Thu Jul 13, 2023 1:45 am     Reply with quote

Lets start with this:
"How does the compiler know the sequence?".

It doesn't. _You_ as the programmer do, so you write your code to send
things and read things in the sequence required. This is programming.

Now in what you post:

ic2_write(0x2C413534);

Not going to happen. I2C_write takes _one_ byte.
So you have to write your own 4 byte write:
Code:

void i2c_write_32(unsigned int32 val)
{
   signed int8 ctr;
   for (ctr=3; ctr>=0; ctr++) //MSB first - count down
      i2c_write(make8(val,ctr)); //send byte from 32bit val
}


Now the I2C address of the device is controlled by a resistive divider on
pins ADR0/1. Your '96' implies these are tied low. However the '96', is
a 7bit I2C address. This has to be sent times two, with the R/W bit
added at the bottom. This is 0b1100000 So:
Code:

#DEFINE READ_ADDRESS 0b11000001
#DEFINE WRITE_ADDRESS 0b11000000


So your first write will be:
I2C_write(WRITE_ADDRESS);

Not the 96 you show.
All I2C transactions need to start with an I2C_start, and end with an
I2C_stop. The start needs to be in front of sending this address byte.

Now then you have to read about I2C bus reversing. For the read, you
_write_ the address required, and then reverse the bus. Look at page 20
of the data sheet, and note the _master restart_. What happens
is the sequence would be:
Code:

signed int8 ctr;
union {
    unsigned int32 word;
    byte bytes[4];
} combine;

I2C_start();
I2C_write(WRITE_ADDRESS);
i2c_write(Register_address); //so you have now written the register no.
I2C_start(); //This is the bus _restart_
I2C_write(READ_ADDRESS); //This now signals to turn the bus round
//You now I2C_read the bytes
for (ctr=3;ctr>=0;ctr++)
   combine.bytes[ctr]=I2C_read(); //read the four bytes MSB first
//Then stop
I2C_stop();


Combine.word now has the 32bit value read from register
Register_address'.

If you look at the data sheet Page20, left hand side, you will see this is
_exactly_ the sequence the manufacturer describes. Including the start,
stop, the address bytes with the extra bit added, etc. etc..
The ACK is done automatically by the hardware.

No guarantees, I typed the code into the post directly, so may have
missed a bracket or comma, but it should be close enough to get you
started.
Blackjackmaster



Joined: 14 May 2023
Posts: 30

View user's profile Send private message

I2C Write
PostPosted: Thu Jul 13, 2023 11:52 am     Reply with quote

Hello,

Thanks for the response.
There are 16 chips on the PCB. The addresses are C0-DC and 00. If the chip is available, I receive a Status:1. What is the best solution for reading Registers 0x35 and 0X27 from each chip.
Code:
unsigned int8 I2C_Address;
unsigned int8 status;
unsigned int8 Device_Count = 0;
int8 Channel;



#define TCAaddr 0xE0                                         
const int8 bus_array[8]={1,2,4,8,16,32,64,128};

void select_bus(int bus)
{
    if (bus > 7 )
        return;                                                //trap illegal bus numbers
    I2C_start();
    I2C_write(TCAaddr);
    I2C_write(bus_array[bus]);                                 //select specified bus number
    I2C_stop();                                                //I2C bus now routes to BUS number
}

//Then with the ADXL wired as described above, simply call
//    select_bus(0);
//And the ADXL will now be connected to the I2C bus with level
//translation.
//You then write to the ADXL as normal.


int8 get_ack_status(int8 address)
{
   int8 ack;

   i2c_start();
   delay_us(20);
   ack = i2c_write(address);   // Status = 0 if got an ACK
   i2c_stop();
   delay_us(20);
   if(ack == 0)
      return(TRUE);
   else
      return(FALSE);
}

void Get_I2C_Addresses(void){
// Try all slave addresses from 0x10 to 0xEF.
// See if we get a response from any slaves
// that may be on the i2c bus.
//   for(I2C_Address = 0x10; I2C_Address < 0xF0; I2C_Address+=2)   // original
   for(I2C_Address = 0x00; I2C_Address < 0xE8; I2C_Address+=2) // trimmed down to avoid scanning mux address, just in case
   
      {
       
       status = get_ack_status(I2C_Address);
       printf("Stat: %X\n\r", status);
       if(status == TRUE)
         {
            printf("ACK addr: %X\n\r", I2C_Address);
            Device_Count++;
            delay_ms(100);
         }
      }
   
   if(Device_Count == 0){
      printf("Nothing Found\n\r");
      delay_cycles(1);
   }
   else{
      printf("Found: %u\n\r", Device_Count);
      delay_cycles(1);
   }
}




//=================================
void main(){
   
   output_float(PIN_B0);
   output_float(PIN_B1);


   for(Channel = 0; Channel < 8; Channel++)
   {                     // loop through channels
     
      select_bus(Channel);
      printf("\n\rTCA Port #%d\n\r",Channel);
     
      Device_Count = 0;
         
      Get_I2C_Addresses();   //I2C scanner
     
   }
 
 
   while(1);
}
If (Status =1){

signed int8 ctr;
union {
    unsigned int32 word;
    byte bytes[4];
} combine;

I2C_start();
I2C_write(WRITE_ADDRESS);
i2c_write(Register_address); //so you have now written the register no.
I2C_start(); //This is the bus _restart_
I2C_write(READ_ADDRESS); //This now signals to turn the bus round
//You now I2C_read the bytes
for (ctr=3;ctr>=0;ctr++)
   combine.bytes[ctr]=I2C_read(); //read the four bytes MSB first
//Then stop
I2C_stop();
}

Or


Is it possible to increment the READ_ADDRESS and WRITE ADDRESS?
Code:
PrinceNai



Joined: 31 Oct 2016
Posts: 478
Location: Montenegro

View user's profile Send private message

PostPosted: Thu Jul 13, 2023 9:13 pm     Reply with quote

Quote:
Is it possible to increment the READ_ADDRESS and WRITE ADDRESS?


Those two defines are NOT some values in RAM. A #define simply tells the compiler to substitute everywhere they are used with whatever they are defined as. It makes life simpler. You use something in many places in your program, but you only have to change it in one place and it reflects everywhere. You can declare two variables, say ReadI2CFrom and WriteI2CTo and use ReadI2CFrom = READ_ADDRESS; increment that variable as needed and then pass ReadI2CFrom to the I2C_write function.

The second thing is this:
Code:
for (ctr=3;ctr>=0;ctr++)

I believe it should read ctr--
Ttelmah



Joined: 11 Mar 2010
Posts: 19503

View user's profile Send private message

PostPosted: Fri Jul 14, 2023 1:04 am     Reply with quote

Yes, dead right. I do say count down, but then typed ++.....

Duh.
PrinceNai



Joined: 31 Oct 2016
Posts: 478
Location: Montenegro

View user's profile Send private message

PostPosted: Fri Jul 14, 2023 7:03 am     Reply with quote

Blackjackmaster, the way you glued the code together in your last post won't work. Check the for loop which scans the addresses. There is a while(1) after it. It stops there. What you added is also outside of the main function. No way to execute. Does it even compile?

Edit: It doesn't compile. There is also a (very easy one to make, but the compiler does warn you about it) mistake here:

If (Status =1) doesn't test for equality. Should be If (Status == 1)
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group