Author Topic: Setting Address on a I2C DAC  (Read 3205 times)

0 Members and 1 Guest are viewing this topic.

Offline dan3460Topic starter

  • Frequent Contributor
  • **
  • Posts: 326
  • Country: us
Setting Address on a I2C DAC
« on: May 27, 2017, 10:08:24 pm »
I need to setup a new address for the I2C bus for a DAC chip (MCP4728T), I didn't realized that the instructions are very specific, there are 4 bytes to be sent and you have to toggle a pin up and down. The problem is where the pin needs to go from high to low and from low to high. "The LDAC pin needs to transition from high to low at during the negative part of the 8 bit of the second byte..." similar for the low to high on the 8 bit of the 4 byte. Is there anyway to monitor the SCL pin on the Atmel328P. maybe put an interrupt at the 8th pulse of every 9?
I Know that I can do this by "brute" force by timing the high and low of three pins on the 328p.
 

Offline Ian.M

  • Super Contributor
  • ***
  • Posts: 12855
Re: Setting Address on a I2C DAC
« Reply #1 on: May 27, 2017, 10:15:40 pm »
Comes from: https://www.eevblog.com/forum/microcontrollers/weird-behavior-on-arduino-envioroment/msg1218848/#msg1218848

If its so fussy that you have to toggle the LDAC pin at a particular point in a single bit of the I2C transfer, the best option would be to ignore the TWI module and bit-bang the whole I2C transfer!
 

Offline dan3460Topic starter

  • Frequent Contributor
  • **
  • Posts: 326
  • Country: us
Re: Setting Address on a I2C DAC
« Reply #2 on: May 28, 2017, 01:19:30 am »
Yes, that is what I thought. Almost done making a little program that tickles the pins up and down in the right sequence.

Thanks for the help
 

Offline dan3460Topic starter

  • Frequent Contributor
  • **
  • Posts: 326
  • Country: us
Re: Setting Address on a I2C DAC - MCP4728
« Reply #3 on: May 28, 2017, 11:39:03 am »
I was able to change the address of the chip. In case that any one needs to do this I have included the little program that I made. I'm sure that there are many things that can be changed to make it more efficient but I only needed to do this once and this "brute" force approach suited me.

Code: [Select]
/*
 * MPC4728_address_changer.cpp
 *
 * Created: 5/27/2017 10:42:53 AM
 * Author : Daniel Kolbach
 * This program changes the address to the DAC chip MPC4728.
 * The specs for the chip indicate that you need to control the LDAC pin at a very specific point
 * during the sequence of commands sent to the chip via I2C.
 * Refer to page 42 of the chip in question
 
 * Disclaimer: This software is provided with no implicit or explicit warranties.
 */
#define F_CPU 16000000
#include <avr/io.h>
#include <util/delay.h>

int main(void)
{

DDRB |= (1<<PORTB4)|(1<<PORTB1)|(1<<PORTB0); // Using Arduino Uno, port 8 (PB0) SCL, port 9 (PB1) SDA, port 12 (PB4) LDAC
PORTB |=(1<<PORTB4)|(1<<PORTB1)|(1<<PORTB0);

uint8_t command[4][8]={ 1,1,0,0, 0,0,0,0, // Initial address is 0x60 (0xC0 with the write bit added
0,1,1,0, 0,0,0,1,
0,1,1,0, 0,1,1,0, // Address changed to 0x61
0,1,1,0, 0,1,1,1};

PORTB &= ~(1<<PORTB1); // Sending the start condition for the I2C bus
_delay_us(1.5);
PORTB &= ~(1<<PORTB0);
_delay_us(1.5);

for (int x=0; x<4; x++)  // Repeat this for each of the commands.
{
for (int y=0; y<8; y++)
{
if(command[x][y] == 1) PORTB |= (1<<PORTB1); // Check from the command table if high or low needs to be written to SDA
else PORTB &= ~(1<<PORTB1);
_delay_us(0.5);
PORTB |= (1<<PORTB0); // Send the clock pulse
_delay_us(1.3);
PORTB &= ~(1<<PORTB0);

}
DDRB &= ~(1<<PORTB1);  // Change SDA to input to check for the answer from the chip

if(x==1) PORTB &= ~(1<<PORTB4); // LDAC needs to be pulled down before the 9th clock pulse only on the second command
if(x==3) PORTB |= (1<<PORTB4);  // LDCA needs to be pulled up before the 9th clock pulse only on the 4th command
_delay_us(0.5);
PORTB |= (1<<PORTB0); // Sending the 9th clock pulse
_delay_us(1.5);
PORTB &= ~(1<<PORTB0);
_delay_us(0.3);
DDRB |= (1<<PORTB1); // Returning the SDA line back to output
PORTB |= (1<<PORTB1);
_delay_us (1.7);
}

PORTB &= ~((1<<PORTB0)|(1<<PORTB1)); // Sending the stop signal
_delay_us(1.5);
PORTB |= (1<<PORTB0);
_delay_us(1.5);
PORTB |= (1<<PORTB1);

    while (1)
    {
    }
}

 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf