CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

code-error DAC MCP4922
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Foppie



Joined: 16 Sep 2005
Posts: 138
Location: The Netherlands

View user's profile Send private message Send e-mail Visit poster's website MSN Messenger

code-error DAC MCP4922
PostPosted: Mon Nov 14, 2005 1:55 am     Reply with quote

Hello,
In my project I need to control a DAC MCP4922 with a PIC16F877A. I wrote the code to do it but found the following problem: when I sent data to the DAC, the output is always on DAC1. Even if I want it to be on DAC0. The output has the right voltage.
I have narrowed it down to the following function, but I cannot see what is the problem.
Code:
#define DAC0      0           // VoutA
#define DAC1      1           // VoutB

void DAC_convert_long(short outputSelect, long data)
   {
      int upper, lower;

      if (outputSelect == DAC0)
      {
         upper = 0b01100000;
      }
      else
      {
         upper = 0b11100000;
      }
      upper = upper | ((int)(data >> 6));
      lower = (int)(data << 2);

      setup_spi(SPI_MASTER | SPI_L_TO_H | SPI_CLK_DIV_16);
      output_low(CS_DAC);
      delay_ms(1);
      spi_write(upper);
      spi_write(lower);
      output_high(CS_DAC);
      delay_ms(1);
      output_low(DAC_LDAC);
      delay_ms(1);
      output_high(DAC_LDAC);
   }
when I call this function, I do it like DAC_convert_long(DAC0, 700); or DAC_convert_long(DAC1, 350);
Any advice is appreciated.
Ttelmah
Guest







PostPosted: Mon Nov 14, 2005 6:04 am     Reply with quote

Try with SPI_H_TO_L.
If you look at the timing diagrams for a PIC SPI, the form where the data is sent while the clock is 'low', on the assumption that the chip at the other end reads it on the rising edge (which is what is illustrated for the MCP4922), has CKP=0, and CKE=1. The bit pattern to generate this on the SPI setup, is SPI_H_TO_L.
I suspect what is happening, is that the data is being output one clock late, so the chip always sees the '1', which is the second bit in the configuration data, as the first bit. It then select DOC1, and gets the gain set to '0', and loses the last bit of the data.

Best Wishes
Foppie



Joined: 16 Sep 2005
Posts: 138
Location: The Netherlands

View user's profile Send private message Send e-mail Visit poster's website MSN Messenger

PostPosted: Mon Nov 14, 2005 6:45 am     Reply with quote

I tried with SPI_H_TO_L but no succes. The DAC doesn't work at all if I use it, not even DAC1. Sad
Foppie



Joined: 16 Sep 2005
Posts: 138
Location: The Netherlands

View user's profile Send private message Send e-mail Visit poster's website MSN Messenger

PostPosted: Tue Nov 15, 2005 1:58 am     Reply with quote

I also wrote a code for the AD5312 chip in the same manner, and that is working perfectly. So now I completely don't understand it anymore...

here's the code for a AD5312:
Code:
#define DAC0      0           // VoutA
#define DAC1      1           // VoutB

void DAC_convert_long(short outputSelect, long data)
{
      int upper, lower;

      if (outputSelect == DAC0)
      {
         upper = 0b01000000;
      }
      else
      {
         upper = 0b11000000;
      }
      upper = upper | ((int)(data >> 6));
      lower = (int)(data << 2);

      setup_spi(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_16);

      delay_us(20);
      output_low(CS_DAC); //SYNC input signal
      delay_us(20);

      //write upper nibble
      spi_write(upper);

      //write lower nibble
      spi_write(lower);

      output_low(DAC_LDAC);
      output_high(CS_DAC);

      //put value on line out
      delay_us(20);
      output_high(DAC_LDAC);
}
Ttelmah
Guest







PostPosted: Tue Nov 15, 2005 3:33 am     Reply with quote

Yes. The code looked fine (I had checked that the .lst generated put the right values in). I'd check what value is actually being put into the SSP config registers, and go and look at the two data sheets involved and see if there is something 'screwy'. Also perhaps check with a scope which way the data line idles (it should be idling low). It is some sort of 'silly' signalling fault I'm afraid....

Best Wishes
Foppie



Joined: 16 Sep 2005
Posts: 138
Location: The Netherlands

View user's profile Send private message Send e-mail Visit poster's website MSN Messenger

PostPosted: Wed Nov 16, 2005 5:01 am     Reply with quote

I changed
Code:
setup_spi(SPI_MASTER | SPI_L_TO_H | SPI_CLK_DIV_16);
into
Code:
setup_spi(SPI_MASTER | SPI_CLK_DIV_16 | SPI_L_TO_H | SPI_SAMPLE_AT_END);
and now it works.
I didn't think it would be in my setup_spi because the DAC1 port was working correctly.

Many thanks Ttelmah
Ttelmah
Guest







PostPosted: Wed Nov 16, 2005 6:17 am     Reply with quote

