How to use DAC Module of Pic Microcontroller and Generate waveforms

In this tutorial, we will see how to use the DAC module of a PIC microcontroller.  Digital to Analog converter is an electronics circuit that converts digital values into analog values. In other words, it converts digital voltage levels into an analog voltage levels. Furthermore, we can use DAC modules to generate different types of electrical waveforms such as sawtooth, triangular,  sine wave, etc.  Its working principle is the exact opposite of an analog to digital converter module.

If you want to recall ADC concepts and How to use Analog to digital converter module of pic microcontroller,  go through these tutorials:

PIC Microcontroller Built-in DAC Modules

Almost all Pic microcontroller that belongs to advance series of PIC16 and PIC18 has built-in DAC modules inside a chip. Therefore, we don’t need to use any external electronics circuits with a pic microcontroller. We can easily configure internal digital to analog converter module for generating analog signals. By using registers, a module can be easily configured. We will see examples in the latter part of this tutorial.

However, if built-in DAC does not support the specific requirement for your embedded design, we can look for off the chip external DAC ICs such as DAC0832. But in this tutorial, we will see how to use internal DAC modules of Microchip devices.

DAC Output Selection

In this tutorial, we will use the PIC18F46K22 microcontroller. It has a built-in 5-bit DAC module.  Some PIC chips also have 8-bit DAC modules. Like ADC, we also define its resolution with the help of a number of bits. A number of bits defines the number of steps or Resolution.  Therefore, a 5-bit converter generates 32 levels. Few pic microcontrollers also have both 5-bit and 8-bit DACs inside a single MCU.

DAC Module PIC18F46K22

PIC18F46K22 has one 5-bit module. This 5-bit module can provide 32 levels of the output voltage. We can select levels using control registers. We will see later on how to select levels. This picture shows a block diagram of a pic microcontroller. As you can see, it consists of resistor ladder types digital to analog converter. We can control the output voltage of the ladder resistive network with DACR [0:3] bits.

Digital to Analog converter Module Block Diagram

We can use it for the following applications:

  • To Generate Variable reference voltage for ADC
  • DACOUT Feature with RA2 pin of PIC18F46K22
  • Input to the comparator pin

PIC DAC Module Control Registers

It mainly consists of two control registers such as VREFCON1 and VREFCON2. But these are 8-bit registers.

DAC VREFCON1: VOLTAGE REFERENCE CONTROL REGISTER 0

DAC VREFCON1 Register Pic microcontroller

This register used to enable the DAC module, enable DACOUT (RA2) pin and a reference voltage. It is an 8-bit register and out of which 4 and 1 are unused.

  • DACEN: This is a DAC module enable bit. You should set this bit to active high. This line will enable the DAC module.
VREFCON1bits.DACEN=1
  • DACLPS: This bit is used for positive voltage reference selection. It selects either DAC reference voltage is a positive or negative voltage. We usually use positive reference voltage.
VREFCON1bits.DACLPS=1 // Setting to active selects positive reference voltage
VREFCON1bits.DACLAP=0 //clearing this selects negative reference voltage
  • DACOE: It enables and disables the DAC output voltage. We can get DAC output voltage from the RA2 pin of PIC18F46K22 microcontroller. If you want output only for ADC or comparator input voltage, we can disable this feature.
VREFCON1bits.DACOE=1;
  • DACPSS

With the help of these two bits, we select a positive voltage source for DAC from these three options:

DACPSSPositive voltage source
00Vdd
01VREF+
10FVR BUF1 output
  • DACNSS

Like DAVPSS, DACNSS selects negative voltage reference from these two options:

DACNSSNegative voltage source
1Vref
0VSS

DAC VREFCON2: VOLTAGE REFERENCE CONTROL REGISTER 2

  • Bit5-7 are unused
  • DACR [4:0] bits

These bits select the level of output voltage from the DAC. This module generates output voltage according to this formula.

VOUT = ((VSRC+) - (VSRC-)) * (DACR [4:0]/(2^5)) + VSRC

The value of DAC will be in the range of 0-31 due to 5 bits resolution.

