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

I2C Help needed

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



Joined: 09 Jun 2009
Posts: 23

View user's profile Send private message

I2C Help needed
PostPosted: Sat May 19, 2012 3:15 am     Reply with quote

Hi all,

I need some help to understand and control this chip (HV881); it uses I2C protocol to turn ON/OFF EL lamps.

So far I have wired the chip correctly and I have started to write a program to control it using 12F629 PIC. I did read through the forum and cannot find something similar to help me to understand a way to send the data and the acknowledgement to the chip.

The data sheet link attached below (i2c page 5). So please have a look at it and any help would be really appreciated. Sad

http://www.supertex.com/pdf/datasheets/HV881.pdf

BTW: I have poor programming skills and I haven’t done anything with I2C before so please make it simple Embarassed

My initial code is (assuming with right data and acknowledgement the chip will output something Question ):-

Code:
#include <12F629.h>   
#fuses NOWDT, NOPROTECT,INTRC_IO, NOPUT,NOBROWNOUT, NOCPD
#use delay(clock=4000000)   
#use i2c(Master,sda=PIN_A3,scl=PIN_A2)   

void main()
{

char z;

while(1)
 {
  i2c_start();                   
  i2c_write(0x06);   //send address
  i2c_write(0x00);   //data (problem here what shall I send to turn  ON for example the 1st and 16th lamps?)
  i2c_stop();
  delay_ms(100); 

}

}
Ttelmah



Joined: 11 Mar 2010
Posts: 19278

View user's profile Send private message

PostPosted: Sat May 19, 2012 4:23 am     Reply with quote

Taking things one by one:

First the device address. This is a _seven bit_ value 0b0000110, sent as the _top_ seven bits of the byte you write to the device. The low bit is the 'bus direction' control (R/W), which is always '0' for this device (you can only write to it). So the byte you have to send for the address is 0b00001100 = 0x0C, or 12 in decimal. This is a real 'annoyance' with I2C, with some devices telling you about this, saying to use bytes of 12/13 (for write/read if the device supported this), while others just give the 7bit value and assume you know how to translate it.

Second have you got the pull up resistors on the bus?. Often forgotten, and the cause of a lot of grief....

Now, if you at there example 'packet', you are meant to send the device address followed by eight bytes to control the sixteen tamp outputs (one nibble for each). Each byte is acknowledged by the slave device. When you perform an I2C_WRITE function, this _returns_ the ACK bit.

So make your function generic:
Code:

#include <12F629.h>   
#fuses NOWDT, NOPROTECT,INTRC_IO, NOPUT,NOBROWNOUT, NOCPD
#use delay(clock=4000000)   
#use i2c(Master,sda=PIN_A3,scl=PIN_A2)   

int1 set_levels(int8 levels[]) {
    //Structure the 'levels' array as sixteen values for the 16 lamps
   int8 ictr;
   int8 bytetosend;
   int1 ack;
   I2C_START();
   ack = I2C_WRITE(0xC); //address the device
   if (ack==1) {
       I2c_STOP(); //device did not ACK
       return FALSE;
   }
   for (ictr=0;ictr<16;ictr++) {
       if (bit_test(ictr,0)==0) { //first byte of pair
          bytetosend=levels[ictr];
       }
       else {
          bytetosend+=(levels[ictr]<<4); //second byte of pair
          ack=I2C_WRITE(bytetosend);
          if (ack==1) {
             I2c_STOP(); //device did not ACK
             return FALSE;
          }
       }
    }
    //Get here all eight bytes have sent and been ack'd
    I2C_STOP();
    return TRUE;
}         
         
