• AVR Freaks

Helpful ReplyHot![Solved] PIC32MZ With I2C MCP4725 DAC (Non-Harmony)

Author
TS9
Super Member
  • Total Posts : 879
  • Reward points : 0
  • Joined: 2010/05/07 10:52:22
  • Status: offline
2019/12/08 23:26:57 (permalink)
0

[Solved] PIC32MZ With I2C MCP4725 DAC (Non-Harmony)

Hi,
 
I am working on PIC32MZ2048EFM144 TQFP With I2C MCP4725 DAC  (Non-Harmony).
The MCP4725 with interface with PIC32MZ 10K Pull Ups with SDA and SCL),A0 Tied to GND , VDD = +3.3V .
 
The PIC32MZ is successfully communicated with MCP4725 DAC . I am using Write DAC Register using Fast Mode Write Command Only. I am not using MCP4725's EEPROM.
 
I am facing two below issue:
 
1)  Reading varies from  0V to 1.65V. How to Select 0 to 3.3V ? Is it Possible VDD= VREF ?
2) I am not getting exact slope from 0 to 1.65 V . I have checked with Digital Multi-meter .
Reading are like below:
0.26V, 0.31,0.41,0.43, 0.45,0.47,0.42, 0.44 and So On ....
 
I have checked with I2C Clock Frequency 100KHz and 400KHz . But Results are same..
 
 
 

 
#define SYS_FREQ 200000000
 
unsigned char FirstByte = 0xC0 ; //Address Byte
unsigned char SecondByte_FM = 0x00; //Command+ Powerdown
unsigned char ThirdByte_FM = 0x00; //Data Byte2
void MCP4725_I2C_DAC_TEST();
 
void TestI2CMemory24C02();
 
unsigned int I2C_ack(void) ;
 
void _mon_putc (char c);
 

// I2C_wait_for_idle() waits until the I2C peripheral is no longer doing anything
void I2C_wait_for_idle(void)
{
while(I2C2CON & 0x1F); // Acknowledge sequence not in progress
// Receive sequence not in progress
// Stop condition not in progress
// Repeated Start condition not in progress
// Start condition not in progress
while(I2C2STATbits.TRSTAT); // Bit = 0 ? Master transmit is not in progress
}
 
// I2C_start() sends a start condition
void I2C_start()
{
I2C_wait_for_idle();
I2C2CONbits.SEN = 1;
while (I2C2CONbits.SEN == 1);
}
 
// I2C_stop() sends a stop condition
void I2C_stop()
{
I2C_wait_for_idle();
I2C2CONbits.PEN = 1;
}
 
// I2C_restart() sends a repeated start/restart condition
void I2C_restart()
{
I2C_wait_for_idle();
I2C2CONbits.RSEN = 1;
while (I2C2CONbits.RSEN == 1);
}
 
// I2C_ack() sends an ACK condition
unsigned int I2C_ack(void)
{
I2C_wait_for_idle();
I2C2CONbits.ACKDT = 0; // Set hardware to send ACK bit
I2C2CONbits.ACKEN = 1; // Send ACK bit, will be automatically cleared by hardware when sent
while(I2C2CONbits.ACKEN); // Wait until ACKEN bit is cleared, meaning ACK bit has been sent
}
 
// I2C_nack() sends a NACK condition
void I2C_nack(void) // Acknowledge Data bit
{
I2C_wait_for_idle();
I2C2CONbits.ACKDT = 1; // Set hardware to send NACK bit
I2C2CONbits.ACKEN = 1; // Send NACK bit, will be automatically cleared by hardware when sent
while(I2C2CONbits.ACKEN); // Wait until ACKEN bit is cleared, meaning NACK bit has been sent
}
 
// address is I2C slave address, set wait_ack to 1 to wait for ACK bit or anything else to skip ACK checking
void I2C_write(unsigned char address, char wait_ack)
{
I2C2TRN = address | 0; // Send slave address with Read/Write bit cleared
while (I2C2STATbits.TBF == 1); // Wait until transmit buffer is empty
I2C_wait_for_idle(); // Wait until I2C bus is idle
if (wait_ack) while (I2C2STATbits.ACKSTAT == 1); // Wait until ACK is received
}
 