Now we will see three example and their codes to generate different waveforms with DAC module of PIC18F46K22 microcontroller.

  1. Sawtooth Wave Generator
  2. Triangular wave Generator
  3. Sine Wave Generator

Use Pic Microcontroller DAC to Generate Triangular Wave Form

In this section, we will see a code to generate a triangular waveform using the DAC module of PIC18F46K22 microcontroller. We can use a simple oscilloscope to see the waveform. RA2 pin which is PORTA pin2 provides DAC OUT signal. This circuit diagram shows the connection of RA2 with an oscilloscope.

Sawtooth is a ramp-up voltage that increases from a minimum value to the maximum value linearly. After reaching a maximum value, it suddenly falls to zero voltage. The operating voltage of the PIC18F46K22 microcontroller is 5 volts. Therefore, the ramp-up voltage goes from 0 to 5 volts.

PIC18F46K22 Microcontroller Circuit

PIC Microcontroller DAC Module Programming

We used MPLAB XC8 Compiler to write a program for this tutorial. You may refer to getting started with MPLAB XC8 Compiler tutorial.

This code generates a sawtooth signal at the output pin.

#include "Config_PIC18F46K22.h"
void internal_16(){
//Clock determined by FOSC in configuration bits
SCS0 = 0;
SCS1 = 0;

//Frequency select bits
IRCF0 = 1;
IRCF1 = 1;
IRCF2 = 1;
//IRCF3 = 1;

//SET PLLx4 OFF
//SPLLEN = 0;
}
void initMain(){
// Run at 16 MHz
internal_16();

// Set PIN D1 as output
TRISAbits.TRISA1 = 0;
TRISAbits.TRISA2 = 0;

// Turn off LED
LATAbits.LATA2 = 0;
LATAbits.LATA1 = 0;

//////////////////////
// Configure DAC
/////////////////////

//VREFCON0bits.FVRS=0b11;

// DAC enabled
DACEN = 1;

// DACOUT pin enabled
DACOE = 1;

// +ve source is Vdd
VREFCON1bits.DACPSS = 0b00;

// -ve source is Vss
DACNSS = 0;
DACLPS = 1;

// Initial output is 0v
VREFCON2bits.DACR=0b0000;
}
void main(void) {
initMain();
int i=0;
while(1)
{
VREFCON2bits.DACR=i;  // increasing i value linearly to get linear output voltage
i++;
__delay_us(310);
if(i>=31)
i=0;
}

return;

}

In this code, we define every DAC control register and its bits according to the information provided in registers sections.  For example, we want to generate a sawtooth waveform of frequency 10HZ. The time period of 10Hz will be T= 1/10 = 10ms.

In order to get a 10Hz time period, we need to know the sampling period. But if we know a number of bits of DAC, we can easily calculate the DAC sampling period.

Ts=10ms/25
Ts= 10ms/32=312.5µs = 310µs

Therefore, we used a delay of 310µs after every DAC output sample.

PIC DAC Simulation Result

PIC Microcontroller DAC to generate sawtooth waveform simulation result

Triangular Wave Generation using PIC DAC Module

In this section, we will see how to generate a triangular waveform with pic microcontroller DAC. A triangular wave consists of ramp-up and ramp-down voltage of equal lengths. For instance, we want to generate a triangular wave of 5Hz frequency.

This program will generate a 5Hz wave.

#include "Config_PIC18F46K22.h"
void internal_16(){
//Clock determined by FOSC in configuration bits
SCS0 = 0;
SCS1 = 0;

//Frequency select bits
IRCF0 = 1;
IRCF1 = 1;
IRCF2 = 1;
//IRCF3 = 1;

//SET PLLx4 OFF
//SPLLEN = 0;
}
void initMain(){
// Run at 16 MHz
internal_16();

// Set PIN D1 as output
TRISAbits.TRISA1 = 0;
TRISAbits.TRISA2 = 0;

// Turn off LED
LATAbits.LATA2 = 0;
LATAbits.LATA1 = 0;

//////////////////////
// Configure DAC
/////////////////////

//VREFCON0bits.FVRS=0b11;

// DAC enabled
DACEN = 1;

// DACOUT pin enabled
DACOE = 1;

// +ve source is Vdd
VREFCON1bits.DACPSS = 0b00;

// -ve source is Vss
DACNSS = 0;
DACLPS = 1;

// Initial output is 0v
//DACR = 0;
//VREFCON2bits.DACR=0b1111;
}
void main(void) {
initMain();
int i=0;
while(i<32)
{
VREFCON2bits.DACR=i;
i++;
}
int j=31;
while(j>-1)
{
VREFCON2bits.DACR=j;
j--;
}

return;

}

