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 support@ccsinfo.com

Transmitting int16 value through i2c
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
muhibraza1



Joined: 26 Jul 2013
Posts: 23

View user's profile Send private message

Transmitting int16 value through i2c
PostPosted: Fri Jul 26, 2013 3:04 am     Reply with quote

Hello, can someone help me find a way for sending 16 bit data through i2c with PIC18F452 ?
mdemuth



Joined: 16 Apr 2007
Posts: 71
Location: Stuttgart, Germany

View user's profile Send private message Visit poster's website

PostPosted: Fri Jul 26, 2013 3:43 am     Reply with quote

Nothing special about it, just send two bytes e.g.
Code:
void Init_PCA9554()
  {
  i2c_start();
  i2c_write(0b01000000); // adress byte
  i2c_write(0x00);       // command byte
  i2c_stop();
  }

Use make8 and make16 functions to convert 16bit into 2x8bit and back.
muhibraza1



Joined: 26 Jul 2013
Posts: 23

View user's profile Send private message

PostPosted: Fri Jul 26, 2013 4:28 am     Reply with quote

Thank you for your help. But I was asking about 1 address byte and 2 data bytes. Not 1 address and 1 data. The Slave is also a PIC18f452 and I am using Ex_slave.c code on it.

I tried the following code but its not working.

Code:

#include <18f452.h>
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#use i2c(Master, sda=PIN_C4, scl=PIN_C3)
   
//====================================
void main()
{
long data , datah , datal ;
data = 720 ;
do
{
//Write data to slave board.
i2c_start();
i2c_write(0xA0);
i2c_write(0x00);
i2c_write(data);
i2c_write(data>>8);
i2c_stop();

printf("write %Lu \n\r", data);

// Read from the slave board and display the data.
i2c_start();
i2c_write(0xA0);
i2c_write(0x00);
i2c_start();
i2c_write(0xA1);
datal = i2c_read();
datah = i2c_read(0);
i2c_stop();

datah = datah<<8;
data = datah | datal ;

printf("read %Lu \n\r", data);

}while(TRUE);
}


The output never comes. The hyperterminal prints nothing.
While the following code is working absolutely fine.

Code:

#include <18f452.h>
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#use i2c(Master, sda=PIN_C4, scl=PIN_C3)
   
//====================================
void main()
{
do
{
// Write the letter 'B' to the slave board.
i2c_start();
i2c_write(0xA0);
i2c_write(0x00);
i2c_write('B');
i2c_stop();

// Read from the slave board and display the data.
i2c_start();
i2c_write(0xA0);
i2c_write(0x00);
i2c_start();
i2c_write(0xA1);
data = i2c_read(0);
i2c_stop();

printf("read %c \n\r", data);

}while(TRUE);
}


The output of this program is
Read B
Read B
Read B

and it continues....

Could anybody tell what is it that I am doing wrong with the 16 bit data ?
muhibraza1



Joined: 26 Jul 2013
Posts: 23

View user's profile Send private message

PostPosted: Fri Jul 26, 2013 4:38 am     Reply with quote

I also tried online debugging on the Master PIC using ICD-U64. I found out that the program never goes beyond this :

Code:

#include <18f452.h>
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#use i2c(Master, sda=PIN_C4, scl=PIN_C3)
   
