Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[PIC] How to interface Dac ic mcp4921 with pic16f877a microcontroller

Status
Not open for further replies.

SivaHari

Newbie level 3
Joined
May 9, 2016
Messages
4
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
44
Hai,
I recently interfaced the DAC mcp 4921 with pic16f877a microcontroller using SPI. THE Process is working fine, when i given the input
directly to DAC (ie : value as 600 without using forloop). but if i given the input using for loop and adding each time value 100 using macros the output suddenly increasing...

I found little bit of error from that... during loop running time the clock generating normally eight to nine clock and then nine to ten clock. due to this problem the input latching incorrectly in DAC register. here i attach my program, kindly someone replay me...
Thank you..
Code:
#include <stdio.h>
#include <stdlib.h>
#include <htc.h>

__CONFIG(FOSC_HS & WDTE_OFF & PWRTE_OFF & BOREN_ON & LVP_OFF & CPD_OFF & WRT_OFF & CP_OFF);
#define _XTAL_FREQ  20000000
#define CS RD7
#define LDAC RD3
#define TEN_VOLT_VALUE 100.00
void SPI_init();
void SPI_single_data_send(unsigned char);
void delay(unsigned int);
void Start_RPM(unsigned int rpm);
void DAC_RST();
unsigned int TEMP,j,b;
unsigned int value = 2500;
char higher_byte,lower_byte;
char DAC_buff[2];
//const int TEN_VOLT_VALUE = 25;
int main()
{
TRISD = 0x00;
TRISC = 0x00;
CS = 1;
SPI_init();
//CS = 1;
delay(100);
//Start_RPM(100);
while(1)
{
    Start_RPM(600);
 //   Start_RPM();
    //for(VALUE=0;VALUE<4095;VALUE+=100)
    //{
    //TEMP = VALUE/1.098;
    //TEMP = (TEMP >> 8);
/*  TEMP = value >> 8;
    higher_byte |= TEMP;
    higher_byte &= 0x0F;
    higher_byte |= 0x30;
    lower_byte = ((value)&0xff);
    DAC_buff[0] = higher_byte;
    DAC_buff[1] = lower_byte;
   // LDAC = 1;
    delay(50);
    CS = 0;
    delay(25);
    for(j=0;j<2;j++)
    {
        SPI_single_data_send(DAC_buff[j]);
    }
    delay(50);
    CS = 1;
    delay(50);
   // LDAC = 0;delay(100);
   // LDAC = 1;
    delay(65000);

//}*/
 //   NOP();
    ;
}
}

void SPI_init()
{
    SSPEN = 0;
    SMP = 0;
    CKP = 0;
    CKE = 0;
    SSPM0 = 0;
    SSPM1 = 0;
    SSPM2 = 0;
    SSPM3 = 0;
    SSPEN = 1;
}

void SPI_single_data_send(unsigned char x)
{
    SSPBUF = x;
    while(!SSPIF);
    SSPIF = 0;
}

void delay(unsigned int z)
{
    unsigned int i;
    for(i=0;i<=z;i++)
    {
        NOP();
    }
}

void Start_RPM(unsigned int rpm)
{
    unsigned int Dac_var,num = 0;
    int five_volt,ten_volt=0;
    float DAC_volt = 0;
   // five_volt = (rpm % 10);
    ten_volt = (rpm / 100);
    DAC_volt = 0;
    higher_byte = 0;
    lower_byte = 0;
  //  DAC_volt = ten_volt;
    for(Dac_var = 1;Dac_var <= ten_volt; Dac_var++)
    {
        DAC_volt += TEN_VOLT_VALUE;
        num = (int)DAC_volt;
       //   num = rpm;
        if(num >3688)
        {
            num = 3688;
        }
        TEMP = (num >> 8);
    higher_byte |= TEMP;
    higher_byte &= 0x0F;
    higher_byte |= 0x30;
    lower_byte = ((num >> 0)&0xff);
    DAC_buff[0] = higher_byte;
    DAC_buff[1] = lower_byte;
    LDAC = 1;
    delay(50);
    CS = 0;
   // delay(50);  //delay(300);
    for(j=0;j<2;j++)
    {
        SPI_single_data_send(DAC_buff[j]);
    }
    delay(50);  //delay(100);
    CS = 1;
    delay(50);
    LDAC = 0;
    delay(100);
    LDAC = 1;
    delay(65000);
    delay(65000);
    delay(65000);
    delay(65000);
    delay(65000);
//    delay(65000);
//    DAC_RST();
   }

}
 