Now I'll have to go an look at what effect 'sample at end', might have on data output!. I must admit, I wish that CCS, did their own nice table, showing which edge data would be sent on, sampled on etc., for their options. It should be obvious from the CCS data sheet, and the values, but it is hard work sometimes, to track through which bit a particular CCS function changes, and what the effect then is.

Now it gets odd. Sample at end, should only set bit 7 of the SSPSTAT register, which should not have any effect on data transmitted...

Aaargh!....

Checked the errata sheets for all versions of the 16F877A, and there is nothing here. I _hate_ this type of fault!...

Glad it now works anyway, I just wish I could see 'why'.

Best Wishes
Foppie



Joined: 16 Sep 2005
Posts: 138
Location: The Netherlands

View user's profile Send private message Send e-mail Visit poster's website MSN Messenger

PostPosted: Wed Nov 16, 2005 7:00 am     Reply with quote

and now I feel really stupid Embarassed
It seemed to work, but it only works once. The first value sent to the DAC is being put on the VoutA port, the rest of the values is on port VoutB. (I need to reset the PIC in order to get another value in VoutA)
The code that is sending looks as follows:
Code:
while(1)
{
   DAC_convert_long(DAC0, ADC_read_long(ADC0));
   delay_ms(100);
}

I know for sure the right value is on the ADC0 input pin. That is something that does work!

I cannot seem to write any other value to VoutA after the first value is sent... Please help.
Ttelmah
Guest







PostPosted: Wed Nov 16, 2005 10:03 am     Reply with quote

Lets try something really 'radical'.
First, remove the SPI configuration from the subroutine. Configure it once when the chip wakes up.
Then, assuming the fault remains, try:
Code:

#byte   SSPBUF = 0x13
#byte   SSPCON = 0x14
#byte   I2CBUF = 0x93
#byte   SSPSTAT = 0x94
#DEFINE  READ_SSP()   (SSPBUF)
#DEFINE   WAIT_FOR_SSP()   while((SSPSTAT & 1)==0)
#DEFINE   WRITE_SSP(chr)   SSPBUF=(chr)
#DEFINE   CLEAR_WCOL()   SSPCON=SSPCON & 0x3F

#define DAC0      0           // VoutA
#define DAC1      1           // VoutB

void DAC_convert_long(short outputSelect, long data) {
      int upper, lower;
      if (outputSelect == DAC0)
      {
         upper = 0b01100000;
      }
      else
      {
         upper = 0b11100000;
      }
      upper = upper | ((int)(data >> 6));
      lower = (int)(data << 2);

      output_low(CS_DAC);
      //Note 1mSec, is a _long_ time - the chip needs 40nSec...
      delay_cycles(1);
      WRITE_SSP(upper);
      WAIT_FOR_SSP();
      WRITE_SSP(lower);
      WAIT_FOR_SSP();
      output_high(CS_DAC);
      //Same comment applies
      delay_cycles(1);
      output_low(DAC_LDAC);
      //Requires 400nSec for this signal only
      delay_us(1);
      output_high(DAC_LDAC);
}

Before using this, make sure you clear TRISC, 5 and 3 in the main.
If it still fails, then get rid of the setup_spi function, and instead write the setup values directly to the configuration registers.
At some point, hopefully it'll start working, and only one tiny fix will be needed...

Best Wishes
Foppie



Joined: 16 Sep 2005
Posts: 138
Location: The Netherlands

View user's profile Send private message Send e-mail Visit poster's website MSN Messenger

PostPosted: Thu Nov 17, 2005 3:44 am     Reply with quote

Ttelmah wrote:
First, remove the SPI configuration from the subroutine. Configure it once when the chip wakes up.
I can't do this because I have another chip on the SPI connected, which requires another setup_spi. It's a max3100, not connected to a max232 chip, that can connect to a PC. But it is not connected. I'm pretty sure that is not a problem, because the only thing I do with the chip (on the moment) is configuring it, way before I do anything with the DAC.

That is why setup_spi is not on PIC wake up.

Ttelmah wrote:
Lets try something really 'radical'.
I'm starting with it now. I'll post as soon as I now more from testing. Thanks for your help so far!
Ttelmah
Guest







PostPosted: Thu Nov 17, 2005 5:14 am     Reply with quote

There is a potential problem present here. If you check the data sheets,the SPI clock line, needs to be low for a certain number of mSec, before the CS operates. If the other chip does not use the same default clock polarity, then it'd cause a problem selecting the DAC. Fortunately, the MAX31xx, does use the same polarity, so this should not be a problem.
You will have 'fun' with the Maxim chip though. The data sheets for this are wrong (the example C code given, does not actually work for data transmission, unless some incoming data arrives - I have a fixed set of code for the 31xx, which works).
Interestingly, I had almost exactly the same problems getting the code for the Maxim to work, as you are seeing. It was the register configuration, that 'fixed' it.
Code:

#byte   SSPCON = 0xFC6
#byte   SSPSTAT = 0xFC7
#define SSPC_INIT 0x00
#bit  SSPEN = SSPCON.5
#define SSPS_INIT 0x40

   //setup_spi(SPI_MASTER|SPI_XMIT_L_TO_H|SPI_CLK_DIV_4);
   SSPCON=SSPC_INIT;
   SSPSTAT=SSPS_INIT;
   SSPEN=1;

I switched from using the 'setup_spi' line given, to using the direct I/O shown above (also setting TRIS, not shown). The key difference, seems to be to not turn the SPI on, till after the setup values are written. The values sould function the same, but for me, the direct code worked, while the sandard setup didn't....
I'd suggest still getting rid of the setup_spi lines, and just toggling any bits that need to change to access the other chip.

Best Wishes
Foppie



Joined: 16 Sep 2005
Posts: 138
Location: The Netherlands

View user's profile Send private message Send e-mail Visit poster's website MSN Messenger

PostPosted: Thu Nov 17, 2005 7:13 am     Reply with quote

Till now, your code gives the same result as mine, but I still have to replace the setup_spi() function...

Strange to hear that. i had totally no problem to program the MAX3100...
The code I use looks as follows:
Code:
void RS232_transmit(int data)
{
   //define configuration byte
   #define txUpper 0b10000010

   //setup SPI
   setup_spi(SPI_MASTER | SPI_CLK_DIV_16 | SPI_L_TO_H | SPI_SAMPLE_AT_END | SPI_XMIT_L_TO_H);

   //send configuration byte and data
   output_low(CS_RS232);
   spi_write(txUpper);
   spi_write(data);
   output_high(CS_RS232);

   //delay before sending next character
   delay_us(981);
}

char RS232_receive()
{
   //variable declaration
   char data;

   //setup SPI
   setup_spi(SPI_MASTER | SPI_CLK_DIV_16 | SPI_L_TO_H | SPI_SAMPLE_AT_END | SPI_XMIT_L_TO_H);

   //send 0x0000 and receive data
   output_low(CS_RS232);
   spi_write(0x00);
   data = spi_read(0x00);
   output_high(CS_RS232);

   //return result
   return data;
}

void RS232_config()
{
   //define configuration bytes
   #define configUpper 0b11000100
   #define configLower 0b00001011

   //setup SPI
   setup_spi(SPI_MASTER | SPI_CLK_DIV_16 | SPI_L_TO_H | SPI_SAMPLE_AT_END | SPI_XMIT_L_TO_H);

   //send configuration
   output_low(CS_RS232);
   spi_write(configUpper);
   spi_write(configLower);
   output_high(CS_RS232);
}

I tested it extinsively, and it works good at 9600 baud.
Ttelmah
Guest







PostPosted: Thu Nov 17, 2005 7:47 am     Reply with quote

You seem to be polling the chip. I was using it interrupt driven, and what happens, is that when you send a character, it does not generate an interrupt, when the transmit buffer empties in certain circumstances. Their own 'example' code for it in interrupt driven mode, only works reliably, if some receive characters arrive, which then trigger an interrupt, and the waiting transmit characters get sent. Provided you have got incoming data, it will work, but if you want to send characters, with nothing arriving, you have to force an interrupt event to occur...

Best Wishes
Prakash



Joined: 17 Sep 2010
Posts: 2
Location: Bangalore

View user's profile Send private message Visit poster's website

PostPosted: Fri Sep 17, 2010 4:36 am     Reply with quote

Foppie wrote:
I also wrote a code for the AD5312 chip in the same manner, and that is working perfectly. So now I completely don't understand it anymore...

here's the code for a AD5312:
Code:
#define DAC0      0           // VoutA
#define DAC1      1           // VoutB

void DAC_convert_long(short outputSelect, long data)
{
      int upper, lower;

      if (outputSelect == DAC0)
      {
         upper = 0b01000000;
      }
      else
      {
         upper = 0b11000000;
      }
      upper = upper | ((int)(data >> 6));
      lower = (int)(data << 2);

      setup_spi(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_16);

      delay_us(20);
      output_low(CS_DAC); //SYNC input signal
      delay_us(20);

      //write upper nibble
      spi_write(upper);

      //write lower nibble
      spi_write(lower);

      output_low(DAC_LDAC);
      output_high(CS_DAC);

      //put value on line out
      delay_us(20);
      output_high(DAC_LDAC);
}


I have ported this code with LPC2148 and its working fine from 0 to 3.3v:)

But I am using Vref as 5V.

For data 100, Vout I am getting is 0.3V and for 1023 Vout is 3.2V. But actually Vout should be 5V for 1023 data.

Kindly let me know what could be the possible issue.
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Fri Sep 17, 2010 7:05 am     Reply with quote

Quote:
But I am using Vref as 5V.
What is your Vdd voltage for the MCP4922?
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group