This code is exactly similar to the last code except for this part.

while(i<32)
{
VREFCON2bits.DACR=i;
i++;
}
int j=31;
while(j>-1)
{
VREFCON2bits.DACR=j;
j--;
}

First, while loop generates rump-up voltage output and second while loop generates a ramp-down voltage as shown in the figure below:

PIC Microcontroller DAC to generate triangular waveform simulation result

Sine wave generation using DAC Module

Like sawtooth and triangular waves, we can also generate a sine wave using built-in digital to analog converter module of PIC18F46K22 microcontroller.  To generate a sine wave, we need to create a sine table inside the code. We use a look-up table that stores values to create a sine wave. Although, you can calculate these values manually using a sine wave formula. But I have used this sine table calculator.

You can generate sine table values according to the size of your DAC module. PIC18F46K22 microcontroller has 5-bit DAC. Therefore, we will use 32 values.

{0,0,1,3,5,7,10,13, 16,19,22,25,27,28,30,31,31,31,30,28,27,25,22,19,16,13,10,7,5,3,1,0};

For example, we want to generate a 50Hz sine wave. We can calculate the sampling period similar to the last sections.

T=1/50=20ms
Ts=20ms/32 = 625 micro seconds

That means we will increment the DACOUT value after every 635 microseconds.

Sine wave with DAC Code

  • Now copy this copy and open MPLAB IDE.
  • Create a new project and select the XC8 compiler from available compilers in MPLAB IDE.
  • First set the configuration bits of PIC18F46K22 microcontroller and save these configuration settings inside a header folder name “Config_PIC18F46K22.h”. You can also simply put configuration files inside the main code. But to save space, I used a separate header file.
  • Now open main.c file and paste this code. After compiling the code and generate a hex file.
#include "Config_PIC18F46K22.h"
void internal_16(){
//Clock determined by FOSC in configuration bits
SCS0 = 0;
SCS1 = 0;

//Frequency select bits
IRCF0 = 1;
IRCF1 = 1;
IRCF2 = 1;
//IRCF3 = 1;

//SET PLLx4 OFF
//SPLLEN = 0;
}
int sinetable[32]=
{0,0,1,3,5,7,10,13, 16,19,22,25,27,28,30,31,31,31,30,28,27,25,22,19,16,13,10,7,5,3,1,0};
void initMain(){
// Run at 16 MHz
internal_16();

// Set PIN D1 as output
TRISAbits.TRISA1 = 0;
TRISAbits.TRISA2 = 0;

// Turn off LED
LATAbits.LATA2 = 0;
LATAbits.LATA1 = 0;

//////////////////////
// Configure DAC
/////////////////////

//VREFCON0bits.FVRS=0b11;

// DAC enabled
DACEN = 1;

// DACOUT pin enabled
DACOE = 1;

// +ve source is Vdd
VREFCON1bits.DACPSS = 0b00;

// -ve source is Vss
DACNSS = 0;
DACLPS = 1;

// Initial output is 0v
//DACR = 0;
//VREFCON2bits.DACR=0b1111;
}
void main(void) {
initMain();
int i=0;
while(1)
{
VREFCON2bits.DACR=sinetable[i];
i++;
__delay_us(620);
if(i == 33)
i=0;
}

return;
}

This code produces a sine wave as shown in this simulation result.

Sine wave generation using DAC module of pic microcontroller PIC18F46K22

In summary, in this tutorial, we have learned the use of DAC module of pic microcontroller with three examples and their programs.

