ccs __ view topic - need i2c examples

11
FAQ Forum Help Official CCS Support Search Profile You have no new messages Log out [ jayanthd ] Please go to www.mcuspace.com/mcuforum for posts concerning PIC ® MCU CCS does not monitor this forum on a regular basis. Please do not post bug Reports on this forum. Send them to [email protected] Need I2C examples Goto page Previous 1 , 2, 3 Next CCS Forum Index -> General CCS C Discussion View previous topic :: View next topic Author Message valemike Guest working i2c example... Posted: Thu Jun 10, 2004 9:31 am I too was not satisfied with CCS's Slave examples. So I made my own, based on the assembly examples in Microchip's APP Note AN734 (AN735?) When looking at the code below, you'll find that I sprinkled way too many "delay_ms()" statements. This was just to let the other PIC catch up, but i'm sure not all of the delay_ms() statements are necessary, and probably the values in them are too excessive. The master code is straightforward, and I use CCS's libraries... Code: #include <18F452.h> #fuses HS,NOWDT,NOPROTECT,NOLVP #use delay(clock=4000000) #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS) #use i2c(master, sda=PIN_C4, scl=PIN_C3, FORCE_HW) //#use i2c(master,sda=PIN_C4, scl=PIN_C3) #define SLAVE_ADDRESS 0x02 void main(void) { unsigned char rx_byte; while (1) { printf ("Start i2c Master logger.\r\n"); i2c_start(); delay_ms(50); i2c_write(SLAVE_ADDRESS); /* Device Address */ delay_ms(50); i2c_write(0x05); delay_ms(50); // i2c_write(12); delay_ms(100); i2c_start(); // restart condition i2c_write(SLAVE_ADDRESS + 1); rx_byte = i2c_read(0); printf ("rx_byte = 0x%2.2X\r\n", rx_byte); i2c_stop(); printf ("Ending i2c Master Logger.\r\n"); } }

Upload: jayanth-dev

Post on 13-Apr-2015

268 views

Category:

Documents


12 download

DESCRIPTION

I2C examples

TRANSCRIPT

Page 1: CCS __ View Topic - Need I2C Examples

FAQ Forum Help Official CCS Support Search

Profile You have no new messages Log out [jayanthd ]

Please go to www.mcuspace.com/mcuforum for posts concerning

PIC®MCU

CCS does not monitor this forum on a regular basis.

Please do not post bug Reports on this forum. Send them [email protected]

Need I2C examplesGoto page Previous 1, 2, 3 Next

CCS Forum Index -> General CCS C Discussion

View previous topic :: View next topic

Author Message

valemikeGuest

working i2c example...

Posted: Thu Jun 10, 2004 9:31 am

I too was not satisfied with CCS's Slave examples. So I made my own, based on the assembly

examples in Microchip's APP Note AN734 (AN735?)

When looking at the code below, you'll find that I sprinkled way too many "delay_ms()" statements.

This was just to let the other PIC catch up, but i'm sure not all of the delay_ms() statements are

necessary, and probably the values in them are too excessive.

The master code is straightforward, and I use CCS's libraries...

Code:

#include <18F452.h>

#fuses HS,NOWDT,NOPROTECT,NOLVP

#use delay(clock=4000000)

#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

#use i2c(master, sda=PIN_C4, scl=PIN_C3, FORCE_HW)

//#use i2c(master,sda=PIN_C4, scl=PIN_C3)

#define SLAVE_ADDRESS 0x02

void main(void)

{

unsigned char rx_byte;

while (1)

{

printf ("Start i2c Master logger.\r\n");

i2c_start();

delay_ms(50);

i2c_write(SLAVE_ADDRESS); /* Device Address */

delay_ms(50);

i2c_write(0x05);

delay_ms(50);

// i2c_write(12);

delay_ms(100);

i2c_start(); // restart condition

i2c_write(SLAVE_ADDRESS + 1);

rx_byte = i2c_read(0);

printf ("rx_byte = 0x%2.2X\r\n", rx_byte);

i2c_stop();

printf ("Ending i2c Master Logger.\r\n");

}

}

