Interfacing MCP4725, 12 bit DAC with AVR Microcontroller #avrPrayog

I2C was originally invented by Philips electronics (now NXP) for use in consumer electronics products. Download the I2C specification by Philips.

As you know avrPrayog board mounts an AVR microcontroller onto it. AVRs provides a simple way to implement TWI (two wire interface) also known as I2C Communication. Most of the AVR devices has TWI block inbuilt in them. All you need to do is write to some registers in a proper predefined sequence.

The datasheet of ATmega8/ 88/ 168/ 328 elaborates the TWI block, its features, how to use it in a very good manner that even a beginner could understand the underlying strategy used by AVR designers. We will be learning TWI/I2C through an interfacing example. TWI/ I2C is a popular protocol for communication between Integrated Circuits. Huge number of peripheral ICs (Memory, flash, DAC, ADC, Audio controllers) uses I2C for communicating with their respective host controllers or Processor. One such chip is an 12 bit Digital to Analog converter MCP4725 by Microchip.

An interfacing Example : MCP4725 with avrPrayog

We will be interfacing MCP4725 using avrPrayog as Host controller or Master Transmitter and MCP4725 as Slave receiver. Read the datasheet of MCP4725 for more details. In a few words MCP4725 is an 12 bit DAC, its a very tiny 6 pin IC which requires a very few passive components around it to work. It gives nice solid analog voltage, this analog output voltage from mcp4725 can be used for many purposes like giving a stable reference voltage to some other part of circuit.

One very important feature of MCP4725 is, its internal EEPROM of size 14 bits, it can hold the 12 bit digital value to be converted into analog, so when you want mcp4725 to give a stable output analog voltage, you can write the corresponding digital value in the EEPROM of mcp4725, for instance you want your mcp4725 to give a constant voltage of 3.3V when it is not even connected to the host controller (Master Transmitter), you can just write the digital value in the EEPROM once, that results in 3V3 when converted to analog. Once EEPROM burnt, you can remove the TWI connections from mcp4725 and it can independently outputs 3V3 for some utility. Lets see how can we do all these things…(real electronics huhhh….) This is how you will find MCP4725 looks like.

Basic Schematic

Talking is Cheap, Show me the Code !

Ok, enough talking, Lets see how to code avrPrayog, so that it can talk to MCP4725 over I2C.

If you read the TWI part of ATmega8′s datasheet you will begin to get an idea of how easy it is in AVRs to implement TWI/ I2C communication. A few main registers related to TWI operation are

  1. TWBR : TWI Bit Rate register - TWBR selects the division factor for the bit rate generator. The bit rate generator is a frequency divider which generates the SCL clock frequency in the Master modes. More details in ATmega8′s datasheet
  2. TWDR : TWI Data Register - In Transmit mode, TWDR contains the next byte to be transmitted. In Receive mode, the TWDR contains the last byte received.
  3. TWCR : TWI Control Register - The TWCR is used to control the operation of the TWI. It is used to enable the TWI, to initiate a Master access by applying a START condition to the bus, to generate a Receiver acknowledge, to generate a stop condition, and to control halting of the bus while the data to be written to the bus are written to the TWDR. It also indicates a write collision if data is attempted written to TWDR while the register is inaccessible.
  4. TWSR : TWI Status Register - this register’s value indicates the current status of I2C bus, it is used to confirm whether Start condition was transmitted successfully or not, similarly the condition or status of other TWI Operations.

twi_init()

void twi_init(void)
 {
       TWBR = 80;
       TWSR& = (~(1<<TWPS1))|(~(1<<TWPS0)); // Prescaler as 1

       /*

       F_SCK = F_CPU / (16 + 2*(TWBR)*POW(4,TWPS));

       */
 }

int twi_send (unsigned char addr, unsigned char value) When Master transmitter

 int twi_send(unsigned char addr, unsigned char value)
 {
       //First send start condition over bus
       TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);

       //Wait for it to get done
       while(!(TWCR & (1<<TWINT)));

       //Check if Start was transmitted or not
       if((TWSR & 0xF8) != 0x08)
       return FALSE;

       //Start transmitted now transmit SLA+W
       TWDR = addr; // 1100 000 0 = 0xc0 for MCP4725

       //Clear TWINT flag to start transmission
       TWCR = (1<<TWINT) | (1<<TWEN);

       //Wait for it to get done
       while(!(TWCR & (1<<TWINT)));

       //Check if transmitted successfully
       if((TWSR & 0xF8)!= 0x18)
       return FALSE;

       //load first data byte into TWDR
       TWDR = 0x60;

       //Clear TWINT flag to start transmission
       TWCR = (1<<TWINT) | (1<<TWEN);

       //Wait for it to get done
       while(!(TWCR & (1<<TWINT)));

       //Check if transmitted successfully
       if((TWSR & 0xF8)!= 0x28)
       return FALSE;

       //load first data byte into TWDR
       TWDR =value;

       //Clear TWINT flag to start transmission
       TWCR = (1<<TWINT) | (1<<TWEN);

       //Wait for it to get done
       while(!(TWCR & (1<<TWINT)));

       //Check if transmitted successfully
       if((TWSR & 0xF8)!= 0x28)
       return FALSE;

       //load first data byte into TWDR
       TWDR = 0xF0;

       //Clear TWINT flag to start transmission
       TWCR = (1<<TWINT) | (1<<TWEN);

       //Wait for it to get done
       while(!(TWCR & (1<<TWINT)));

       //Check if transmitted successfully
       if((TWSR & 0xF8)!= 0x28)
       return FALSE;

       //Now transmit STOP condition

       TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);

       return TRUE;

 }

We invite you to suggest any modification in the above piece of code. Can write your suggestions to devesh[at]electroons[dot]com.

Download

Download the C code for MCP4725 interfacing with avrPrayog (ATmega8 at 16 MHz). It is compiled using avr-gcc, should work with Arduino also, not as a library though.

Download the PDF of this article

  • How many samples that we can take for a temperature sensor using ADC? like our voice sampling rate could you please help me about this

  • vunhansu

    help me! value 255 = 5v => 8 bit, using 12 bit 4095 =5v ???