|
|
View previous topic :: View next topic |
Author |
Message |
rikotech8
Joined: 10 Dec 2011 Posts: 376 Location: Sofiq,Bulgariq
|
SPI and DAC |
Posted: Wed Feb 29, 2012 1:39 pm |
|
|
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: 1615 Location: Central Illinois, USA
|
|
Posted: Wed Feb 29, 2012 5:29 pm |
|
|
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
|
|
Posted: Wed Feb 29, 2012 6:24 pm |
|
|
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
|
|
Posted: Thu Mar 01, 2012 11:23 am |
|
|
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: 9245 Location: Greensville,Ontario
|
|
Posted: Thu Mar 01, 2012 1:02 pm |
|
|
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
|
|
Posted: Sat Mar 03, 2012 12:35 am |
|
|
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
|
|
Posted: Sat Mar 03, 2012 8:44 am |
|
|
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: 9245 Location: Greensville,Ontario
|
|
Posted: Sat Mar 03, 2012 9:42 am |
|
|
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: 19546
|
|
Posted: Sat Mar 03, 2012 10:05 am |
|
|
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
|
|
Posted: Sun Mar 04, 2012 9:35 am |
|
|
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! |
|
|
|
|
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
|