Page 2: CCS __ View Topic - Need I2C Examples

Here is the slave code. Cut and paste it, and compile. If you're using a different processor, then you

need to change the #byte statements to match the particular PIC you're using.

Code:

#define PIC18F452

#include <18F452.h>

#fuses HS,NOWDT,NOPROTECT

#use delay(clock=4000000)

unsigned char read_i2c(void);

void i2c_interrupt_handler(void);

void i2c_initialize(void);

void i2c_error(void);

void write_i2c(unsigned char transmit_byte);

#INT_SSP

void ssp_interupt ()

{

i2c_interrupt_handler();

}

/* These #byte's are for PIC18F452 ONLY!! */

/* Change it per chip */

#byte PIC_SSPBUF=0xFC9

#byte PIC_SSPADD=0xFC8

#byte PIC_SSPSTAT=0xFC7

#byte PIC_SSPCON1=0xFC6

#byte PIC_SSPCON2=0xFC5

#byte PIC_SSPBUF=0x13

#byte PIC_SSPADD=0x93

#byte PIC_SSPSTAT=0x94

#byte PIC_SSPCON1=0x14

/* Bit defines */

#define PIC_SSPSTAT_BIT_SMP 0x80

#define PIC_SSPSTAT_BIT_CKE 0x40

#define PIC_SSPSTAT_BIT_DA 0x20

#define PIC_SSPSTAT_BIT_P 0x10

#define PIC_SSPSTAT_BIT_S 0x08

#define PIC_SSPSTAT_BIT_RW 0x04

#define PIC_SSPSTAT_BIT_UA 0x02

#define PIC_SSPSTAT_BIT_BF 0x01

#define PIC_SSPCON1_BIT_WCOL 0x80

#define PIC_SSPCON1_BIT_SSPOV 0x40

#define PIC_SSPCON1_BIT_SSPEN 0x20

#define PIC_SSPCON1_BIT_CKP 0x10

#define PIC_SSPCON1_BIT_SSPM3 0x08

#define PIC_SSPCON1_BIT_SSPM2 0x04

#define PIC_SSPCON1_BIT_SSPM1 0x02

#define PIC_SSPCON1_BIT_SSPM0 0x01

#define PIC_SSPCON2_BIT_GCEN 0x80

#define PIC_SSPCON2_BIT_ACKSTAT 0x40

#define PIC_SSPCON2_BIT_ACKDT 0x20

#define PIC_SSPCON2_BIT_ACKEN 0x10

#define PIC_SSPCON2_BIT_RCEN 0x08

#define PIC_SSPCON2_BIT_PEN 0x04

#define PIC_SSPCON2_BIT_RSEN 0x02

#define PIC_SSPCON2_BIT_SEN 0x01

#define RX_BUF_LEN 32

#define NODE_ADDR 0x02 /* I2C address of the slave node */

unsigned char slave_buffer[RX_BUF_LEN];

int buffer_index;

Page 3: CCS __ View Topic - Need I2C Examples

int buffer_index;

int comms_error;

int debug_state;

void i2c_initialize(void)

{

/* Set up SSP module for 7-bit */

PIC_SSPCON1 = 0x36; /* 0011 0101 */

PIC_SSPADD = NODE_ADDR; /* Set the slave's address */

PIC_SSPSTAT = 0x00; /* Clear the SSPSTAT register. */

enable_interrupts(INT_SSP); /* Enable MSSP interrupts. */

}

void i2c_interrupt_handler(void)

