Microcontrollers Projects

Connect PIC16F877A to DAC chip MCP4921

Digital and analog are an integral part of electronics. Most devices have both ADC and DAC and are used whenever a signal needs to be converted from analog to digital or digital to analog. Moreover, real-world signals such as sound and light are also analog in nature, so whenever these real-world signals have to be used, the digital signal has to be converted to analog, such as producing sound using a speaker or controlling a light source.

Another type of DAC is a pulse width modulator (PWM). A PWM takes in a digital word and generates a digital pulse with a variable pulse width. When this signal is passed through a filter, the result will be purely analog. The signal in an analog signal can have many types of data.

In this article, we will connect Microchip’s PIC16F877 microcontroller to ADAC MCP4921 to achieve digital-to-analog conversion. In this article, we will convert digital signals to analog signals and display the input digital value and output analog value on a 16×2 LCD. It will provide 1V, 2V, 3V, 4V, and 5V as the final analog output.

DACs can be used in many applications such as motor control, controlling brightness of LED lights, frequency amplifiers, video encoders, data acquisition systems, etc.

MCP4921 DAC (Digital-to-Analog Converter)

The MCP4921 is a 12-bit DAC, so the MCP4921 will provide 12-bit output resolution. DAC resolution means the number of digital bits that can be converted into an analog signal. We can get the value from the formula. For 12 bits, it is equal to 4096. This means that a DAC with a 12-bit resolution can produce 4096 different outputs.

By using this value, a single analog step voltage can be easily calculated. In order to calculate the step size, a reference voltage is needed. Since the logic voltage of this device is 5V, the step voltage is 5/4095 (because the starting point of the digital is not 1, it is 0, so it is 4096-1), which is 0.00122100122 millivolts. Therefore, changing 1 bit will change the analog output by 0.00122100122.

So that’s it for the conversion part. The MCP4921 is an 8-pin IC. The pinout diagram and description can be found below.

Connect PIC16F877A to DAC chip MCP4921

The MCP4921 IC communicates with the microcontroller through SPI communication. For SPI communication, the device must be a master, which submits data or commands to the external device connected as a slave. In a SPI communication system, multiple slave devices can be connected with a single master.

To submit data and commands, it is important to understand the command register.

The following figure shows the command register,

The command register is a 16-bit register. Bits 15 to 12 are used for configuration commands. The figure above clearly shows the data input and configuration. The data determined by bits D11 to D0 of the register together is 0011. It is necessary to submit 16-bit data 0011 xxxx xxxx xxxx, where the first 4 bits of the MSB are configuration and the rest are LSB. It will be clearer by looking at the write command timing diagram.

Connect PIC16F877A to DAC chip MCP4921

According to the timing diagram and datasheet, the CS pin is low during the entire command write to the MCP4921. Now it is time to connect the device with hardware and write the code.

Required Components

● MCP4921

● PIC16F877A microcontroller

● 20 MHz crystal

● Display 16×2 character LCD.

● Multimeter

● Breadboard

● 5V power supply

Connection Schematic

Given below is the circuit diagram for interfacing DAC4921 with PIC microcontroller:

Connect PIC16F877A to DAC chip MCP4921

The circuit is made in a breadboard.

Code Description

The complete code for converting digital signal to analog signal using PIC16F877A is provided at the end of this article. As always, we first need to set the configuration bits in the PIC microcontroller.

  1. // PIC16F877A Configuration Bit Settings
  2. // ‘C’ source line config statements
  3. //CONFIG
  4. #pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
  5. #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
  6. #pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
  7. #pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled)
  8. #pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3/PGM pin has PGM function; low-voltage programming enabled)
  9. #pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
  10. #pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
  11. #pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)

Copy code

The following lines of code are used to include the LCD and SPI header files and also declare the XTAL frequency and CS pin connections for the DAC.

  1. #include <xc.h>
  2. #include <stdint.h>
  3. #include “supporting_cfile\lcd.h”
  4. #include “supporting_cfile\PIC16F877a_SPI.h”
  5. /*
  6. Hardware related definition
  7. */
  8. #define _XTAL_FREQ 200000000 //Crystal Frequency, used in delay
  9. #define DAC_CS PORTCbits.RC0 //Declaring DAC CS pin

