Problem with SPI - Transferring 32 bit on MPC5644A

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

Problem with SPI - Transferring 32 bit on MPC5644A

2,329件の閲覧回数
VaisakhPS
Contributor I

Hi Everyone,

 

I am trying to interface a DAC(DAC8168) on to Freescale's MPC5644A evaluation kit over SPI_B interface. The SPI controller FIFO allows us to write 16-bit at a time, and if the chip select is deasserted before ADC samples 32-bit, the data will be discard. Now this is where the problem resides. 

 

In my implementation of SPI driver, I am using continous chip select assertion during the taransfer, but after transferring first 16-bit, there is a small glitch (or a transition )in chip select and clock lines. How to solve this???

 

I have attached waveforms observed in CRO and source code.

 

Regards,

Vaisakh P S

 

 

#include "MPC5644A.h"extern void SpiDrvrInit();extern void SpiDrvrWrite32(unsigned char cs,unsigned int databuff);       /* **************************************************************************** * PLL Code * **************************************************************************** */typedef struct { uint8_t eprediv; uint8_t emfd; uint8_t erfd; }T_FMPLL_INITVALS;#define  FMPLL_MHZ_INDEX  0/* * Table containing initialisation values for FMPLL */T_FMPLL_INITVALS fmpll_init_vals [] = { {0x04, 0x46, 0x01},   };/* * Function to initialise system clock and PLL values * */void initSysclk (int req_clk_index) {  uint32_t esyncr1_val = 0xF0000000         | (((uint32_t)(fmpll_init_vals[req_clk_index].eprediv)) << 16)        | ((uint32_t)(fmpll_init_vals[req_clk_index].emfd));  uint32_t esyncr2_val = ((uint32_t)(fmpll_init_vals[req_clk_index].erfd));         FMPLL.ESYNCR2.R = esyncr2_val;   /*Set */    FMPLL.ESYNCR1.R  = esyncr1_val;          while (FMPLL.SYNSR.B.LOCK != 1) {};  /* Wait for FMPLL to LOCK  */  }       /* **************************************************************************** * SPI Code * **************************************************************************** */static void initDSPI_B(void) { //configure pads SIU.PCR[102].R = 0x0606;  // SPI Clock DSPI_B_CSK, primary, out SIU.PCR[103].R = 0x0500;  // DSPI_B_SIN, primary SIU.PCR[105].R = 0x0604; // Chip select DSPI_B_CS, primary,out //~~SIU.PCR[105].R = 0x0205; // Chip select DSPI_B_CS, GPIO,out //~~SIU.GPDO[105].B.PDO = 1;  SIU.PCR[104].R = 0x0605;  // DSPI_B_SOUT, primary  // DAC GPIOS SIU.PCR[203].R = 0x0200; SIU.GPDO[203].B.PDO = 0; SIU.PCR[204].R = 0x0200; SIU.GPDO[204].B.PDO = 0; // configure controller   DSPI_B.MCR.R = 0xA0010001;     /* Configure DSPI_B as master */}static void StartDSPI_B(void) { // configure controller DSPI_B.SR.B.EOQF = 0x0; DSPI_B.MCR.B.FRZ = 0x0; DSPI_B.MCR.B.HALT = 0x0;     /* Leave HALT mode*/ // Wait until running state is set while (DSPI_B.SR.B.TXRXS == 0){} }static void StopDSPI_B(void) { DSPI_B.SR.B.EOQF = 0x1; DSPI_B.MCR.B.FRZ = 0x1; DSPI_B.MCR.B.HALT = 0x1;     /* Enter HALT mode*/ while (DSPI_B.SR.B.TXRXS != 0){}}void SpiDrvrWrite32(unsigned char cs,   // chip select to be asserted     unsigned int databuff) // buffer containinng data to be transmitted{ unsigned short *tbuffptr = (unsigned short *)&databuff;  // Setting  //  framesize to 16 bits,  //  SCLK to active high //  Data is captured on leading edge and changed on falling //  Baudrate scaler to 0xF //  Baudrate Pre scaler to 0x3 DSPI_B.CTAR[0].R = 0x7A03000A; //0x7A030001; - for LSB First // set configuration for transfer //~~SIU.GPDO[105].B.PDO = 0; StartDSPI_B(); //select chip selects switch(cs) {  case 0: DSPI_B.PUSHR.B.PCS0 = 1;break;  case 1: DSPI_B.PUSHR.B.PCS1 = 1;break;  case 2: DSPI_B.PUSHR.B.PCS2 = 1;break;  case 3: DSPI_B.PUSHR.B.PCS3 = 1;break;  case 4: DSPI_B.PUSHR.B.PCS4 = 1;break;  case 5: DSPI_B.PUSHR.B.PCS5 = 1;break;  case 6: DSPI_B.PUSHR.B.PCS6 = 1;break;  case 7: DSPI_B.PUSHR.B.PCS7 = 1;break; } DSPI_B.PUSHR.B.TXDATA = tbuffptr[0]; DSPI_B.PUSHR.B.TXDATA = tbuffptr[1]; // Wait for transmission completion while(DSPI_B.SR.B.TCF == 0){} StopDSPI_B(); //~~SIU.GPDO[105].B.PDO = 1; } /* **************************************************************************** * DAC Code - DAC8168 * **************************************************************************** */#define DAC8168_CMD_WRITE_REG   0x00#define DAC8168_CMD_UPDATE_REG   0x01#define DAC8168_CMD_WRTSELREG_UPDALL 0x02#define DAC8168_CMD_WRTSELREG_UPDRESP 0x03#define DAC8168_CMD_PWRDOWN    0x04#define DAC8168_CMD_WRITE_TO_CC_REG  0x05#define DAC8168_CMD_WRITE_TO_LDAC_REG 0x06#define DAC8168_CMD_SOFTWARE_RESET  0x07#define DAC8168_CHANNEL_ADDR_A   0x00#define DAC8168_CHANNEL_ADDR_B   0x01#define DAC8168_CHANNEL_ADDR_C   0x02#define DAC8168_CHANNEL_ADDR_D   0x03#define DAC8168_CHANNEL_ADDR_E   0x04#define DAC8168_CHANNEL_ADDR_F   0x05#define DAC8168_CHANNEL_ADDR_G   0x06#define DAC8168_CHANNEL_ADDR_H   0x07#define DAC8168_CHANNEL_ADDR_ALL  0x0Fvoid Dac8168Send(uint8_t cmd,uint8_t channel, uint16_t data){ uint32_t spi_data = 0x00000000;  // pull LDAC line up SIU.GPDO[204].B.PDO = 1; spi_data = ((uint32_t)(cmd & 0x0F)) << 24; spi_data |= ((uint32_t)(channel & 0x0F)) << 20; spi_data |= ((uint32_t)(data & 0x3FFF)) << 6; SpiDrvrWrite32(0x0, spi_data);  // pull down LDAC to load new value to DAC output SIU.GPDO[204].B.PDO = 0; //TODO: induce a sleep and drive the line back high return;}int main(void) { volatile int i = 0; //initialise peripherals & pll initSysclk(FMPLL_MHZ_INDEX); initDSPI_B(); //initialise dac  //Dac8168Send(DAC8168_CMD_SOFTWARE_RESET, DAC8168_CHANNEL_ADDR_ALL, 0x0FFFu); Dac8168Send(DAC8168_CMD_WRTSELREG_UPDALL, DAC8168_CHANNEL_ADDR_ALL, 0x0FFFu); /* Loop forever */ for (;;) {  //Dac8168Send(DAC8168_CMD_WRTSELREG_UPDALL, DAC8168_CHANNEL_ADDR_ALL, 0x0FFFu); //i++; }}

 