// value is the value of the data we want to send, set ack_nack to 0 to send an ACK or anything else to send a NACK
int I2C_read( char ack_nack)
{
unsigned char value;

I2C2CONbits.RCEN = 1; // Receive enable
while (I2C2CONbits.RCEN); // Wait until RCEN is cleared (automatic)
while (!I2C2STATbits.RBF); // Wait until Receive Buffer is Full (RBF flag)
//

if (!ack_nack) // Do we need to send an ACK or a NACK?
I2C_ack(); // Send ACK
else
I2C_nack(); // Send NACK

value = I2C2RCV; // Retrieve value from I2C2RCV

return value ;
}
 
unsigned int MCP4725FastModeWriteI2C(unsigned char FirstByte, unsigned char SecondByte_FM, unsigned char ThirdByte_FM)
{
unsigned int ErrorCode;
_mon_putc ('s') ;
 
I2C_wait_for_idle();
I2C_start();
I2C_write(FirstByte , 1) ; // _mon_putc ('C') ;
I2C_wait_for_idle();

ErrorCode = I2C_ack() ;

I2C_write(SecondByte_FM , 1) ;
I2C_wait_for_idle();
ErrorCode = I2C_ack();

I2C_write(ThirdByte_FM , 1) ;
I2C_wait_for_idle();
ErrorCode = I2C_ack();

I2C_wait_for_idle();
I2C_stop();
_mon_putc ('P') ;
return(ErrorCode);
}
void MCP4725_I2C_DAC_TEST()
{

ThirdByte_FM = ThirdByte_FM + 1 ;
if (ThirdByte_FM == 0xFF )
{
ThirdByte_FM = 0x00;
SecondByte_FM = SecondByte_FM + 1 ;

if (SecondByte_FM > 0x0F)
{
SecondByte_FM = 0x00;
}
}
MCP4725FastModeWriteI2C(FirstByte, SecondByte_FM, ThirdByte_FM);

}
// I2C_init() initialises I2C2 at at frequency of [frequency]Hz
void I2C_init(double frequency)
{
double BRG;

I2C2CON = 0; // Turn off I2C2 module
I2C2CONbits.DISSLW = 1; // Disable slew rate for 100kHz

BRG = (1 / (2 * frequency)) - 0.000000104;
BRG *= (SYS_FREQ / 2) - 2;

I2C2BRG = (int)BRG; // Set baud rate
I2C2CONbits.ON = 1; // Turn on I2C2 module
}
void main()
{
unsigned char value;

// Set performance to ultra rad
set_performance_mode();

// Moved all the ANSEL, TRIS and LAT settings to their own function
setup_ports();

// Enable multi-vectored interrupts mode
INTCONbits.MVEC = 1;

UART2PPS() ;
UART2_Init();

// Initialise I2C2 at 400kHz
I2C_init(400000);
_mon_putc ('a') ;
while (1)
{
_mon_putc ('Z') ;
MCP4725_I2C_DAC_TEST();
// Wait 10ms Before Second Reading
delay_ms(10);
}
}
 

 
Thanks in advance ..
 
--
TS9
post edited by TS9 - 2019/12/16 00:06:01
#1
andersm
Super Member
  • Total Posts : 2833
  • Reward points : 0
  • Joined: 2012/10/07 14:57:44
  • Location: 0
  • Status: online
Re: PIC32MZ With I2C MCP4725 DAC (Non-Harmony) 2019/12/09 16:33:54 (permalink) ☄ Helpfulby TS9 2019/12/09 20:25:26
0
The MCP4725_I2C_DAC_TEST() function will skip values, eg. go from 0x0FE directly to 0x100. Also, having local variables with the same name as globals is a source of bugs waiting to happen.
 
This isn't great code either, but slightly better:
void MCP4725_I2C_DAC_TEST(void)
{
    static uint16_t dac_value = 0;
    MCP4725FastModeWriteI2C(dac_value, dac_value >> 8, ThirdByte_FM);
    if (++dac_value > 4095) {
      dac_value = 0;
    }
}