{

unsigned char i2c_mask = 0x2D; /* 0010 1101 */

unsigned char temp_sspstat;

unsigned char this_byte;

unsigned char tx_byte;

int x;

/* Mask out the unnecessary bits */

temp_sspstat = PIC_SSPSTAT & i2c_mask;

switch (temp_sspstat)

{

/* Write operation, last byte was an address, buffer is full */

case 0x09: /* 0000 1001 */

/* Clear the receive buffer */

for (x=0; x<RX_BUF_LEN; x++)

{

slave_buffer[x] = 0x00;

}

buffer_index = 0; /* Clear the buffer index */

this_byte = read_i2c(); /* Do a dummy read of PIC_SSPBUF */

debug_state = 1;

break;

/* Write operation, last byte was data, buffer is full */

case 0x29: /* 0010 1001 */

/* Point to the buffer */

this_byte = read_i2c(); /* Get the byte from the SSP */

slave_buffer[buffer_index] = this_byte; /* Put it into the buffer

*/

buffer_index++; /* Increment the buffer pointer */

/* Get the current buffer index */

/* Subtract the buffer length */

/* Has the index exceeded the buffer length? */

if (buffer_index >= RX_BUF_LEN)

{

buffer_index = 0; /* Yes, clear the buffer index. */

}

debug_state = 2;

break;

/* Read operation; last byte was an address, buffer is empty */

case 0x0C: /* 0000 1100 */

buffer_index = 0; /* Clear the buffer index */

/* Point to the buffer */

tx_byte = slave_buffer[buffer_index]; /* Get byte from the buffer

*/

write_i2c(tx_byte); /* Write the byte to PIC_SSPBUF */

buffer_index++; /* increment the buffer index */

debug_state = 3;

break;

/* Read operation; last byte was data, buffer is empty */

case 0x2C: /* 0010 1100 */

/* Get the current buffer index */

/* Subtract the buffer length */

/* Has the index exceeded the buffer length? */

if (buffer_index >= RX_BUF_LEN)

{

buffer_index = 0; /* Yes, clear the buffer index */

}

Page 4: CCS __ View Topic - Need I2C Examples

}

/* Point to the buffer */

/* Get the byte */

tx_byte = slave_buffer[buffer_index];

write_i2c(tx_byte); /* Write to PIC_SSPBUF */

buffer_index++; /* increment the buffer index */

debug_state = 4;

break;

/* A NACK was received when transmitting data back from the master. */

/* Slave logic is reset in this case. R_W=0, D_A=1, and BF=0. */

/* If we don't stop in this state, then something is wrong!! */

case 0x28: /* 0010 1000 */

debug_state = 5;

break;

/* Something went wrong!! */

default:

i2c_error();

break;

}

}

void i2c_error(void)

{

comms_error = 1;

printf ("I2C ERROR!\r\n");

}

void write_i2c(unsigned char transmit_byte)

{

unsigned char temp;

unsigned char write_collision = 1;

while (PIC_SSPSTAT & PIC_SSPSTAT_BIT_BF) /* Is BF bit set in PIC_SSPSTAT?

*/

{

/* If yes, then keep waiting */

}

while (write_collision)

{

/* If not, then do the i2c_write. */

PIC_SSPCON1 &= ~PIC_SSPCON1_BIT_WCOL; /* Clear the WCOL flag */

PIC_SSPBUF = transmit_byte;

/* Was there a write collision? */

if (PIC_SSPCON1 & PIC_SSPCON1_BIT_WCOL)

{

/* Yes there was a write collision. */

write_collision = 1;

}

else

{

/* NO, there was no write collision. */

/* The transmission was successful */

write_collision = 0;

}

}

PIC_SSPCON1 |= PIC_SSPCON1_BIT_CKP; /* Release the clock. */

}

/* This function returns the byte in SSPBUF */

unsigned char read_i2c(void)

{

return PIC_SSPBUF;

}

void main(void)

