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

MAX5418LETA+ I2C Communication

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



Joined: 09 Jul 2008
Posts: 3
Location: South Windsor, CT

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

MAX5418LETA+ I2C Communication
PostPosted: Wed Jul 09, 2008 9:29 am     Reply with quote

I'm trying to communicate with a MAX5418 digital potentiometer using a PIC16F873A-I/SP. I'm supposed to write 8 bits and then clock a 9th bit so that the MAX5418 chip can pull down the SDA line as an acknowledge. I assume this is part of the I2C specification and therefore the i2c_write includes this functionality (but I could be wrong). I do have pull-up resistors on SDA and SCL. (Before I put the pull ups on, the chip was resetting whenever I tried to send anything over I2C).

I send the following data I don't know how I would go about figuring out if I'm getting an ACK from the MAX5418 or some other issue. Any ideas?
Attached is some code snippets in case there's something simple that I'm missing that someone could kindly point out.
Code:

// I2C for MAX5418 commmunication
#use I2C(master, sda=PIN_C4,scl=PIN_C3, FORCE_HW, FAST=300000, NOFLOAT_HIGH, RESTART_WDT)
//sets the target speed to 300 KBSP

#define MAX518_ADDRESS_W   0x50    //Address can be 0x50 or 0x52
                                   //depending upon MAX5418_AO_OUT.
#define MAX518_VREG        0x11    //Write to volatile memory and update position.

OUTPUT_LOW(MAX5418_AO_OUT);//MAX518 Address is 0x50 when low,0x52 when high.

            i2c_start();
            i2c_write(MAX518_ADDRESS_W);
            i2c_write(MAX518_VREG);
            i2c_write(brt_pos_count);
            i2c_stop();

rnielsen



Joined: 23 Sep 2003
Posts: 852
Location: Utah

View user's profile Send private message

PostPosted: Wed Jul 09, 2008 9:57 am     Reply with quote

The i2c_write() function returns the ACK bit. So, you could write something like this as part of your code:

Code:
var = i2c_write(address);


This would place the ACK into var. A 0 means your device ACK'd. A 1 means it returned a NOACK.

You could also write something like this:

Code:
if(!i2c_write(address))


This could test if the function returned a 0. You could then place the rest of your I2C code inside of the if() statement. If the device returned a NOACK then you could skip the rest of the I2C code or try to restart your I2C code to attempt to talk to it again.

Clear as mud?

Ronald
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jul 09, 2008 11:56 am     Reply with quote

Quote:
I assume this is part of the I2C specification and therefore the i2c_write includes this functionality

That's correct.

Post a complete test program. The program should contain the code
that you posted above, but it should be a complete, compilable program.
It should have the #include statement for the PIC, and the #fuses,
#use delay() statements. It should have a main(). Post all required
variable declarations and #define statements. Keep it short.

Also post your compiler version.
rgreger2



Joined: 09 Jul 2008
Posts: 3
Location: South Windsor, CT

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

PostPosted: Wed Jul 09, 2008 1:02 pm     Reply with quote

Code:

#include <16F873A.h>
#device adc=8

#FUSES NODEBUG                 //No Debug mode for ICD
#FUSES WDT                     //Watch Dog Timer
#FUSES HS                      //High speed Osc (> 4MHz)
#FUSES PUT                     //Power Up Timer
#FUSES NOPROTECT               //Code not protected from reading
#FUSES BROWNOUT                //Brownout reset
#FUSES NOLVP                   //No low voltage programming,
                               //B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                   //No EE protection
#FUSES NOWRT                   //No Write Protection
// Restart Watchdog Timer during delays
#use delay(clock=18432000, RESTART_WDT)      //18.432 MHz
// I2C for MAX5418 commmunication
#use I2C(master, sda=PIN_C4,scl=PIN_C3, FORCE_HW, FAST=300000, NOFLOAT_HIGH, RESTART_WDT)
//sets the target speed to 300 KBSP
// MAX5418LETA+ Address
#define MAX518_ADDRESS_W   0x50    //Address can be 0x50 or 0x52
                                   //depending upon MAX5418_AO_OUT.
#define MAX518_VREG        0x11    //Write to volatile memory and update position.
#define GLED_OUT  50               //Green LED output (0 = LED Off, 1 = LED On)
#define YLED_OUT    58             //Yellow LED output (1=On, 0=Off)
#define MAX5418_AO_OUT   61        //MAX5418, A0