#2
TS9
Super Member
  • Total Posts : 879
  • Reward points : 0
  • Joined: 2010/05/07 10:52:22
  • Status: offline
Re: PIC32MZ With I2C MCP4725 DAC (Non-Harmony) 2019/12/09 18:26:59 (permalink)
0
Thanks for your update...and
code..

I will try your suggestion and update you.

But first parameter should be Hardware address (0xC0)..as mentioned in datasheet of MCP4725.

And you haven't mentioned any device address in your code snippet ..

Please Correct me..

N How to Select VDD = VRef
for 0 to 3.3V

--
TS9
post edited by TS9 - 2019/12/09 18:38:29
#3
simong123
Lab Member No. 003
  • Total Posts : 1391
  • Reward points : 0
  • Joined: 2012/02/07 18:21:03
  • Location: Future Gadget Lab (UK Branch)
  • Status: offline
Re: PIC32MZ With I2C MCP4725 DAC (Non-Harmony) 2019/12/09 20:13:19 (permalink) ☄ Helpfulby TS9 2019/12/09 20:25:17
0
TS9
N How to Select VDD = VRef
for 0 to 3.3V
--
TS9

Vref is always VDD for the MCP4725
andersm's code should be
void MCP4725_I2C_DAC_TEST(void)
{
    static uint16_t dac_value = 0;
    MCP4725FastModeWriteI2C(FirstByte_FM, dac_value >> 8, dac_value);
    if (++dac_value > 4095) {
      dac_value = 0;
    }
}

#4
TS9
Super Member
  • Total Posts : 879
  • Reward points : 0
  • Joined: 2010/05/07 10:52:22
  • Status: offline
Re: PIC32MZ With I2C MCP4725 DAC (Non-Harmony) 2019/12/09 20:23:59 (permalink)
0
Thanks.. I will check and update to you..
 
--
TS9
#5
TS9
Super Member
  • Total Posts : 879
  • Reward points : 0
  • Joined: 2010/05/07 10:52:22
  • Status: offline
Re: PIC32MZ With I2C MCP4725 DAC (Non-Harmony) 2019/12/14 02:13:48 (permalink)
0
Hi,
 
I have changed as below: 

unsigned int MCP4725NormalModeWriteI2C(
unsigned char FirstByte,
unsigned char SecondByte_SM ,
unsigned char ThirdByte_EE,
unsigned char FourthByte_EE)
{
unsigned int ErrorCode;
I2C_wait_for_idle();
I2C_start();

I2C_write(FirstByte , 1) ;
I2C_write(SecondByte_SM , 1) ;
I2C_write(ThirdByte_EE, 1) ;
I2C_write(FourthByte_EE , 1) ;

I2C_wait_for_idle();
I2C_stop();
return(ErrorCode);
}
unsigned int MCP4725FastModeWriteI2C(unsigned char FirstByte, unsigned char SecondByte_FM, unsigned char ThirdByte_FM)
{
unsigned int ErrorCode;

I2C_wait_for_idle();
I2C_start();
I2C_write(FirstByte , 1) ; ;

I2C_write(SecondByte_FM , 1) ;
I2C_write(ThirdByte_FM , 1) ;

I2C_wait_for_idle();
I2C_stop();

return(ErrorCode);
}
nt MCP4725ModeSelect = 0;
void MCP4725_I2C_DAC_TEST()
{
static uint16_t dac_value = 0;
if(MCP4725ModeSelect == 0 ) // This is for Normal Mode
{
MCP4725NormalModeWriteI2C(
MCP4725HardWareAddress ,
MCP4725InternalAddress_Normal_Mode,
dac_value >> 4,
dac_value << 4
) ;
if (++dac_value > 4095)
{
dac_value = 0;
}
}
else // This is For Fast Mode
{
MCP4725FastModeWriteI2C(MCP4725HardWareAddress ,dac_value >> 8 , dac_value);
if (++dac_value > 2048)
{
dac_value = 0;
}
}

}

Now MCP4725 Worked with both Normal  (0 to 3.3V)and Fast Mode (0 to1.65V)  .
 
--
TS9
#6
Jump to:
© 2020 APG vNext Commercial Version 4.5