{

debug_state = 0;

i2c_initialize();

enable_interrupts(GLOBAL);

// printf ("Starting I2C Slave Logger.\r\n");

while (1)

{

if (debug_state)

{

Page 5: CCS __ View Topic - Need I2C Examples

{

// printf ("Debug State = %d\r\n", debug_state);

debug_state = 0;

}

}

}

falleaf

Joined: 23 May 2004Posts: 48

Posted: Thu Jun 10, 2004 11:33 am

Oh,thanks indeed. It's that what I need.

Thanks muchie. If I have some question on this code, may I ask you for more information?

Thanks.

dyeatman

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

Posted: Thu Jun 10, 2004 11:37 am

With all the noise he is making about this I would suspect he is trying to get us to do a school

project or something similar for him.

With the fact of his requestes do not make sense and how insistant he is to get specifically the I2C

drivers. In that the posts in the board are apparently not good enough for him, I would suspect he

wants us to hand him a working solution to his problem with us doing all the work for him.

I may be wrong but I bet not!

falleaf

Joined: 23 May 2004Posts: 48

Posted: Thu Jun 10, 2004 11:10 pm

hallo,

Yeah, this is a school project. However, don't bet on this, because you will lose. . My project is on

motion control.

I'm trying with my project on C. And if you pay a visit to electrotech, you will see I helped students

there. That is, I would like to ask, and will help if I can.

I need to have to comparation between the C code >> view as ASM with the ASM writen myself.

However, it's difficult to compare the code if I cannot write as I need. Don't know anything about C

for PIC.

My undertaking is not writing the communication, but understanding C.

By the way, I2C communication in ASM published everywhere. If you need it to include to C, I think

no problems.

That is my question about.

Dont feel so bad to meeh.

And my question will not as how to write the code, but it should be. As writing on ASM, I need to do

this this this... so how should we do it on C... blah blah..

I asked about PWM, but no ans !!

As generating C code to change PWM. We only use set_pwm_duty function. But in ASM, as I change

PWM duty, I have to wait until the timer overflow. So will the C code do this? The problem is that, if

the pin is HIGH, and we change the duty, it still get HIGH at the next period, and we get wrong at

the first period as changing duty. What is the way C code do?

I would like to know about such problems on C, to understand and make a C program better. And

You will see that, C is not always good as ASM. Some init function, I have to use ASM for example.

Now, I did some simple function and understand how to fix C code and ASM. With simple function,

Page 6: CCS __ View Topic - Need I2C Examples

and repeated unexpectedly, I change to use ASM.

Sorry, my English is not good, so I have a long explanation. But that is what I'm doing.

falleaf

Joined: 23 May 2004Posts: 48

Posted: Fri Jun 11, 2004 1:07 am

Example codes also here:

Source: http://www.walking-productions.com/school/adtech/

Master

Code:

/* Standard Include for 16F877 Chip */

#include <16F877.h>

#fuses XT,NOWDT,NOPROTECT,NOLVP,PUT

/* Delay for 4 mhz crystal */

#use delay (clock=4000000)

/* Setup RS232 */

#use rs232(baud=9600, xmit=PIN_D4,rcv=PIN_D5, INVERT)

/* Setup I2C */

#use I2C(MASTER, sda=PIN_C4, scl=PIN_C3, SLOW)

main()

{

int8 i2c_command = 66;

while (true)

{

delay_ms(1000);

printf("Outputting: %c", i2c_command);

/* Master */

i2c_start(); // Start condition

i2c_write(0xa0); // Device address

i2c_write(i2c_command); // Write Command

i2c_stop(); // Stop condition

}

}

Slave

Code:

/* Standard Include for 16F877 Chip */

#include <16F877.h>

#fuses XT,NOWDT,NOPROTECT,NOLVP,PUT

/* Delay for 4 mhz crystal */

#use delay (clock=4000000)

/* Setup RS232 */

#use rs232(baud=9600, xmit=PIN_D4,rcv=PIN_D5, INVERT)

/* Setup I2C */

#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0xa0, SLOW, FORCE_HW)

#INT_SSP

void ssp_interupt ()

{

byte incoming;

incoming = i2c_read();

printf("\n\rRead byte 1: %x\n\r", incoming);

incoming = i2c_read();

printf("Read byte 2: %x\n\r\n\r", incoming);

}

Page 7: CCS __ View Topic - Need I2C Examples

}

main()

{

delay_ms(1000);

printf("Running");

enable_interrupts(GLOBAL);

enable_interrupts(INT_SSP);

while (true)

{

}

}

valemikeGuest

Posted: Fri Jun 11, 2004 8:17 am

falleaf wrote:

Example codes also here:

Source: http://www.walking-productions.com/school/adtech/ [snip]

Master }[/code]

