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

SPI and DAC

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
rikotech8



Joined: 10 Dec 2011
Posts: 376
Location: Sofiq,Bulgariq

View user's profile Send private message

SPI and DAC
PostPosted: Wed Feb 29, 2012 1:39 pm     Reply with quote

The one chip is 18F2520. Another one is MCP4822 (12bit DAC). It is a simple code that should drive the DAC but something is wrong. Here is the code:
Code:

#include <18f2520.h>
#fuses nomclr
#use delay(internal = 8M)

void main()
{
setup_spi(SPI_MASTER|SPI_L_TO_H|SPI_CLK_DIV_64);
unsigned int16 res;
unsigned int8 msb,lsb; //most significant & low significant bytes.
res =4000;   //result
msb = make8(res,1);
lsb = make8(res,0);

while (1)
   {
    delay_us(50);
    output_low(pin_c4);  //connected to chip select pin (DAC)
    spi_write(msb);
    spi_write(lsb);
    delay_us(50);
    output_high(pin_c4);
   }
}

The pin - Latch DAC Input (LDAC) I have connected to GND.
I would like to know is there something obvious wrong in my code?
Excuse my bad english!
Thx in advance!
bkamen



Joined: 07 Jan 2004
Posts: 1611
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Wed Feb 29, 2012 5:29 pm     Reply with quote

You don't tell us what's wrong.
You don't tell us the compiler version.

What is the problem you are seeing?

-Ben
_________________
Dazed and confused? I don't think so. Just "plain lost" will do. :D
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Feb 29, 2012 6:24 pm     Reply with quote

Define statements for SPI modes:
Code:

#define SPI_MODE_0  (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1  (SPI_L_TO_H)
#define SPI_MODE_2  (SPI_H_TO_L)
#define SPI_MODE_3  (SPI_H_TO_L | SPI_XMIT_L_TO_H)


MCP4822 data sheet:
http://ww1.microchip.com/downloads/en/devicedoc/22249a.pdf

Quote:
The MCP4802/4812/4822 devices are designed to
interface directly with the Serial Peripheral Interface
(SPI) port, available on many microcontrollers, and
supports Mode 0,0 and Mode 1,1.

i.e., it supports SPI modes 0 and 3. Compare that to your code.

And you're totally ignoring the upper 3 bits in the command word,
which you can't do, and still hope that it works.
rikotech8



Joined: 10 Dec 2011
Posts: 376
Location: Sofiq,Bulgariq

View user's profile Send private message

PostPosted: Thu Mar 01, 2012 11:23 am     Reply with quote

I know about upper 3 bits and it suits me they to be '0'.

Quote:

15bit: 0 = Write to DACA
13bit: 0 = 2x (VOUT = 2 * VREF * D/4096)
12bit: 0 = Output buffer disabled, Output is high-impedance
temtronic



Joined: 01 Jul 2010
Posts: 9162
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Thu Mar 01, 2012 1:02 pm     Reply with quote

my 'guess' is that his oddly named variable 'res' which is set to 4,000 is not a good set of data to send to the DAC.

1st I would rename it to something like 'DAC_CMD_DATA'.
2nd I would use hex values to easily see what is being sent.
3rd I would define the pin used for DAC chip select as DAC_CS*.
4th I would use the SPI 'mode' defines as shown elsewhere .

5th I would confirm the dac command sequence to be valid.

6th Normally I'd have a LOT more fuse options too !
rikotech8



Joined: 10 Dec 2011
Posts: 376
Location: Sofiq,Bulgariq

View user's profile Send private message

PostPosted: Sat Mar 03, 2012 12:35 am     Reply with quote

Hello! I have made some changes in my code, according to your suggestions.
Code:

#include <18f2520.h>
#fuses nomclr,wdt,noprotect,intrc
#use delay(internal = 8M)
#define chip_select pin_C4
#define prog_exe    pin_A0

void main()
{
setup_spi(SPI_MASTER|SPI_XMIT_L_TO_H|SPI_L_TO_H|SPI_CLK_DIV_4);
unsigned int16 Data_word; 
unsigned int8 msb,lsb;
set_tris_a(0);
set_tris_b(0);
set_tris_c(0);
while (1)
{
SETUP_WDT(WDT_ON);
output_high(prog_exe);
for(Data_word=0x00;Data_word<0xfff;Data_word++)   
   {
    msb = make8(Data_word,1);
    lsb = make8(Data_word,0);
    bit_set(msb,4); 
    bit_set(msb,5); 
    delay_ms(5);
    output_low(chip_select);
    delay_us(10);
    spi_write(msb);
    spi_write(lsb);
    delay_us(10);
    output_high(chip_select);
   }
}
}