void main(void) {
    int8 lamps[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    //ensure all levels start as 0.

    do {
        lamps[0]=15; //First lamp to 'full on'
        lamps[15]=8; //Sixteenth lamp 'half on'

        if (set_levels(lamps)==FALSE) {
            //Here something has gone wrong - flash an LED or something....
        }
        delay_ms(10000); //wait ten seconds
        lamps[0]=0;  //first lamp 'off'
        lamps[15]=15; sixteenth lamp full on
        if (set_levels(lamps)==FALSE) {
            //Here something has gone wrong - flash an LED or something....
        }

        delay_ms(10000); wait another ten seconds
    }
}


Lamp 'levels' are 0 to 15 for off to full power.

Probably full of errors, just 'typed in', on the screen, but it should give you a starting point.

Best Wishes
nizar445



Joined: 09 Jun 2009
Posts: 23

View user's profile Send private message

Wow Wow Wow
PostPosted: Sat May 19, 2012 9:41 am     Reply with quote

@Ttelmah

First: Thanks a lot for your generous explanation and help. Thank god I do understand the address and the R/W bits now all because of your clear explanations.

Second: Yes, you are right, I have missed the pull up resistors. Embarassed

From what I found on the net that they are used to determine the speed of the communication etc.. I will use 4.7k for them do you think that’s reasonable enough to just get me going?

Third: about the code you have written can you please explain it into more details as I am very interested in understanding it more than copying it Embarassed

Especially the following parts (excuse my poor programming skills and understanding):-

What are you doing here and what do you mean by that?
Code:
int1 set_levels(int8 levels[]) { 
    //Structure the 'levels' array as sixteen values for the 16 lamps



Does the acknowledgement need to be zero? Does it say that on the data sheet or it’s something common?
Code:
if (ack==1) {
       I2c_STOP(); //device did not ACK
       return FALSE;



bit_test where did you define that?
Code:
if (bit_test(ictr,0)==0) { //first byte of pair



How is that related to the code above the void main(void) !!?
Code:
   int8 lamps[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    //ensure all levels start as 0.
    do {
        lamps[0]=15; //First lamp to 'full on'

Sorry again for my poor understanding. I think you trying to control the brightness in one section and then control the ON/OFF in the main program am I right?

BTW: I have tried to compile your code and it keeps pointing towards the place under the void main(void) and says expecting a WHILE shall I just stick a while(1) loop there?

Sorry again about the inconvenience and thanks alot for help.

Best regards
Nizar
jeremiah



Joined: 20 Jul 2010
Posts: 1320

View user's profile Send private message

PostPosted: Sat May 19, 2012 1:04 pm     Reply with quote

You need to spend some time looking at the compiler manual. It answers a lot of your questions, such as bit_test() and the ack question
temtronic



Joined: 01 Jul 2010
Posts: 9142
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sat May 19, 2012 2:45 pm     Reply with quote

hint..
When you have your project open, press F11 to get the manual to magically open up !!
Keep it open to get instant access to all the stuff you need to know !!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat May 19, 2012 3:12 pm     Reply with quote

Quote:

BTW: I have tried to compile your code and it keeps pointing towards the
place under the void main(void) and says expecting a WHILE shall I just
stick a while(1) loop there?


The code looks like this:
Code:

  do {
        .
        .
        .

    }

Look in a C language manual and see what keyword is supposed to
come after the closing brace.
Ttelmah



Joined: 11 Mar 2010
Posts: 19278

View user's profile Send private message

PostPosted: Sun May 20, 2012 3:52 am     Reply with quote

As I said, just typed in....

Manual will answer most questions (including what I have forgotten to put in on the penultimate line....).

Some comments though:

First thing. Visualise you are asked to do the accounts for a company with 10000 employees. I doubt if anybody would start with a single large 'ledger', and try to do the accounts in one 'lump'. Instead, they would do the accounts for (say) the front office, in one book, make sure these check and work out, do the same for a dozen other 'parts' of the company, and then take the results from these, and combine them to give the final result. Keeping the sections small enough, is a vital tool in a lot of things, and applies to software as much as this example. You should 'segment' your job. Thinking 'code to set the power levels on the lamps'. 'code to scan keyboard/serial', 'code to display results', etc. etc.. Each section can then be checked _on it's own_, with just a small 'test' program calling it. This is where subroutines and functions come in in coding.

Basically you need to look at a basic C book. Routines can either be declared 'in front' of where they are used, _or_ you can declare a 'prototype' (which tells the compiler what they are 'going' to contain), and then the physical routine can be declared later. I elected to use the former approach here.

The chip _does not_ have a command for 'on/off'. It controls 16 lamps, and allows you to set the level for each from '0' to '15'. Each of these numbers is coded as 4 bits in a byte, so it expects to receive 8 bytes to control the 16 lamps. A value of '0', turns a lamp 'off', while a value of '15', turns a lamp full 'on'. Values between give you different levels between this. So turning 'on/off', is done by setting the level to 0, or 15.

I wrote the function to accept 16 'lamp level numbers', each between 0, and 15 (inclusive), which it then converts into the eight bytes, and sends to the chip. Since the 16 values need to encode to eight bytes, the 'even', and 'odd' value have to be treated differently. The 'bit_test', is one way of telling if a number is even or odd.

Best Wishes
nizar445



Joined: 09 Jun 2009
Posts: 23

View user's profile Send private message

PostPosted: Sun May 20, 2012 5:46 am     Reply with quote

@jeremiah and temtronic

Thanks a lot for referring me to the C compiler manual, I haven’t seen it before.

@ PCM programmer

Found it thank you for the hint Embarassed .
nizar445



Joined: 09 Jun 2009
Posts: 23

View user's profile Send private message

Thanks
PostPosted: Sun May 20, 2012 5:47 am     Reply with quote

@Ttelmah

Thanks again for your help and clear explanations.

I do understand the main objective of the code you have written but the part that I don’t understand is that how is the function you have written “int1 set_levels(int8 levels[]) “ is called in the main program “void main(void) “.

Please be patient with me as programming is not my area.

Thanks again and again.
Ttelmah



Joined: 11 Mar 2010
Posts: 19278

View user's profile Send private message

PostPosted: Sun May 20, 2012 1:20 pm     Reply with quote

This really is basic 'C', and some reading should explain it.

In 'C', there are two ways of addressing 'lists' of things. An 'array', and a 'pointer'. The name of an array, is the pointer _to_ the array.

I declare a 16 number array (for the 16 lamps), and fill it with zeros (just so the unused lamps are turned 'off'). Then change the two values for the lamps we want to control (lamps[0], and lamps[15]), then hand the _pointer_ to the array to the subroutine. The subroutine is written so it 'knows' the pointer it receives, is to an array of integers, so uses these to build the bytes to send. It really is basic 'C 101' stuff, and you need to be able to understand this before you have any hope of writing meaningful code. Get a C primer.

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
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