3 thoughts on “How to use DAC Module of Pic Microcontroller and Generate waveforms”

  1. #include “mcc_generated_files/mcc.h”
    #define led1 LATAbits.LATA1
    #define led2 LATAbits.LATA2
    #define sawtooth VREFCON2bits.DACR
    void main(void)
    {
    SYSTEM_Initialize();
    TRISAbits.TRISA1= 0; TRISAbits.TRISA2 = 0;led1=1 ;led2=0;__delay_ms(1000);
    led1=1 ;led2=1;
    DACEN = 1;// DAC enabled
    DACOE = 1;// DACOUT pin enabled
    VREFCON1bits.DACPSS = 0b00; // +ve source is Vdd
    DACNSS = 0; // -ve source is Vss
    DACLPS = 1;
    VREFCON2bits.DACR=0b00000;// Initial output is 0v
    int i=0;

    while (1)
    {
    sawtooth=i; // increasing i value linearly to get linear output voltage
    i++;__delay_us(2010);
    if (i>=31) {i=0;}
    }
    }

    Reply
  2. —————————————————————
    // traingular wave form pic18F45K22 on 1 Mhz

    #include “mcc_generated_files/mcc.h”
    #define led1 LATAbits.LATA1
    #define led2 LATAbits.LATA2
    #define sawtooth VREFCON2bits.DACR
    void main(void)
    {
    SYSTEM_Initialize();
    TRISAbits.TRISA1= 0; TRISAbits.TRISA2 = 0;led1=1 ;led2=0;__delay_ms(1000);
    led1=1 ;led2=1;
    DACEN = 1;// DAC enabled
    DACOE = 1;// DACOUT pin enabled
    VREFCON1bits.DACPSS = 0b00; // +ve source is Vdd
    DACNSS = 0; // -ve source is Vss
    DACLPS = 1;
    VREFCON2bits.DACR=0b00000;// Initial output is 0v
    int sinetable[32]=
    {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0};
    int i = 0;

    while (1){
    sawtooth= sinetable[i],i++;__delay_us(1000);
    if(i==32){i=0;}
    }
    }

    —————————————————————
    // #include “mcc_generated_files/mcc.h”
    #define led1 LATAbits.LATA1
    #define led2 LATAbits.LATA2
    #define sawtooth VREFCON2bits.DACR
    void main(void)
    {
    SYSTEM_Initialize();
    TRISAbits.TRISA1= 0; TRISAbits.TRISA2 = 0;led1=1 ;led2=0;__delay_ms(1000);
    led1=1 ;led2=1;
    DACEN = 1;// DAC enabled
    DACOE = 1;// DACOUT pin enabled
    VREFCON1bits.DACPSS = 0b00; // +ve source is Vdd
    DACNSS = 0; // -ve source is Vss
    DACLPS = 1;
    VREFCON2bits.DACR=0b00000;// Initial output is 0v
    int sinetable[32]=
    {0,0,1,3,5,7,10,13, 16,19,22,25,27,28,30,31,31,31,30,
    28,27,25,22,19,16,13,10,7,5,3,1,0};
    int i = 0;

    while (1){

    sawtooth= sinetable[i],i++;__delay_us(1000);
    if(i==32){i=0;}

    }
    }

    —————————————————–
    // for traingular wave form pic18F45K22 on 1 Mhz

    #include “mcc_generated_files/mcc.h”
    #define led1 LATAbits.LATA1
    #define led2 LATAbits.LATA2
    #define sawtooth VREFCON2bits.DACR
    void main(void)
    {
    SYSTEM_Initialize();
    TRISAbits.TRISA1= 0; TRISAbits.TRISA2 = 0;led1=1 ;led2=0;__delay_ms(1000);
    led1=1 ;led2=1;
    DACEN = 1;// DAC enabled
    DACOE = 1;// DACOUT pin enabled
    VREFCON1bits.DACPSS = 0b00; // +ve source is Vdd
    DACNSS = 0; // -ve source is Vss
    DACLPS = 1;
    VREFCON2bits.DACR=0b00000;// Initial output is 0v
    int i=0;int j=31;

    while (1){int i = 0;
    while (i<32){sawtooth=i; i++;__delay_us(1000);}
    j=31;
    while (j=31) {i=0;}

    }
    }

    ——————————-

    Reply

Leave a Comment