0 件の賞賛
返信
4 返答(返信)

1,829件の閲覧回数
VaisakhPS
Contributor I

In waveform captures,

 

000.png: channel 1 is chip select & channel 2 is clock

001.png: channel 1 is chip select & channel 2 is clock & channel 3 is data

002.png: channel 1 is chip select & channel 2 is clock & channel 3 is data

 

 zommed view of waveform are available in the bottom part of each capture. 

 

As you can see there is momentary transition in clock and chip select lines after the 16-bit boundary. How do i resolve this?

 

Regards,

Vaisakh P S

0 件の賞賛
返信

1,829件の閲覧回数
TomE
Specialist II

A quick scan through the MCP5646 manual I have here shows timing diagrams like you're seeing in the sections:

 

Figure 28-40. Continuous SCK Timing Diagram (CONT=0)

Figure 28-41. Continuous SCK Timing Diagram (CONT=1)

 

Read through those sections to see if anything you're doing matches any of the warnings in there (like FIFO Underrun).

 

Tom

 

0 件の賞賛
返信

1,829件の閲覧回数
VaisakhPS
Contributor I

I found something similar in a errata document for MPC5567 for SPI.

 

Check errata:  e1103 in  http://cache.freescale.com/files/32bit/doc/errata/MPC5567BCE.pdf. It is saying that the next block to be transferred should be wriiten in to FIFO before the previous one is shifted out.

 

I am exploring on this point now

 

Regards,

Vaisakh P S

0 件の賞賛
返信

1,829件の閲覧回数
TomE
Specialist II

> It is saying that the next block to be transferred should be wriiten in to FIFO before the previous one is shifted out.

 

I don't think it says that.

 

It says:

 

If the CONT bit is set with the first PUSHR write, the PCS de-asserts after the transfer because the configuration data for the next frame has already been fetched from the next (empty) fifo entry. This behavior continues till the buffer is filled once and all CONT bits are one.

The tenses are a little tricky, but I read that to say "When you write the first command, it is ALREADY TOO LATE to write the second one, because the controller will have noticed there is no second one when you wrote the first.

 

Your code pushes two words into the FIFO about as fast as it can, but that isn't fast enough.

 

The errata also says:

 

When the DSPI module has more than one entry in the TX FIFO and only one entry is written

 

That implies "greater than one and one" which doesn't make much sense.

 

it looks like you have to write the FIFO with the SPI not enabled, then enable it, but I don't think that works.

 

Maybe what you need to do is to write THREE words to the FIFO. The first being a "dummy command" to write data to an unused chip-select (via a different CTAR). That should give you enough time to write the REAL two words (being the 32-bits you want to transfer) into the FIFO. Make sure all interrupts are disabled when writing those three words, or another interrupt might get in between them.

 

Tom

 

0 件の賞賛
返信