Copy code

SPI_Initialize_Master() is slightly modified according to the other configurations required for this article . The SSPSTAT register is configured to sample the input data at the end of the data output time and the SPI clock is configured to transition from the active clock state mode to the idle clock state mode for transmission. Everything else is the same.

  1. void SPI_Initialize_Master()
  2. {
  3.                 TRISC5 = 0; // Set as output
  4.                 SSPSTAT = 0b11000000; //pg 74/234
  5.                 SSPCON = 0b00100000; //pg 75/234
  6.                 TRISC3 = 0; //Set as output for slave mode
  7. }

Copy code

Likewise, some modifications have been made to the SPI_Write() function. The data transfer will take place after clearing the buffer to ensure flawless data transfer over SPI.

  1. void SPI_Write(char incoming)
  2. {
  3.                 SSPBUF = incoming; //Write the user given data into buffer
  4.                 while (!SSPSTATbits.BF);
  5. }

Copy code

The important part of this program is the MCP4921 driver. It is a bit difficult because it combines the commands and digital data together to provide a full 16-bit data over the SPI. However, the logic is clearly shown in the code comments.

  1. /*
  2. This Function is for converting the digital value to the analog.
  3. */
  4. void convert_DAC(unsigned int value)
  5. {
  6.    /*Step Size = 2^n, Therefore 12bit 2^12 = 4096
  7.      For 5V reference, the step will be 5/4095 = 0.0012210012210012V or 1mV (approx)*/
  8.   unsigned int container ;
  9.   unsigned int MSB;
  10.   unsigned int LSB;
  11.   /*Step: 1, store the 12 bit data into the container
  12.    Suppose the data is 4095, in binary 1111 1111 1111*/
  13.   container = value;   
  14.   /*Step: 2 Creating Dummy 8 bit. So, by dividing 256, upper 4 bits are captured in LSB
  15.    LSB = 0000 1111*/
  16.   LSB = container/256;
  17.   /*Step: 3 Sending the configuration with punching the 4 bit data.
  18.    LSB = 0011 0000 OR 0000 1111. Result is 0011 1111 */
  19.   LSB = (0x30) | LSB;
  20.   /*Step:4 Container still has the 21bit value. Extracting the lower 8 bits.
  21.    1111 1111 AND 1111 1111 1111. Result is 1111 1111 which is MSB*/  
  22.   MSB = 0xFF & container;   
  23. /*Step:4 Sending the 16bits data by dividing into two bytes. */
  24.     DAC_CS = 0; // CS is low during data transmission. As per the data-sheet it is required         
  25.     SPI_Write(LSB);
  26.     SPI_Write(MSB);   
  27.     DAC_CS = 1;              
  28. }

Copy code

In the main function, a “for loop” is used to create digital data for 1V, 2V, 3V, 4V, and 5V outputs. The digital value will be calculated based on the output voltage / 0.0012210012210012 millivolts.

  1. void main() {
  2.     system_init();
  3.     introduction_screen();
  4.     int number=0;
  5.     int volt=0;
  6.     while (1) {
  7.         for (volt=1; volt<=MAX_VOLT; volt++){
  8.             number = volt / 0.0012210012210012;
  9.             clear_screen();           
  10.             lcd_com(FIRST_LINE);            
  11.             lcd_puts(“DATA Sent:- “);
  12.             lcd_print_number(number);
  13.             lcd_com(SECOND_LINE);            
  14.             lcd_puts(“Output:- “);            
  15.             lcd_print_number(volt);
  16.             lcd_puts(“V”);
  17.             convert_DAC(number);
  18.             __delay_ms(300);                                    
  19.         }
  20.     }
  21. }

Copy code

Testing the PIC’s digital-to-analog conversion

Use a multimeter to test the built circuit. In the following figure, the output voltage and digital data are displayed on the LCD. The multimeter shows a close reading.

Code

Here is the complete code used in this article:  main

Back to top button
error: Content is protected !!