View previous topic :: View next topic |
Author |
Message |
AlPicCss73
Joined: 20 May 2015 Posts: 18
|
DAC Module does not work in dspic33fj128gp804 |
Posted: Fri Jul 08, 2016 10:51 am |
|
|
Hi guys!
I'm trying to use the internal dac modules in the 33fj128gp804. but they're not working and I have no idea about that. in the following topic the same chip is used and seems working at all.
http://www.ccsinfo.com/forum/viewtopic.php?t=45621&highlight=dspic33fj128gp+dac
The problem that I'm facing is when I configure the DAC module its output is constant and does not change anyway. I disable and enable the midpoint but it's still there and the negative and the positive outputs are at 1.5 and 1.7 volt respectively. In mean time I don't find any problem with my hardware at all.
This is my code:
Code: |
int idac;
void main()
{
setup_dac(DAC_LEFT_ON, 1);
while(TRUE)
{
idac++;
dac_write(DAC_LEFT,idac);
if (idac==12000)
idac=0;
}
}
|
And I changed the registers manually in different ways:
Code: |
#word DAC1CON = 0x03F0
#word DAC1STAT = 0x03F2
#word DAC1DFLT = 0x03F4
#bit LEMPTY = 0x03F2.8
|
So, what's wrong? What I've missed?
Bests.
Last edited by AlPicCss73 on Fri Jul 08, 2016 12:28 pm; edited 1 time in total |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1349
|
|
Posted: Fri Jul 08, 2016 11:31 am |
|
|
We used a built in dac on another chip (A PIC24 I think) and on ours using the default settings we had to continuously reload the DAC value using its interrupt. Otherwise it would release the line and not output the value we wanted.
We ended up moving to an external DAC later on for other reasons, so I don't know if we could have configured it differently or not, but it might be something you could try to see if it is the same scenario. To get a specific value we would use a global variable to hold the value and then have the interrupt use that variable to reload the register each time it fired.
We didn't spend enough time on it to see if we were doing the hardware wrong or if the configuration was wrong though.
It was something like:
Code: |
volatile unsigned int16 dac_value = 0;
#INT_DAC1L
void DAC1L_isr(){
dac_write(DAC_LEFT,dac_value);
}
void main(){
setup_dac(DAC_LEFT_ON,1);
dac_value = 0x8000; //some value
enable_interrupts(INT_DAC1L);
enable_interrupts(GLOBAL);
while(TRUE);
}
|
EDIT: found it! we were trying out the dspic33FJ128GP804 |
|
|
AlPicCss73
Joined: 20 May 2015 Posts: 18
|
|
Posted: Fri Jul 08, 2016 12:42 pm |
|
|
Thanks, But nothing changed!
As I understand, using an infinite loop do the same thing like your code. It's really confusing for me that why negative and positive outputs both have high values. it's really disappointing that I don't find any clue. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Fri Jul 08, 2016 2:50 pm |
|
|
The first thing is that you are going to be sending the values too fast. 100Ksps max with a 25.6MHz master DAC clock.
Then what is your DAC clock rate?. You are setting the divisor to 1, the maximum rate for this is 25.6MHz.
Understand this is not a conventional DAC. It is designed for audio synthesis. It has a master clock, which it needs. If you look at the example post you have found, he gives how he is calculating this, and sets it up. He then tests the DAC register for empty (or you can use the interrupt for this), and loads the next value. It synthesises points 'between' the values you give, for 256 DAC clocks between each load.
If you don't reload the register, the output will fade to zero over the next 256 cycles (this is what Jeremiah was seeing). |
|
|
AlPicCss73
Joined: 20 May 2015 Posts: 18
|
|
Posted: Fri Jul 08, 2016 10:51 pm |
|
|
Thanks, but nope! that's not the case as I know the internal clock is about 1/256 of external clock, so with my 8MHz clock this won't be a problem. In spite of this fact, I used the slowest mode and nothing changed. It's reluctant to any changes and that's a strange thing. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Sat Jul 09, 2016 12:59 am |
|
|
No.
There are two different DAC rates. The master clock, which is directly 'at' the clock rate you set it, and DAC 're-sample' rate, which is at 1/256th this.
What happens is that the DAC outputs a value at every cycle of it's master clock (the Aux clock). It is this that is limited to 25.6 MHz. Every 256 of these, it requests a new value (INT_DAC, or the buffer empty bit). This then gives the DAC 'update' rate. So you have a DAC update rate limited to 100KHz, and a DAC master clock limited to 25.6MHz (256 times the update rate). The values it outputs in the 256 cycles are generated by hardware interpolation. This is the 256* 'oversampling' supported by this DAC.
Now the DAC, can be fed from it's own external crystal on the secondary oscillator, or from the system clock. Which are you selecting?. This is the SELACK bit. What speed are you running the system?.
If you look at the example you refer to, he is using the 7.37MHz FRC oscillator, and clocking the CPU at 16* this to give 117.92Mhz. He then divides this by 8, to give an Aux clock (he calculates) of 22.115Mhz. So under the 25.6MHz limit. This then potentially gives a DAC update rate of 86.4 KHz.
If you look though, this figure is wrong (117.92/8 = 14.74MHz). His update rate will then be 57.5KHz.
So though he is working off just 7.37MHz, he is clocking the DAC at 14MHz. The clocking needs to be got right, before you have any hope of getting the chip to update correctly. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Sat Jul 09, 2016 2:44 am |
|
|
jeremiah wrote: | We used a built in dac on another chip (A PIC24 I think) and on ours using the default settings we had to continuously reload the DAC value using its interrupt. Otherwise it would release the line and not output the value we wanted.
We ended up moving to an external DAC later on for other reasons, so I don't know if we could have configured it differently or not, but it might be something you could try to see if it is the same scenario. To get a specific value we would use a global variable to hold the value and then have the interrupt use that variable to reload the register each time it fired.
We didn't spend enough time on it to see if we were doing the hardware wrong or if the configuration was wrong though.
It was something like:
Code: |
volatile unsigned int16 dac_value = 0;
#INT_DAC1L
void DAC1L_isr(){
dac_write(DAC_LEFT,dac_value);
}
void main(){
setup_dac(DAC_LEFT_ON,1);
dac_value = 0x8000; //some value
enable_interrupts(INT_DAC1L);
enable_interrupts(GLOBAL);
while(TRUE);
}
|
EDIT: found it! we were trying out the dspic33FJ128GP804 |
The point is that this is not a standard DAC, where you output a value, and it feeds to a resistor tree to give a voltage. This is an audio DAC, which automatically oversamples at 256* the selected output rate. Every DAC update needs a value loaded to the buffer, or after a couple of cycles the buffer will empty, and the output will (smoothly) be interpolated to zero....
It's not really the tool if you just want a stable voltage output. |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1349
|
|
Posted: Sat Jul 09, 2016 8:07 am |
|
|
No disagreement here. Unfortunately I don't get to make those kind of decisions where I work. Luckily we had another reason to switch (I forget what is was now...like 2 or 3 years ago). |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Sun Jul 10, 2016 11:42 am |
|
|
As a further comment to the original poster, this DAC, takes a signed value, so for 'zero', the output will be sitting at half the reference voltage.... |
|
|
AlPicCss73
Joined: 20 May 2015 Posts: 18
|
|
Posted: Mon Jul 11, 2016 2:38 am |
|
|
Thanks guys! Really useful comments.
But I'm still confused, sort of! And that's because I've never changed the clock settings except those configuration registers. Would you help me in setting the registers?
I'm using an 8MHz external crystal and I want at least meet the minimum requirements to bring it to the life. My configuration registers are:
Code: |
FOSCSEL :0x0082
FOSC :0x0085
OSCCON ?
CLKDIV ?
PLLFBD ?
ACLKCON ?
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Mon Jul 11, 2016 7:00 am |
|
|
You keep telling us you are using an 8MHz crystal, but not how fast you are clocking the PIC?.
Post your fuses, and your clock setup line.
The crystal on these PIC's does not tell you how fast the chip is going.
Unless you mean you have this on the secondary oscillator?. |
|
|
AlPicCss73
Joined: 20 May 2015 Posts: 18
|
|
Posted: Mon Jul 11, 2016 1:40 pm |
|
|
You're right! But that's because I just wanted to run it anyway. I used the basic settings, using external crystal without PLL which results in 4Mips and don't use any secondary oscillator. All configuration bits are here:
Code: |
FBS : 0x00CF
FSS :0x00CF
FGS :0x0007
FOSCSEL :0x0083
FOSC :0x0045
FWDT :0x005F
FPOR :0x00F7
FICD :0x00C3
|
I'm confused because when I checked the values of the link that I posted before with its explanation, I found some contradictions. The values that I think should be correct are here:
Code: |
OSCCON = 0x0342;
CLKDIV = 0x07C0;
PLLFBD = 0x002f;
ACLKCON = 0x074A;
|
I really appreciate your comments. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Tue Jul 12, 2016 6:04 am |
|
|
What I am looking for, is a _basic_ program showing what you are trying to do, with the CCS code. So something like:
Code: |
#include <33FJ128GP804.h>
#device ICSP=1
#use delay(CLOCK=8MHz)
#FUSES PR //Run primary oscillator with no PLL
#FUSES XT //XT oscillator on primary (<10MHz)
#FUSES NOWDT
#FUSES NOCKSFSM
#FUSES NOJTAG
#bit FORM=getenv("BIT:FORM")
#word ACLKCON=getenv("SFR:ACLKCON")
volatile int16 dac_value = 0;
int1 update=FALSE;
#INT_DAC1L
void DAC1L_isr()
{
dac_write(DAC_LEFT,dac_value); //This should be called about 8000*per second
update=TRUE;
}
void main(void)
{
setup_dac(DAC_LEFT_ON,4); // -> update at 8000000/1024 = 7812*per second
FORM=0; //make sure output is set to unsigned
ACLKCON=0x0780; //ensure primary oscillator selected
dac_value = 0; //Starting point
enable_interrupts(INT_DAC1L);
enable_interrupts(GLOBAL);
while(TRUE)
{
while(update==FALSE)
; //wait for the DAC to update
update=FALSE;
dac_value++;
if (dac_value>=12000)
dac_value=0;
}
}
|
Toggle a pin in the interrupt and see if it is being called. What happens?. |
|
|
|