//====================================
void main()
{
long data , datah , datal ;
data = 720 ;
do
{
//Write data to slave board.
i2c_start();
i2c_write(0xA0);


It gets stuck here. While the other program which I used for transmitting 8 bit data is working absolutely fine.

Just thought that it may be helpful for you in understanding the problem.
muhibraza1



Joined: 26 Jul 2013
Posts: 23

View user's profile Send private message

PostPosted: Sat Jul 27, 2013 1:28 am     Reply with quote

anyone ??
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Sat Jul 27, 2013 5:52 am     Reply with quote

The situation as you describe it is strange, and then with strange I mean that something is going wrong not caused by your program but by some other cause. Both programs are identical up to the point where you say the program stops so that program line by itself can't be the problem cause.

How do you know the program stops at the I2C line? Tell us how you found this out because your debug method might be what causes the problem.

Have you tried your first program again and is this still working?

What is the value of the pull-up resistors at the I2C lines you use? And at which lines do you have these pull-up resistors?

What is the length of the cable between your master and slave PIC?

ALWAYS post your compiler version number!

A general comment is to always add the 'ERRORS' parameter to the #use RS232 line. This will make the compiler to add error clearing code when the UART has a receive buffer overflow. Without the ERRORS directive the UART will stop working until the error condition is cleared by you.
muhibraza1



Joined: 26 Jul 2013
Posts: 23

View user's profile Send private message

PostPosted: Thu Aug 01, 2013 2:18 am     Reply with quote

Quote:
How do you know the program stops at the I2C line? Tell us how you found this out because your debug method might be what causes the problem.


I have done online debugging with ICD-U64 on CCS PICC Compiler V4.124. I clicked on single step and it worked fine before the program reached this line
Code:
i2c_write(0xA0);

At this line the debugger shows the status of the program as "running" and then takes forever to complete this step. :/

Quote:
Have you tried your first program again and is this still working?

Yes, it does. It always works fine.

Quote:
What is the value of the pull-up resistors at the I2C lines you use? And at which lines do you have these pull-up resistors?

I am using 4.7K resistors on SDA and SCL line.

Quote:
What is the length of the cable between your master and slave PIC?

Its around 4 or 5 inches.
And I don't think that this may be the problem because the same hardware is working fine with the 8 bit program. It must not be the hardware.

Quote:
ALWAYS post your compiler version number!

Ttelmah



Joined: 11 Mar 2010
Posts: 19244

View user's profile Send private message

PostPosted: Thu Aug 01, 2013 3:39 am     Reply with quote

Do you have the CCS IDE?.

If so, try using the device editor, going to the errata section, and ticking the one that says "Don't do BSR15".
Re-compile, and see if it makes any difference.

About 95% of 18F452's, have this as an erratum. Basically if a register access is performed with the BSR set to 15, it clears a status bit in the I2C peripheral. Result can be I2C hanging.....
It only applies if you use I2C, and makes accessing the top bank of RAM slower, so CCS leave it off by default. However if you want to use I2C, with these chips, it needs to be on.
Personally, I'd really strongly suggest switching to the 4520 instead. Generally it is cheaper, and has a lot less faults (on the later revisions).

Best Wishes
muhibraza1



Joined: 26 Jul 2013
Posts: 23

View user's profile Send private message

PostPosted: Thu Aug 01, 2013 6:04 am     Reply with quote

Ohh. Thanks for providing this great info. Does this problem occur in PIC18F252 or any other controllers too or is it specfic to this 18F452 ?
snock



Joined: 10 Oct 2011
Posts: 24

View user's profile Send private message

PostPosted: Thu Aug 01, 2013 6:25 am     Reply with quote

Thanks for the head's up on the BSR15 issue. We've been having issues with the i2c on PIC16F882s so I will try it with it off. It's a very intermittent problem and hopefully this fixes it.
Ttelmah



Joined: 11 Mar 2010
Posts: 19244

View user's profile Send private message

PostPosted: Fri Aug 02, 2013 1:28 am     Reply with quote

The 16F882, does not have this issue.

However it has a lot of other errata for the I2C....

If you are a master device, then consider switching to software I2C (FORCE_SW). If this fixes the problems, then you have to decide whether the gain from using the hardware is worthwhile (small)....

If you are working as a slave device, then look at errata 5. If you are a slave with SS enabled, look at errata 7.

Best Wishes
snock



Joined: 10 Oct 2011
Posts: 24

View user's profile Send private message

PostPosted: Fri Aug 02, 2013 6:21 am     Reply with quote

Well, another peculiarity is that the code when compiled with version 4.050 will function properly but when compiled with version 4.124 does not function.

Here is the code which does not function when compiled with 4.124:

Code:

#include<16f882.h>
#fuses XT, MCLR, WDT, NOLVP, NOBROWNOUT, NODEBUG, NOFCMEN, PUT
#use delay(clock=4MHz)
#use fast_io(b)
#use fast_io(c)
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0xa0, force_hw, slow)

// * PORT A DEFINITIONS ********************************************************
#define IO_FLT    PIN_A5
// *****************************************************************************

// * PORT B DEFINITIONS ********************************************************
#define Q0        PIN_B0
#define Q1        PIN_B1
#define Q2        PIN_B2
#define Q3        PIN_B3
#define Q4        PIN_B4
#define Q5        PIN_B5
#define Q6        PIN_B6
#define Q7        PIN_B7
// *****************************************************************************

// * PORT C DEFINITIONS ********************************************************
#define ADDR0     PIN_C0
#define ADDR1     PIN_C1
#define ADDR2     PIN_C2
#define SCL       PIN_C3
#define SDA       PIN_C4
// *****************************************************************************

// * PORT E DEFINITIONS ********************************************************
#define SHDN      PIN_E3
// *****************************************************************************

// * PROGRAM DEFINITIONS *******************************************************
// *****************************************************************************

#zero_ram

#byte ANSEL=0x188

static int8 mem_addr;
static int8 card_data[20];

// * I2C INTERRUPT HANDLER *****************************************************
#int_ssp
void i2c_handler(void) {
    int8 state;
    state=i2c_isr_state();
    if(state<0x80) { // Master is sending data
       if(state==1) mem_addr=i2c_read(1); // Store the address
       if(state==2) card_data[mem_addr]=i2c_read(1); // Read and store the data
    }
    if(state>=0x80) { // Master is requesting data
       i2c_write(card_data[mem_addr]);  // Write the memory over i2c
    }
}
// *****************************************************************************       

// * MAIN ROUTINE **************************************************************
void main(void) {
   
    int8 i2c_address;
    set_tris_b(0b00000000); // Set port B direction
    set_tris_c(0b00011111); // Set port C direction
    set_tris_e(0b00001000); // Set port E direction
    setup_adc_ports(NO_ANALOGS);
    setup_comparator(NC_NC_NC_NC);
    ANSEL=0; // Bug work around   
    output_b(0); // Clear relays on port B
    output_float(IO_FLT); // Float the I/O fault line
    enable_interrupts(GLOBAL);
    enable_interrupts(INT_SSP);
    setup_wdt(WDT_36MS);
    i2c_address=(~input_c() & 0x07)<<5; // Read address switch at startup
    if(i2c_address==0) i2c_address=2<<5; // Default if not set
    i2c_slaveaddr(i2c_address); // Assign i2c address   
    while(TRUE) { // Loop forever
       restart_wdt();
       card_data[0]=0x09; // Card is a QR8 relay card
       card_data[1]=0; // Set status byte, do more with later
       output_b(card_data[10]); // Write to relay output register
    }
}
// *****************************************************************************
Ttelmah



Joined: 11 Mar 2010
Posts: 19244

View user's profile Send private message

PostPosted: Fri Aug 02, 2013 8:21 am     Reply with quote

Some little comments:

1) A slave does not have a 'speed'. On older compilers this can result in invalid values being loaded into the configuration registers.
2) As posted, the code does not do a read on state==0. This can result in the I2C getting hung, since it won't release the clock stretch till the read is done.

It may well be that CCS have added fixes for these (then have done for '1' on the later V4 compilers.

Best Wishes
snock



Joined: 10 Oct 2011
Posts: 24

View user's profile Send private message

PostPosted: Fri Aug 02, 2013 8:32 am     Reply with quote

Ttelmah, thanks for the pointers. I guess I am still a little confused. I thought that state==0 is the i2c address. So you are saying to insert a
Code:
if(state==0) i2c_read();
into my code? Hanging i2c is the problem with this program however it only happens rarely.
Ttelmah



Joined: 11 Mar 2010
Posts: 19244

View user's profile Send private message

PostPosted: Fri Aug 02, 2013 9:03 am     Reply with quote

Yes, The address still has to be 'read', to release the I2C transaction. If clock stretching is not being used, this doesn't cause a problem (except on some chips), but if it is, the chip holds the clock, until the read is performed.

Look at the ccs example. They perform a read for every state _up to and including 0x80_. 0x80, is the other 'gotcha' one, since this is the address being received, _for_ a write. So on this one, the chip has to read, and then write.

Best Wishes
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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