|
|
View previous topic :: View next topic |
Author |
Message |
Blackjackmaster
Joined: 14 May 2023 Posts: 30
|
I2C Write |
Posted: Tue Jul 11, 2023 1:06 pm |
|
|
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: 1934 Location: Norman, OK
|
|
Posted: Tue Jul 11, 2023 2:16 pm |
|
|
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: 19535
|
|
Posted: Wed Jul 12, 2023 12:51 am |
|
|
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...
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
|
I2C Write |
Posted: Wed Jul 12, 2023 8:23 am |
|
|
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: 19535
|
|
Posted: Thu Jul 13, 2023 1:45 am |
|
|
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
|
I2C Write |
Posted: Thu Jul 13, 2023 11:52 am |
|
|
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?
|
|
|
PrinceNai
Joined: 31 Oct 2016 Posts: 480 Location: Montenegro
|
|
Posted: Thu Jul 13, 2023 9:13 pm |
|
|
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: 19535
|
|
Posted: Fri Jul 14, 2023 1:04 am |
|
|
Yes, dead right. I do say count down, but then typed ++.....
Duh. |
|
|
PrinceNai
Joined: 31 Oct 2016 Posts: 480 Location: Montenegro
|
|
Posted: Fri Jul 14, 2023 7:03 am |
|
|
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) |
|
|
|
|
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
|