Not quite. It looks like the slave can only handle incoming bytes, but it doesn't handle when the

master is requesting data. At one time, I too thought it was easy to just do like the example.

However, the "state machine" in the APP note AN735/AN734 is in fact the proper way to handle the

i2c interrupts on the slave side. It's not really a state machine though as far as the source code is

concerned, since I don't have to worry about previous states. I guess the PIC's SSP does it for us.

You just have to worry about the current contents of SSPSTAT with each interrupt.

-Mike

falleaf

Joined: 23 May 2004Posts: 48

Posted: Sun Jun 13, 2004 5:43 am

Yes, I used AN735 ASM code, and it worked very good. So the problem is that I don't know exactly

how the C code work!!!. I'm trying to understand it.

Thanks muchie.

ben500Guest

Acknowledgment bit

Posted: Mon Jun 14, 2004 1:09 pm

Hi,

I'm trying to make communicate a PIC16F819 (master) with a PIC16F876 (slave) by I2C. I've tried

now a lot of different example codes, but it is always the same error which occured: the slave does

not send any acknowledgement! According to the datasheets (16f87x, table 9-2), I think I am in the

fifth case where the BF bit is cleared and the SSPOV bit is set. My problem is that I don't know how

to avoid it. Perhaps someone could help me, it is near to break my nerves...

Thanks you,

~Ben

Guest Posted: Thu Jun 17, 2004 3:28 am

Code:

#byte PIC_SSPBUF=0xFC9

#byte PIC_SSPADD=0xFC8

Page 8: CCS __ View Topic - Need I2C Examples

#byte PIC_SSPADD=0xFC8

#byte PIC_SSPSTAT=0xFC7

#byte PIC_SSPCON1=0xFC6

#byte PIC_SSPCON2=0xFC5

#byte PIC_SSPBUF=0x13

#byte PIC_SSPADD=0x93

#byte PIC_SSPSTAT=0x94

#byte PIC_SSPCON1=0x14

You redefine here, and the 4 below lines is use for 16Fxxx PIC only, does it mean in C that the

program can choose one of these address? Or you write as an example for who want to use 16F

PICs?

What is the different between hardware I2C and software?

As using #uses I2C from CCS C, what will it generate?

falleaf

Joined: 23 May 2004Posts: 48

Posted: Thu Jun 17, 2004 3:31 am

Sorry, it's meeh, I forgot to login

valemike1Guest

oops

Posted: Fri Jun 18, 2004 11:17 am

Code:

#byte PIC_SSPBUF=0xFC9

#byte PIC_SSPADD=0xFC8

#byte PIC_SSPSTAT=0xFC7

#byte PIC_SSPCON1=0xFC6

#byte PIC_SSPCON2=0xFC5

#byte PIC_SSPBUF=0x13

#byte PIC_SSPADD=0x93

#byte PIC_SSPSTAT=0x94

#byte PIC_SSPCON1=0x14

When I cut and pasted the code, I dont know why but I took out the #if 0...#endif statements.

Delete one of the groups, since you don't want to redefine twice. The second set

0x13,0x93,0x94,0x14 is for the PIC16F876, 873, etc. The numbers with the 0xFc9, etc. is for the

PIC18F252/452/etc.

-Mike

p.s. Software i2c is bitbanged and you just toggle these pins high and low like any general purpose

i/o pin. Hardware i2c actually uses the built-in MSSP/SSP module. If you must use i2c, then go use a

PIC with the hardware i2c mssp/ssp module. That way you won't burn processor time bitbanging.

falleaf

Joined: 23 May 2004Posts: 48

Posted: Sat Jun 19, 2004 3:15 am

Yes, I'm using 16F876A and 16F877A. I'm using 16F876A as a slave and 877 as the master.

Everything seems oki.

I found that CCS C is really like normal C, and the function is clear. But I still cannot read the ASM

code generated from CCS C.

Page 9: CCS __ View Topic - Need I2C Examples

code generated from CCS C.

With your code, I save it as a file i2c_slave_mike.c and include to my program, then use it.

Code:

#byte PIC_SSPBUF=0x13