With this code I had a success partly. When I test the DAC (MCP4822) with this driver
On the output the voltage should be increasing. It's OK for now, but about 400mV, the
output voltage pull down for very short moment, and then continue works correct. I'm wondering, if that problem is hardware or software.
ckielstra



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

View user's profile Send private message

PostPosted: Sat Mar 03, 2012 8:44 am     Reply with quote

You enable the watchdog but never trigger it inside the long for-loop....

For a first prototype you save yourself a lot of trouble by disabling the watchdog. For many projects a watchdog is unimportant, but if you do need one, then at a later time add the watchdog code when you know the rest is working correctly.

When a program is not working then try to make it as simple as possible by removing all fancy stuff. Often this solves the problem so you know where to look and otherwise the code without the extras is easier to debug.
temtronic



Joined: 01 Jul 2010
Posts: 9162
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sat Mar 03, 2012 9:42 am     Reply with quote

Also for debugging, add a simple print statement to either a PC terminal program or a local LCD to display the variables.

Since we don't easily know the DAC config, the error at 400mv, doesn't mean too much however if you also include the dataword,msb,lsb we can better diagnose what might be the problem.

In your case , I'd like to see dataword, msb,lsb to confirm the numbers are correct.You might want a large delay inside the loop,say 100ms so you can observe the LCD data !

disable the WDT for sure !!
Ttelmah



Joined: 11 Mar 2010
Posts: 19328

View user's profile Send private message

PostPosted: Sat Mar 03, 2012 10:05 am     Reply with quote

I'm fairly sure the core problem here is the watchdog. It'll default to /128, so will give about 600mSec timeout. At 5+mSec per repeat, this will be about 0.1 of the output scale, or about 0.4v.....
However, as a general comment, 'think tidier':
Code:

#include <18F4520.h>
#device adc=16
#FUSES WDT, WDT128, INTRC_IO, NOFCMEN, NOIESO, PUT, BORV27, NOPBADEN, NOLPT1OSC, NOMCLR, NOLVP, NOXINST
#use delay(internal = 8M, RESTART_WDT)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,errors)

#define SPI_MODE_0  (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1  (SPI_L_TO_H)
#define SPI_MODE_2  (SPI_H_TO_L)
#define SPI_MODE_3  (SPI_H_TO_L | SPI_XMIT_L_TO_H)

union combiner {
   int8 bytes[2];
   int16 word;
};
#define DAC_CS (PIN_C2)
#define RUNNING (PIN_A0)
   
void set_4822(union combiner value,int1 channel,int1 gain) {
   //Function to configure 4822
   #bit DAC_chan=value.15
   #bit DAC_gain=value.13
   #bit DAC_enable=value.12
   
   DAC_chan=channel; //select channel
   DAC_gain=gain; //gain
   DAC_enable=TRUE; //turn on the DAC
   output_low(DAC_CS);
   spi_write(value.bytes[1]);
   spi_write(value.bytes[0]);
   output_high(DAC_CS);
}

void main(void) {
   //Variable definitions _must_ be before code in any block
   unsigned int16 Dac_Value;

   setup_spi(SPI_MASTER|SPI_MODE_3);
   output_high(DAC_CS); //You must ensure this starts _high_.

   set_tris_a(0);
   set_tris_b(0);
   set_tris_c(0);
   
   SETUP_WDT(WDT_ON); //You have enabled the watchdog - must keep resetting it....
   output_high(RUNNING);   
   do {
      for (Dac_Value=0;Dac_Value<4096;Dac_Value++){
         
         restart_wdt();
         set_4822(Dac_Value,0,1);
         delay_ms(5); //also modified to restart watchdog
      }
   } while (TRUE); //avoids condition always true error
}


Put the DAC code into a routine, then you can delay, or fiddle with it, independently of the 'main' code, and also use it again when you want to access the second channel etc...

Best Wishes
rikotech8



Joined: 10 Dec 2011
Posts: 376
Location: Sofiq,Bulgariq

View user's profile Send private message

PostPosted: Sun Mar 04, 2012 9:35 am     Reply with quote

Thank you, but there is two things I don't understand.
1. Why do you declare #use rs232, why do you need that ?
2. What is that
Quote:
union combiner value
its a totally unknown for me?

Thank you very much again!
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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