Last edited by a moderator:

Don't use delays to know when the SPI exchange has completed to manipulate the chip select line. The MSSP peripheral will set the BF bit flag when the exchange has completed and you can sample this to know exactly when the exchange has completed.
I have no idea what the function calls do (whether they block until completion, read the received value to clear the BF bit or what). The MSSP peripheral is really very straightforward to configure and use that I would not recommend using function calls to use it. As in this case, all they do is hide what is going on.
However you should be able to check when the MSSP peripheral has completed the last exchange and so clear the chip select line then.
Susan
 
Hi,

To ease the code you could LDAC continously tie to LOW. You don't have to toggle it.

Do you have a scope to show cs, clk mosi?

Klaus
 

Hi,
I already used this method, but according to the DAC 2941 datasheet
They mentioned to make toggle LDAC that after the CS rising edge. but it is used to synchronize the DAC A-channel and B-channel. IN this DAC 2941 IC only A-channel, then why they given this LDAC pin that still i don't know.
SivaHari
 

Section 3.5 of the data sheet does say (as KlausST pointed out) that the \LDAC\ pin: "Can also be tied low if transfer on the rising edge of CS is desired."
The way Microchip often use the \CS\ line is the falling edge is used to resync the SDI exchange (so that any spurious transition seen before are ignored) and the rising edge to indicate the exchange is complete. In this case as you are only using one channel then it will not matter which approach you take.
Susan
 
I want to say thanks to MR.Susan and MR.Klaus for given little bit of ideas and i found my major bug in my code that is i made a mistake in bit wise operation after the if condition. In my previous code i made OR operation to store first higher bits. Here the previous value and current value are mixing using OR operation. so i removed and i replaced to assignment operator.

This is my working code..,
Code:
#include <stdio.h>
#include <stdlib.h>
#include <htc.h>

__CONFIG(FOSC_HS & WDTE_OFF & PWRTE_OFF & BOREN_ON & LVP_OFF & CPD_OFF & WRT_OFF & CP_OFF);
#define _XTAL_FREQ  20000000
#define CS RD7
#define LDAC RD3
#define TEN_VOLT_VALUE 25
void SPI_init();
void SPI_single_data_send(unsigned char);
void delay(unsigned int);
void Start_RPM(unsigned int rpm);
void DAC_RST();
unsigned int j,b;
unsigned char higher_byte,lower_byte, TEMP;
char DAC_buff[2];
int main()
{
TRISD = 0x00;
TRISC = 0x00;
CS = 1;
SPI_init();
delay(100);
Start_RPM(1400);
while(1)
{
    ;
}
}

void SPI_init()
{
    SSPEN = 0;
    SMP = 0;
    CKP = 1;
    CKE = 1;
    SSPM0 = 0;
    SSPM1 = 0;
    SSPM2 = 0;
    SSPM3 = 0;
    SSPEN = 1;
}

void SPI_single_data_send(unsigned char x)
{
    SSPBUF = x;
    while(!SSPIF);
    SSPIF = 0;
}

void delay(unsigned int z)
{
    unsigned int i;
    for(i=0;i<=z;i++);
}

void Start_RPM(unsigned int rpm)
{
    unsigned int Dac_var,num = 0;
    unsigned int five_volt,ten_volt=0;
    unsigned int DAC_volt = 0;
   // five_volt = (rpm % 10);
    ten_volt = (rpm / 10);
    DAC_volt = 0;
    higher_byte = 0;
    lower_byte = 0;
    DAC_volt = ten_volt;
    for(Dac_var = 1;Dac_var <= ten_volt; Dac_var++)
    {
   
        DAC_volt += TEN_VOLT_VALUE;
        num = DAC_volt;
       
        if(num >3688)
        {
            num = 3688;
        }
        TEMP = (num >> 8);
    higher_byte  = TEMP;
    higher_byte &= 0x0F;
    higher_byte |= 0x30;
    lower_byte = (num & 0xFF);
    DAC_buff[0] = higher_byte;
    DAC_buff[1] = lower_byte;
    LDAC = 1;
    delay(50);
    CS = 0;
    delay(100);  //delay(300);
    for(j=0;j<2;j++)
    {
        SPI_single_data_send(DAC_buff[j]);
    }
    delay(100);  //delay(100);
    CS = 1;
    delay(50);
    LDAC = 0;
    delay(100);
    LDAC = 1;
    delay(65000);
    delay(65000);
   }

}
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top