void main()
{
#use FAST_IO(B)
#use FAST_IO(C)

          /*PORTB INPUT/OUTPUT PORT
             Bit  Function     
              7 = PGD    (Input) (TRIS=1)
              6 = PGC    (Input) (TRIS=1)
              5 = Unused (Input) (TRIS=1)
              4 = Unused (Input) (TRIS=1)
              3 = PGM    (Input) (TRIS=1)
              2 = Green LED Out,(0 = LED Off, 1 = LED On) (GLED_OUT)
              1 = Unused (Input) (TRIS=1)
              0 = Output*/
        set_tris_b(0xFA);          //PORTB set to output on pins 2,0

          /*PORTC INPUT/OUTPUT PORT
             Bit  Function     
              7 = Input
              6 = Output
              5 = MAX5418, A0    (Output) (MAX5418_AO_OUT)
              4 = MAX5418, SDA    (Input) (TRIS=1) (I2C_SDA_IN)
              3 = MAX5418, SCL    (Input) (TRIS=1) (I2C_SCL_IN)
              2 = Yellow LED Out,(0 = LED Off, 1 = LED On) (YLED_OUT)
              1 = Input
              0 = Output*/
             
         set_tris_c(0x9A);          //PORTC set to output on pins 6,5,2,0

         OUTPUT_LOW(MAX5418_AO_OUT);//MAX5418 Address is 0x50 when low,0x52 when high.
         setup_wdt(WDT_576MS);      //Setup WDT for 576 milliseconds

         while(1)
         {
               restart_wdt();
               OUTPUT_LOW(GLED_OUT);
               OUTPUT_LOW(YLED_OUT);

               delay_ms(5000);      //Delay 5 seconds
               //Update brightness to zero on MAX5418
               i2c_start();
               if(!i2c_write(MAX518_ADDRESS_W))
               {
                  i2c_stop();
                  //Blink 1 time
                  OUTPUT_HIGH(YLED_OUT);
                  delay_ms(1000);
                  OUTPUT_LOW(YLED_OUT);
               }
               else
               {
                  if(!i2c_write(MAX518_VREG))
                  {
                     i2c_stop();
                     //Blink 2 times
                     OUTPUT_HIGH(YLED_OUT);
                     delay_ms(1000);
                     OUTPUT_LOW(YLED_OUT);
                     delay_ms(1000);
                     OUTPUT_HIGH(YLED_OUT);
                     delay_ms(1000);
                  }
                  else
                  {
                     if(!i2c_write(0x00))
                     {
                        i2c_stop();
                         //Blink 3 times
                        OUTPUT_HIGH(YLED_OUT);
                        delay_ms(1000);
                        OUTPUT_LOW(YLED_OUT);
                        delay_ms(1000);
                        OUTPUT_HIGH(YLED_OUT);
                        delay_ms(1000);
                        OUTPUT_LOW(YLED_OUT);
                        delay_ms(1000);
                        OUTPUT_HIGH(YLED_OUT);
                        delay_ms(1000);
                     }
                     else
                     {
                        i2c_stop();
                        OUTPUT_HIGH(GLED_OUT); //Success
                        delay_ms(5000);      //Delay 5 seconds
                     }
                  }
               }
         }
}

Compiler Version 4.04
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jul 09, 2008 2:09 pm     Reply with quote

That's not a simple test program, or at least not a short one.
This is what I was thinking of:
Notice that I got rid of the Watchdog timer and all the "ack" and LED
stuff. I use software i2c at the default slow speed. I let the compiler
set the TRIS for me. The main loop is simple. Notice I made the
MAX518 code into a function and I call it. Notice that I don't use magic
numbers for the i/o pins. I use the CCS pin names from the .H file.
This is a simple test program.
Code:

#include <16F873A.H>
#fuses HS,NOWDT,NOPROTECT,BROWNOUT,PUT,NOLVP
#use delay(clock=18432000)       
#use i2c(master, sda=PIN_C4, scl=PIN_C3)

#define MAX518_ADDRESS_W   0x50     
#define MAX518_VREG        0x11  // Wrt to volatile mem and update pos.

#define GLED_OUT   PIN_B2       // Green LED (0=Off, 1=On)
#define YLED_OUT   PIN_C2       // Yellow LED (1=On, 0=Off)
#define MAX5418_AO_OUT  PIN_C5  // MAX5418, A0


void max5418_write_vreg(int8 value)
{
i2c_start();
i2c_write(MAX518_ADDRESS_W);
i2c_write(MAX518_VREG);
i2c_write(value);   // Brightness
i2c_stop();
}

//=================================
void main()
{
output_low(MAX5418_AO_OUT); // Addr is 0x50 when low, 0x52 when high
delay_ms(100);

output_low(GLED_OUT);
output_low(YLED_OUT);

while(1)
  {
   max5418_write_vreg(0xFF);
   delay_ms(500);

   max5418_write_vreg(0x00);
   delay_ms(500);
  }


}

This program should change the digital pot between the min and max
resistance values every 500 ms. If you connect +5v to one end, and
ground to the other end, and then put a voltmeter (or scope) on the
wiper, you should see the wiper pin switch between +5v and ground
every 500 ms.


Quote:
Compiler Version 4.04

This is not the complete version number. You have dropped the last
digit. The last digit is quite significant. There might be 50 bugs or
features between vs. 4.040 and 4.049. Always give the full vs. number.
rgreger2



Joined: 09 Jul 2008
Posts: 3
Location: South Windsor, CT

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

Simple Test Program
PostPosted: Thu Sep 25, 2008 10:14 am     Reply with quote

Thank you for the simple program. I have now confirmed that the IC2 communication functions between the PIC and the MAX5418.

I will take your advice regarding "I use the CCS pin names from the .H file". Previously, I copied and pasted the CCS Pin Names from the .h file and rewrote the pin names using my own identifiers, but your way is much easier to read and less prone to errors.
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