This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
您好,
我目前在使用 DSP (TMS320F28335) 與 FPGA板子 (PYNQ-Z2) 用 spi 通訊作溝通。
希望能夠以 DSP 作為 master 傳送浮點數數值 (例如: 0.12 0.121 0.122 ......) 到 作為 slave 的 FPGA ,但在測試時 FPGA 接收到的值有些會有錯誤。
原先猜測是會多一個0在最前面 (以2進制表示時),像是我原先要傳 1111111111111111 結果會變成 0111111111111111, 多的1會被推到下一列,試著手動全部往前推一位後仍然會一些值是錯的,
想知道這個問題是什麼導致的,以及該如何修正。
以下是往後移一位之後的部分結果 (紅色字為有嚴重錯誤):
0.120 -> 0.11951171606779099
0.121 -> 0.12099999934434891
0.122 -> 0.12200000137090683
0.123 -> 0.12300000339746475
0.124 -> 0.12399999797344208
0.125 -> 0.1259765774011612
0.126 -> 0.12502342462539673
0.127 -> 0.12797658145427704
0.128 -> 0.12702342867851257
0.129 -> 0.12997658550739288
0.130 -> 0.12902343273162842
......
另外,DSP這邊是以範例:
來做更改的,以下是我更改過的程式碼:
#include "DSP28x_Project.h" // Device Headerfile and Examples Include File //#include "DSP2833x_Device.h" // // Function Prototypes // //__interrupt void ISRTimer2(void); void delay_loop(void); void spi_xmit(Uint16 a); void spi_fifo_init(void); void spi_init(void); void error(void); union datatype{ float f_type; Uint16 u_type[2]; }; union datatype sdata; union datatype rdata; char data_switch=0; // // Main // void main(void) { sdata.f_type = 0.12; // // Step 1. Initialize System Control: // PLL, WatchDog, enable Peripheral Clocks // This example function is found in the DSP2833x_SysCtrl.c file. // InitSysCtrl(); // // Step 2. Initialize GPIO: // This example function is found in the DSP2833x_Gpio.c file and // illustrates how to set the GPIO to it's default state. // // InitGpio(); // Skipped for this example // // Setup only the GP I/O only for SPI-A functionality // This function is found in DSP2833x_Spi.c // InitSpiaGpio(); // // Step 3. Clear all interrupts and initialize PIE vector table: // Disable CPU interrupts // DINT; // // Initialize PIE control registers to their default state. // The default state is all PIE interrupts disabled and flags // are cleared. // This function is found in the DSP2833x_PieCtrl.c file. // InitPieCtrl(); // // Disable CPU interrupts and clear all CPU interrupt flags: // IER = 0x0000; IFR = 0x0000; // // Initialize the PIE vector table with pointers to the shell Interrupt // Service Routines (ISR). // This will populate the entire table, even if the interrupt // is not used in this example. This is useful for debug purposes. // The shell ISR routines are found in DSP2833x_DefaultIsr.c. // This function is found in DSP2833x_PieVect.c. // InitPieVectTable(); // // Step 4. Initialize all the Device Peripherals: // This function is found in DSP2833x_InitPeripherals.c // // InitPeripherals(); // Not required for this example spi_fifo_init(); // Initialize the Spi FIFO spi_init(); // init SPI // // Step 5. User specific code: // // // Interrupts are not used in this example. // int count = 0; for(;;) { if(count < 100) { spi_xmit(sdata.u_type[data_switch]); while(SpiaRegs.SPIFFRX.bit.RXFFST !=1) { } rdata.u_type[data_switch] = SpiaRegs.SPIRXBUF; if(data_switch==0) { data_switch=1; } else { sdata.f_type = sdata.f_type + 0.001; count ++; data_switch=0; } delay_loop(); } } } // // delay_loop - Step 7. Insert all local Interrupt Service Routines (ISRs) and // functions here: // void delay_loop() { long i; for (i = 0; i < 1000000; i++) { } } // // error - // void error(void) { __asm(" ESTOP0"); // Test failed!! Stop! for (;;); } // // spi_init - // void spi_init() { SpiaRegs.SPICCR.all =0x000F; // Reset on, rising edge, 16-bit char bits // // Enable master mode, normal phase, enable talk, and SPI int disabled. // SpiaRegs.SPICTL.all =0x0006; SpiaRegs.SPIBRR =0x007F; SpiaRegs.SPICCR.all =0x008F; // Relinquish SPI from Reset SpiaRegs.SPIPRI.bit.FREE = 1; // Set so breakpoints don't disturb xmission } // // spi_xmit - // void spi_xmit(Uint16 a) { SpiaRegs.SPITXBUF=a; } // // spi_fifo_init - // void spi_fifo_init() { // // Initialize SPI FIFO registers // SpiaRegs.SPIFFTX.all=0xE040; SpiaRegs.SPIFFRX.all=0x204f; SpiaRegs.SPIFFCT.all=0x0; }
再麻煩替小弟我解惑了!!
您好,有確認過FPGA跟DSP兩邊的的設定,都是設定為 clock polarity = 0, clock phase = 0,這幾天有修改FPGA部分的程式,雖然多一個0的問題仍存在,但暫時可以取得正確的數值了,可以的話還是希望能夠解決這個問題。
另外,有發現FPGA回傳給DSP的值同樣會有問題,需要經過循環位移的方式才會得到正確的值,例如:
FPGA原先要傳 0, 1, 2, 3, 4, ...., 32768, 32769, 32770, 32771, ....
DSP這邊會收到 0, 2, 4, 6, 8, ...., 1, 3, 5, 7, ....
經過以下計算後DSP才會得到正確的值:
result = (val << (16 - 1) | (val >> 1)); // val 為DSP收到的值。
不知道這兩個問題是不是同一個問題產生的,或是彼此之間有關聯性?
您好,
有確認過FPGA跟DSP兩邊的的設定,都是設定為 clock polarity = 0, clock phase = 0,
这就是我们在强调的,这些设置可能在 FPGA 和 MCU 之间有完全不同的实现方式。 还请您仔细查看 TRM。 一个时钟极性=时钟相位= 0会导致之后的时序,即数据在时钟的上升沿切换,采样在时钟的下降沿。 这是否是 FPGA 所期望的?
不好意思,過了這麼久才回覆,因為有其他的進度暫時擱置了。
這幾天回去檢查兩邊 TRM 後發現兩邊對於clock polarity, clock phase 的定義不一樣,
FPGA 的 clock polarity=0 為 DSP 的 clock polarity=1 調整過後,接收的值都正常了。