|
|
View previous topic :: View next topic |
Author |
Message |
rgreger2
Joined: 09 Jul 2008 Posts: 3 Location: South Windsor, CT
|
MAX5418LETA+ I2C Communication |
Posted: Wed Jul 09, 2008 9:29 am |
|
|
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
|
|
Posted: Wed Jul 09, 2008 9:57 am |
|
|
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
|
|
Posted: Wed Jul 09, 2008 11:56 am |
|
|
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
|
|
Posted: Wed Jul 09, 2008 1:02 pm |
|
|
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
|
|
Posted: Wed Jul 09, 2008 2:09 pm |
|
|
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
|
Simple Test Program |
Posted: Thu Sep 25, 2008 10:14 am |
|
|
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. |
|
|
|
|
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
|