Dear All,
This is regarding interfacing DAC8552 using stellaris LM3s6965 evaluation board. I have following queries:-
I could succeed writina full scale value to DAC 8552 but any intermediate values are not getting updated.
void SpiInit(void){ SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); GPIOPinConfigure(GPIO_PA2_SSI0CLK); GPIOPinConfigure(GPIO_PA5_SSI0TX); GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5 | GPIO_PIN_4| GPIO_PIN_2); SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 1000000, 8); SSIEnable(SSI0_BASE); }
//*****************************************************************************//// void DacUpdate_channelA(void);//test byte = 8bit data which needs to be sent to DAC as count 3 times.
eg: i want to just update DAC A then I need to write Into DAC register count as 0x30FFFF; so testbye1 =0x30; testbyte2=0xFF; testbyte3= 0xFF;//*****************************************************************************void DacUpdate_channelA(void){ StartDacUpdate(); // pull SYNC signal low SsiWrite(test_byte1); // this function is being called inside void main(); SsiWrite(test_byte2); SsiWrite(test_byte3); StopDacUpdate(); // pull SYNC signal high}
//*****************************************************************************//// void SsiWrite(unsigned char byte)////*****************************************************************************void SsiWrite(unsigned char byte){ // while(!SSIBusy(SSI0_BASE)); SSIDataPut(SSI0_BASE, byte); }
//*****************************************************************************//// void StartDacUpdate(void);////*****************************************************************************void StartDacUpdate(void){ GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE,GPIO_PIN_1); GPIO_PORTA_DATA_R &= ~(0x02);}
//*****************************************************************************//// void StopDacUpdate(void);////*****************************************************************************void StopDacUpdate(void){ GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE,GPIO_PIN_1); GPIO_PORTA_DATA_R|= 0x02;}
Also if I would like to use the PA3 pin as a GPIO which has multiplexed functionality as SSIFss, what care has to be taken while configuring the pin as a GPIO to avoid getting into FAULT ISR.
Also I observed that in CCSv4.1 while using LM6965 eval board I am not able to put breakpoints at run time, every time I need to pause the execution and put the breakpoint and then execute the code again. Is there any solution for this as while using the same IDE for MSP430 series I do not face such problems.
Please help....
Regards,
harshit
Harshit,
I am trying to design an interface from Stellaris (LM3S5P56) SPI to DAC8552. I am doubtful about using the frame signal SSI0FSS because the value to be clocked on every frame is 24-bits long (8 control, 16-bit data) and it seems that none of the Stellaris SPI modes handle a 24-bit value with the FSS signal. I saw that you had to shift from PA3 (SSI0FSS) to PA1 (as GPIO?) to get it to work, but still you seemed to be having difficulty. I am currently doing the circuit design for my prototype hardware and had planned on connecting SSI0CLK to SCLK, SSI0FSS to SYNC, and SSI0TX to DIN. This is exactly what you tried, but I'm not sure if you were successful.
Could you tell me how you solved your problem?
Thanks in advance for any help you may provide.
Kind regards,
Kevin in Goa
Hi kevin...
Kevin KregerCould you tell me how you solved your problem?
I had faced this issue when I was new to this controller family. I had to interface this DAC with both MSP and stellaris Any ways u can proceed with your design as u mentioned. In my case it worked well afterwards. Just make sure to configure the SSI0FSS pin as a simple GPIO not as a peripheral functionality just that pin only. U have to use 3 wire SPI to communicate with DAC.
As far as sending 24bit data is concerned, the DAC will look it as a 24 bit stream unless u do not pull the SYNC pin high, after pullin it low initially i.e frame the control byte in such a way that u arrange it in single byte stream. So first pull the chip select low send 3 bytes by ensuring each byte is transmitted properly (split 24bit data into 3 bytes) and pull the sync pin high. It will work.
Hope this helps....... i do not have access to code as i am on outdoor duty would post my code if u still face problem in updating DAC.
harshit Jain
Hi Harshit,
Thanks so much. I found the app note on interfacing a similar DAC here:
http://www.ti.com/mcu/docs/litabsmultiplefilelist.tsp?sectionId=96&tabId=1502&literatureNumber=sbaa158&docCategoryId=1&familyId=342
AND I re-read your posting. So, I concluded that I could just toggle a line as GPIO for the frame sync as you suggest. However, I did move from the FSS pin to another pin as I was fearful the chip may have a problem per your experience. Apparently, this fear was unwarranted :-)
So, I will pulse the SYNC as GPIO and make sure it stays low for the 3 byte transfers and then repeat.
I posted because I was finishing the hardware design and wanted to be sure there was no error in the board, so I would appreciate any code snippets when I get onto the coding part and you are no longer on outdoor duty. I'm not sure duties such a talented software guy could have outdoors, but I hope you are enjoying. It is still nice and cool in Goa and I am enjoying before the heat arrives. This weekend is carnival so I may see a parade and some floats. I am more looking forward to Shigmo as I am told the gods on the floats are much more elaborate and animated.
Thanks again for your time. Let me know if there is anything you may need in return. I will likely be asking you for your advice when I get to writing the SSI codes.
Kevin
I am facing problems with the new board writing to DAC8552 using Stellaris SSI.
Note I am only using Tx and CLK in SSI1. For my SYNC* framing I am using a different port entirely and I tested the START_DAC_UPDATE() and STOP_DAC_UPDATE() macros by checking SYNC* pin on the chipto confirm it is being pulled low before the 3 bytes are written and then high after (with a short delay added for caution).
Here is my setup:
SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI1); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); GPIOPinConfigure(GPIO_PE0_SSI1CLK); GPIOPinConfigure(GPIO_PE3_SSI1TX); // The pins are assigned as follows: // PE3 - SSI1Tx // PE0 - SSI1CLK GPIOPinTypeSSI(GPIO_PORTE_BASE, GPIO_PIN_3 | GPIO_PIN_0); // Disable the SSI1 module while making changes SSIDisable(SSI1_BASE);
SSIConfigSetExpClk(SSI1_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 1000000, 8); SSIEnable(SSI1_BASE);
Here is how I write to the DAC8552:
unsigned char bytea = 0x10, byteb = 0x24, byte2= 0x40, byte3= 0x40;
START_DAC_UPDATE(); //DAC SYNC* signal low SSIDataPut(SSI1_BASE, byteb); // byte1 is control byte which selects DAC channel SSIDataPut(SSI1_BASE, byte2); // byte2 is MSB of value SSIDataPut(SSI1_BASE, byte3); // byte3 is LSB of valuei = 0;do{i++;}while(i < 100); STOP_DAC_UPDATE(); //DAC SYNC* signal high
I don't get any change in voltage...both DOUTA and DOUTB are zero volts :-(
(Note that I try both DOUTA and DOUTB with the control bytes bytea and byteb)
Suggestions?
It is very hot in Goa. I hope you are managing to stay cool!
Thanks in advance,
You can ignore my last request. I have gotten it to work by putting a SSIDataGet() before every SSIDataPut().
Hi Kevin,
You shouldn't need a SSIDataGet() before a SSIDataPut call, something else must be wrong. From the DAC datasheet, I think you rather need SSI_FRF_MOTO_MODE_1, instead of a SSI_FRF_MOTO_MODE_0, which has a low clock polarity bit but a high phase control bit, did you try that already?
Hey Marc,
Thanks for your analysis! I did have to change to SSI_FRF_MOTO_MODE_1 ~AND~ do the SSIDataGet()....go figure.
It is the only way that it works. It took me a loooong time to get this to work, but I had previously set up SSI0 to read a serial ADC and I had to do the same thing with MODE_1 and (in the case of reading incoming ssi data)do an interleaved SSIDataPut().
If you can suggest what else I may try because the excess puts and gets are just eating op cycles.
Thanks again,
I still think it’s a timing problem, instead of implementing a delay(do-loop), you’d be better of polling the busy(BSY) bit and transmission FIFO empty(TFE) bit, in the status register(SSISR), before pulling the DAC SYNC line high.
Checking for the busy bit only will probably be enough, but you could loop until the BSY bit is zero and the TFE bit is set, and delete the SSIDataGet() calls.
Hi Marc,
I will try it, but I had tried something similar with the SSI0 when I was receiving data (except with Rx FIFO). This seems like it should work better then the kludge that I have! :-)I'm struggling with a timer problem at the moment though wherein I get a fault ISR if I increase the speedof the timer, so it will take me some time to get back onto this.I noticed that you are ~not~ Stellaris Marc, so this means you are not with TI, correct?
Anyhow, I am sure to be hacking away all day. The sun has just come up here and it is going to be blazinghot outside (I'm in India). It's a good climate for staying inside and coding if you have AC.
Thanks so much!
kevin
Kevin,
Your timer problem is probably a wrong manipulation of a register, if you have any means of debugging, check the fault registers when the program enters in the fault ISR loop.
Anyway, regarding the SSI problem, you need to wait until the last byte has left the serializer, before pulling the SYNC pin high, a simple delay loop does not always guarantee that this will be the case, and waiting longer than necessary is not optimal either (also some compilers might not compile that piece of code(depending on the optimization level), especially within a ISR, unless you define the variable as volatile).
No I’m not Stellaris Marc, just marc from Brussels :)
Here we are screaming for a little more sun, it’s the heating we need to turn on :(
Cheers!
Dear Brussels Marc :-)
Thanks for the tip...we are on the road from Bombay to US. I am sure to try this, but probably after another week. I've wanted to clear this mystery for sometime and I just had to rush on to the next thing when I got it to work. The odd thing was I inherited this code from an MSP430 (this code was doing SSI reads from a ADC). He was interspersing these SSI writes and I thought...that's odd...I'll delete this crap and get it to work properly. BUT I had to replace the writes to get the reads to work! Now, I have the reverse problem with having to insert reads to get writes to work with an DAC. I did look at status bits with the original ADC problem, but to no avail. So, I'm sure there is a common best approach for solving both these problems, but it will have to wait as I am having a serious problem with the Beta of the ADC chip which TI is looking at.
cheers,
k
I've finally gotten back to this. I checked the DAC8552 output and it won't let me go above about 1/2 full scale (1/2 of Vref).
I thought at first I must be latching an extra zero at the end of the first byte written (the control byte) but the measurements don't support that assumption.
Have you heard of anything like this? Any suggestions?
Thanks!
I monkeyed with the clock rate on the SSI and was able to get 1 of the 2 outputs to full scale! I'm guessing is dirty clock or dirty data line.
Note: DAC8552 is very close to Stellaris. The data line is a straight run with no conditioning components going straight from Stellaris (about 1/2-3/4 inch run),
The data line is the same, but I put a 33 ohm resistor in-line. Any idea if/how I should condition these lines with Rs or Cs?
k.
You don't need any resistors in the SSI lines, and certainly don’t add any capacitors(RC), this will delay your signal(you’ll create a sinus like signal, instead of a rectangular signal on the lines)
Just connect them straight pin to pin(even if you have multiple devices on the same bus, with SPI, the pins from the non selected devices are high –z, so you should not have any drive problems), only if you have long print lanes, you can pull them high(100K) at the last device.
Dear Marc,
First of all, thanks so much. You have really gone out of your way to help me on this one.
Second, do you agree that this is a noisy data or clock line issue? It seems that because it is timing related as I can change the SSI rate from 1MHz to 250kHz (or 5MHz) and I start to get the correct full-scale on one of the two DAC8552 outputs that this seems to be a noise issue (but please note I am in India without a proper o-scope).
Third, if you agree it is noise related the consider my layout: I have short runs for clock and data (as I say, 1/2-3/4 inch) but my clock line has a 33 ohm in-line (i.e. spi clock out of stellaris connects to 33 ohm other side of 33 ohm is tied to SCLK on DAC8552)...the data line itself is direct connect (also about 1/2-3/4 inch). It sounds like I should replace the 33 ohm with a jumper. Do you agree? Also, I will look at the layout and see if there is any noisy lines nearby.
Finally, below is the code I am using for setup and sending data. This appears to work for one channel, but not the other (despite the fact it is identical except for the data). So, I expect it is not the code, but a noise issue.
Please let me know if you agree or find fault with my analysis. As well, if you think I should remove the 33 ohm resistor.
THANKS!
----------------------------------------------------------------------------------------------------
SSI1 SETUP:
// Enable SSI1 peripheral SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI1);
// SSI1 is used with PortE // Enable GPIO port E SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
// Configure the pin muxing for SSI1 functions on PE0 & PE3 GPIOPinConfigure(GPIO_PE0_SSI1CLK); GPIOPinConfigure(GPIO_PE3_SSI1TX);
// Configure the GPIO settings for the SSI pins. This function also gives // control of these pins to the SSI hardware. // The pins are assigned as follows: // PE3 - SSI1Tx // PE0 - SSI1CLK GPIOPinTypeSSI(GPIO_PORTE_BASE, GPIO_PIN_3 | GPIO_PIN_0);
// Disable the SSI1 module while making changes SSIDisable(SSI1_BASE);
// // Configure and enable the SSI port for SPI master mode. Use SSI0, // system clock supply, idle clock level low and active low clock in // freescale SPI mode, master mode, 1MHz SSI frequency, and 8-bit data. // For SPI mode, you can set the polarity of the SSI clock when the SSI // unit is idle. You can also configure what clock edge you want to // capture data on. Please reference the datasheet for more information on // the different SPI modes. ////! Polarity Phase Mode//! 0 0 SSI_FRF_MOTO_MODE_0//! 0 1 SSI_FRF_MOTO_MODE_1//! 1 0 SSI_FRF_MOTO_MODE_2//! 1 1 SSI_FRF_MOTO_MODE_3// When the SPH phase control bit is clear, data is captured on the first clock // edge transition (0->1). If the SPH bit is set, data is captured on the second// clock edge transition (1->0).// TBD: SPO = 1, SPH = 0 (i.e. MODE_1)? SSIConfigSetExpClk(SSI1_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_1, SSI_MODE_MASTER, 10000000, 8); //This worked for DOUTA but DOUTB corrupt// SSI_MODE_MASTER, 5000000, 8); //This worked for DOUTA but DOUTB corrupt// SSI_MODE_MASTER, 50000, 8); //This worked for DOUTA but DOUTB corrupt// SSI_MODE_MASTER, 25000, 8); //This worked for DOUTA but DOUTB corrupt// SSI_MODE_MASTER, 1000000, 8); //DOUTA & DOUTB corrupt
// Read any residual data from the SSI port. SSIDataGetNonBlocking() returns // "true" when data was returned, and "false" when no data was returned. while(SSIDataGetNonBlocking(SSI1_BASE, &ulDataRx)) { } SSIEnable(SSI1_BASE);
-----------------------------------------------------------------------------------------
UPDATING DAC8552:
if( vs_dc_offset != vs_dc_offset_old ) { //Update DAC for Red LED OFFSET with vs_dc_offset // Write vs_dc_offset value to DAC8552 (DOUTA) START_DAC_UPDATE(); //DAC SYNC* signal low SSIDataPut(SSI1_BASE, 0x10); // byte1 is control byte which selects DAC channel A SSIDataGet(SSI1_BASE, &uldata); SSIDataPut(SSI1_BASE, vs_dc_offset >> 8); // byte2 is MSB of value SSIDataGet(SSI1_BASE, &uldata); SSIDataPut(SSI1_BASE, vs_dc_offset); // byte3 is LSB of value SSIDataGet(SSI1_BASE, &uldata); //TBD - Delay before stop? i = 0; do{i++;}while(i < 100); STOP_DAC_UPDATE(); //DAC SYNC* signal high vs_dc_offset_old = vs_dc_offset; } if( vs_LED_level != vs_LED_level_old ) { //TBD - Delay before start? i = 0; do{i++;}while(i < 100); //Update DAC for Red LED with vs_LED_level // Write vs_LED_level value to DAC8552 (DOUTB) // Note: Control byte for writing DOUTB is 0x24 (DOUTA is 0x10 see p. 16 of data sheet) START_DAC_UPDATE(); //DAC SYNC* signal low//TEST ONLY - add delayi = 0; do{i++;}while(i < 100); SSIDataPut(SSI1_BASE, 0x24); // byte1 is control byte which selects DAC channel SSIDataGet(SSI1_BASE, &uldata); SSIDataPut(SSI1_BASE, vs_LED_level >> 8); // byte2 is MSB of value SSIDataGet(SSI1_BASE, &uldata); SSIDataPut(SSI1_BASE, vs_LED_level); // byte3 is LSB of value SSIDataGet(SSI1_BASE, &uldata); //TBD - Delay before stop? i = 0; do{i++;}while(i < 100); STOP_DAC_UPDATE(); //DAC SYNC* signal high vs_LED_level_old = vs_LED_level; }