#byte PIC_SSPADD=0x93

#byte PIC_SSPSTAT=0x94

#byte PIC_SSPCON1=0x14

#byte PIC_SSPCON2=0x91

And I see that there is some #define *BIT* you didn't use in the code. Will it takes the memories a

compiling the code? Because as defining, we can only define it as a number. And will the C takes

some memories to save those number?

By the way, what is the difference between using your code on 16f876 and #uses I2C of CCS C?

Because I see that we can force it to hardware mode?

I would like to understand more about function i2c_start();

As it generate start condition, will it reset the buffer_index? Because if I would like to use 8 first

bytes to save data from master, and 8 low bytes to save transmit bytes. I will have to set buffer

length as 8 or 16 bytes?

If this is writen identically as AN734, I can use 16 bytes. Because the master will do as below: (I

don't write in CCS C code, because I'm not sure of it).

function TX_RX ()

{

start condition

send the address of slave in write mode

for i from 1 to 8

write (data[i]);

start condition

send the address of slave in read mode

for i from 9 to 16

data[i] = read_i2c;

}

In slave chip, I have 16 bytes buffer. In write condition of master, the slave will receive 8 byte and

save to buffer[1..8]. After that, the read condition, the index still at 9. Then the slave will send

buffer[9..16].

May we do this with your code?

Then each sampling time I only have to call function TX_RX. I can send and receive all what I need.

I see that you put buffer_index as a global variable, so that it can do this. In ASM, I can easily know

exactly register address, so I don't care muchie as writing in ASM, but C for PIC confuse meeh

And pls explain me about #uses I2C in CCS C? which is smaller code between yours and force

hardware CCS C? I'm using 16F876a.

Thanks muchie.

falleaf Posted: Sun Jun 20, 2004 11:57 am

Page 10: CCS __ View Topic - Need I2C Examples

Joined: 23 May 2004Posts: 48

Mike,

I've tested with your code, the tx from master to slave is oki, but as rx, it wrong.

In your code, I've tested:

master:

....

i2c_write(0x05);

i2c_write(0x06);

i2c_write(0x07);

i2c_start(); //restart

i2c_write(add +1); // normally in asm I used to set this bit0

byte1 = i2c_read();

byte2 = i2c_read();

...

but rx way is not good, and I receive wrong result.

Pls explain me about this.

valemikeGuest

Posted: Mon Jun 21, 2004 3:28 pm

For receiving, you will need to determine what you want to put in the outgoing bytes. The global

array I provided is just an example taken from the application note. However, it is pretty much

useless by itself.

So, you said that you tried it and it works fine for master sending bytes to the slave, and you

confirmed that the slave received the bytes? But when the master tries to read from the slave, then

you get errors?

I'll try to answer your questions later this evening when I go home.

-Mike

Guest Re: Acknowledgment bit

Posted: Mon Jun 21, 2004 3:33 pm

ben500 wrote:

Hi,

I'm trying to make communicate a PIC16F819 (master) with a PIC16F876 (slave) by I2C. I'vetried now a lot of different example codes, but it is always the same error which occured: theslave does not send any acknowledgement! According to the datasheets (16f87x, table 9-2), Ithink I am in the fifth case where the BF bit is cleared and the SSPOV bit is set. My problem isthat I don't know how to avoid it. Perhaps someone could help me, it is near to break my

nerves...

Thanks you,

~Ben

When using the CCS-supplied libraries for the MASTER, my AN735-based Slave gets NACK states

(case 5?) all the time, but it doesn't seem to hurt anything.

Display posts from previous: All Posts Oldest First Go

CCS Forum Index -> General CCS C DiscussionAll times are GMT - 6 Hours

Goto page Previous 1, 2, 3 Next

Page 2 of 3

Watch this topic for replies

Jump to: General CCS C Discussion Go

Page 11: CCS __ View Topic - Need I2C Examples

You can post new topics in this forumYou can reply to topics in this forum

You can edit your posts in this forumYou can delete your posts in this forum

You can vote in polls in this forum

Powered by phpBB © 2001, 2005 phpBB Group