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.
大家好!
我无法配置 SPI 3线模式、即简单地向 SPI 从器件发送3个字节。
已正确配置 GPIO:
SysCtrlRegs.PCLKCR0.bit.SPIAENCLK = 1; // SPI-A //-------------------------------------------------------------------------------------- // GPIO-16 - PIN FUNCTION = SPISIMO-A GpioCtrlRegs.GPAPUD.bit.GPIO16 = 0; // Enable pull-up on GPIO16 (SPISIMOA) GpioCtrlRegs.GPAQSEL2.bit.GPIO16 = 3; // Asynch input GPIO16 (SPISIMOA) GpioCtrlRegs.GPAMUX2.bit.GPIO16 = 1; // 0=GPIO, 1=SPISIMO-A, 2=Resv, 3=TZ2 //-------------------------------------------------------------------------------------- // GPIO-17 - PIN FUNCTION = SPISOMI-A (as GPIO not needed in 3-wire mode) GpioCtrlRegs.GPAMUX2.bit.GPIO17 = 0; // 0=GPIO, 1=SPISOMI-A, 2=Resv, 3=TZ3 GpioCtrlRegs.GPADIR.bit.GPIO17 = 1; // 1=OUTput, 0=INput GpioDataRegs.GPACLEAR.bit.GPIO17 = 1; // uncomment if --> Set Low initially //-------------------------------------------------------------------------------------- // GPIO-18 - PIN FUNCTION = SPICLK-A GpioCtrlRegs.GPAPUD.bit.GPIO18 = 0; // Enable pull-up on GPIO18 (SPICLKA) GpioCtrlRegs.GPAQSEL2.bit.GPIO18 = 3; // Asynch input GPIO18 (SPICLKA) GpioCtrlRegs.GPAMUX2.bit.GPIO18 = 1; // 0=GPIO, 1=SPICLK-A, 2=SCITX-A, 3=XCLKOUT //-------------------------------------------------------------------------------------- // GPIO-19 - PIN FUNCTION = SPISTE-A GpioCtrlRegs.GPAPUD.bit.GPIO19 = 0; // Enable pull-up on GPIO19 (SPISTEA) GpioCtrlRegs.GPAQSEL2.bit.GPIO19 = 3; // Asynch input GPIO19 (SPISTEA) GpioCtrlRegs.GPAMUX2.bit.GPIO19 = 1; // 0=GPIO, 1=SPISTE-A, 2=SCIRX-A, 3=ECAP1 //--------------------------------------------------------------------------------------
然后、我为 TX 用3个级别初始化 FIFO、我不需要 RX (也许是肯定的?):
void spi_fifo_init() { // Initialize SPI FIFO registers //SpiaRegs.SPIFFTX.all=0xE040; SpiaRegs.SPIFFTX.bit.SPIRST=1; //SPI FIFO can resume transmit or receive SpiaRegs.SPIFFTX.bit.SPIFFENA=1; //SPI FIFO enhancements are enabled SpiaRegs.SPIFFTX.bit.TXFFINTCLR =1; // Clear TXFIFO interrupt flag SpiaRegs.SPIFFTX.bit.TXFFIENA = 0; // TXFIFO interrupt disabled SpiaRegs.SPIFFTX.bit.TXFFIL =3; //3 levels for TXFIFO Interrupt (no needed) SpiaRegs.SPIFFTX.bit.TXFIFO =1; //Release transmit FIFO from reset. //SpiaRegs.SPIFFRX.all=0x2044; SpiaRegs.SPIFFRX.bit.RXFFOVFCLR = 1; // CLEAR OV rX flag SpiaRegs.SPIFFRX.bit.RXFFINTCLR =1; //b6 Clear SPIFFRX flag SpiaRegs.SPIFFRX.bit.RXFFIENA = 0; //b5 RXFIFO interrupt disabled SpiaRegs.SPIFFRX.bit.RXFFIL=0; //level bits for RXFIFO Interrupt (no needed) SpiaRegs.SPIFFRX.bit.RXFIFORESET = 1; //b13 Re-enable receive FIFO operation. SpiaRegs.SPIFFCT.all=0x0; //The next word in the TX FIFO buffer is transferred to //SPITXBUF immediately upon completion of transmission of the //previous word. }
然后 SPI 初始化:
void spi_init_DAC70501() { //SpiaRegs.SPICCR.all =0x000F; // Reset on, rising edge, 16-bit char bits //SpiaRegs.SPICTL.all =0x0006; // Enable master mode, normal phase, // enable talk, and SPI int disabled. SpiaRegs.SPICCR.bit.SPISWRESET = 0; //Reset SPI before configuration SpiaRegs.SPICCR.bit.CLKPOLARITY =1; //falling edge SpiaRegs.SPICCR.bit.SPICHAR =7; //8-bit char bits SpiaRegs.SPICTL.bit.MASTER_SLAVE=1; //Enable master mode SpiaRegs.SPICTL.bit.CLK_PHASE=1; // phase with delay SpiaRegs.SPICTL.bit.TALK = 1; // Enable Transmit path SpiaRegs.SPICTL.bit.OVERRUNINTENA = 0; //disbale overrun interruption SpiaRegs.SPICTL.bit.SPIINTENA = 0; ////disable SPIinterruption SpiaRegs.SPIBRR =127; // SPI Baud Rate=LSPCLK/(SPIBRR+1) LSPCLK=CPU_FREQ/4 // 15MHz/(127+1)=117kHz // 15MHz/(14+1)=1MHz SpiaRegs.SPIPRI.bit.TRIWIRE=1; //3-wire SPI mode enable //(The unused pin SPISOMI is free for GPIO) //SpiaRegs.SPICCR.all =0x009F; // Relinquish SPI from Reset SpiaRegs.SPICCR.bit.SPISWRESET = 1; // Relinquish SPI from Reset SpiaRegs.SPIPRI.bit.FREE = 1; // Set so breakpoints don't disturb xmission }
最后、这是我将 在主程序中定期调用的 TX 函数:
/********************************************************************** * Function: spi_xmit() * * Description: Transmit 16bit to SPIA using 3-Wire Mode Transmit * When the master transmits, it receives the data it * transmits (because SPISIMOx and SPISOMIx are connected * internally in 3-wire mode). Therefore, the junk data received * must be cleared from the receive buffer every time data is transmitted. **********************************************************************/ void spi_xmit(char a) { Uint16 data= (Uint16)(a<<8); Uint16 dummy; SpiaRegs.SPICTL.bit.TALK = 1; // Enable Transmit path SpiaRegs.SPITXBUF = data; // Master transmits data while(SpiaRegs.SPISTS.bit.INT_FLAG !=1) {} // Waits until data rx’d dummy = SpiaRegs.SPIRXBUF; // Clears junk data from itself SpiaRegs.SPITXBUF = data; // Master transmits data while(SpiaRegs.SPISTS.bit.INT_FLAG !=1) {} // Waits until data rx’d dummy = SpiaRegs.SPIRXBUF; // Clears junk data from itself SpiaRegs.SPITXBUF = data; // Master transmits data while(SpiaRegs.SPISTS.bit.INT_FLAG !=1) {} // Waits until data rx’d dummy = SpiaRegs.SPIRXBUF; // Clears junk data from itself }
我可以在示波器中检查第一个字节已发送、但之后通信会被阻止。
如果没有3线制模式或 FIFO、我就能够顺利发送2个字节(没有阻塞)。
我做错了什么? 通过 SPI 向外部从器件发送3个字节的正确方法是什么?
提前感谢。
此致
您好!
如果您说通信被"阻止"、您是说代码卡在"while"循环中、等待 INT_flag 设置为1吗? 或者、您能否详细说明一下含义?
您是否还能提供一些示波器捕获 SPI 线路上的行为、以便我们可以查看该行为?
艾里森
尊敬的 Allison:
是的、您答对了、分块是由于行:
while (SpiaRegs.SPISTS.bit.INT_flag!=1){}//等待数据接收
删除它后、我可以看到3个字节已正确发送。
void spi_xmit(char a) { SpiaRegs.SPICTL.bit.TALK = 1; // Enable Transmit path SpiaRegs.SPITXBUF = (Uint16)(0x03<<8); // Master transmits data dummy = SpiaRegs.SPIRXBUF; // Clears junk data from itself SpiaRegs.SPITXBUF = (Uint16)(0x01<<8); // Master transmits data dummy = SpiaRegs.SPIRXBUF; // Clears junk data from itself SpiaRegs.SPITXBUF = (Uint16)(0x00<<8); // Master transmits data dummy = SpiaRegs.SPIRXBUF; // Clears junk data from itself }
数据(红色)和时钟(蓝色)
SPISTE 线路(红色)和时钟(蓝色)。
看起来现在是正确发送3个字节。 但是、DAC (SPI 从器件)似乎没有反应。 可以是 SPI 的极性和相位吗? 从 DAC 规格来看、我认为它是带延迟的下降沿。 可能是错了吗?
感谢您的帮助
此致
您好!
很高兴听到数据似乎正在正确发送! 简单解释一下:
通常、最佳做法是检查其中之一(取决于您处于 FIFO 模式还是非 FIFO 模式)、以 确保传输不会被覆盖/损坏
至于时钟、从您所连接的图像来看、我觉得数据会在时钟的上升沿传输并在时钟的下降沿锁存、 这表明 F28027时钟极性应该为0、相位应该为0。 从器件 TRM 第8.3.6节 SPI 时钟方案中、这将是 "无延迟的上升沿。 SPI 在 SPICLK 信号的上升沿上发送数据、而在 SPICLK 信号的下降沿上接收数据。' 请告诉我使用时钟模式是否会改变行为!
此致、
艾里森
尊敬的 Allison:
您对时钟极性和相位没有任何疑问。 它现在与"无延迟的上升沿"一起工作非常完美。
关于 SPI 配置、我会复制并粘贴我的最终配置、以帮助其他用户、并澄清一些疑问。 我的目标是作为主器件向 SPI 从器件(在本例中为 DAC 70501)传输3个字节:
配置 SPI 引脚并启用 SPI 时钟
GPIO 配置为 SPI 3线(GPIO-17免费用于其他用途) :
GPIO-16 - PIN 功能= SPISIMO-A
-GPIO-18 - PIN 功能= SPICLK-A
- GPIO-19 - PIN 功能= SPISTE-A
SPI FIFO 配置:
/********************************************************************** * Function: spi_fifo_init_DAC70501() * * Description: Sets the SPI fifo configuration for the DAC70501 * - Enable FIFO enhancement * - No interruptions **********************************************************************/ void spi_fifo_init_DAC70501() { // Initialize SPI FIFO registers //SpiaRegs.SPIFFTX.all=0xE040; SpiaRegs.SPIFFTX.bit.SPIRST=1; //SPI FIFO can resume transmit or receive SpiaRegs.SPIFFTX.bit.SPIFFENA=1; //SPI FIFO enhancements are enabled SpiaRegs.SPIFFTX.bit.TXFFINTCLR =1; // Clear TXFIFO interrupt flag SpiaRegs.SPIFFTX.bit.TXFFIENA = 0; // TXFIFO interrupt disabled SpiaRegs.SPIFFTX.bit.TXFFIL =0; //levels for TXFIFO Interrupt (no needed) SpiaRegs.SPIFFTX.bit.TXFIFO =1; //Release transmit FIFO from reset. //SpiaRegs.SPIFFRX.all=0x2044; SpiaRegs.SPIFFRX.bit.RXFFOVFCLR = 1; // CLEAR OV rX flag SpiaRegs.SPIFFRX.bit.RXFFINTCLR =1; //b6 Clear SPIFFRX flag SpiaRegs.SPIFFRX.bit.RXFFIENA = 0; //b5 RXFIFO interrupt disabled SpiaRegs.SPIFFRX.bit.RXFFIL=0; //level bits for RXFIFO Interrupt (no needed) SpiaRegs.SPIFFRX.bit.RXFIFORESET = 1; //b13 Re-enable receive FIFO operation. SpiaRegs.SPIFFCT.all=0x0; //The next word in the TX FIFO buffer is transferred to //SPITXBUF immediately upon completion of transmission of the //previous word. }
SPI 配置:
/********************************************************************** * Function: spi_init_DAC70501() * * Description: Initializes spi on the piccolo for DAC70501 SPI specs * - CLOCK polarity and Phase: * data is being transmitted on the rising edge of the clock and latched * on the falling edge of the clock, which would indicated that the F28027 * clock polarity should be 0 and phase should be 0. * From the device TRM section 8.3.6 SPI Clocking Schemes, this would be * "Rising Edge Without Delay. * The SPI transmits data on the rising edge of the SPICLK signal and * receives data on the falling edge of the SPICLK signal." * - 8 bit char--> each transmitted word is configured to be a byte (8 bits) * - 3-wire SPI mode enable: * When the master transmits, it receives the data it * transmits (because SPISIMOx and SPISOMIx are connected * internally in 3-wire mode). Therefore, the junk data received * must be cleared from the receive buffer every time data is transmitted. * GPIOs are initialised in Gpio.c and CLOCKs in InitSysCtrl() **********************************************************************/ void spi_init_DAC70501() { //SpiaRegs.SPICCR.all =0x000F; // Reset on, rising edge, 16-bit char bits //SpiaRegs.SPICTL.all =0x0006; // Enable master mode, normal phase, // enable talk, and SPI int disabled. SpiaRegs.SPICCR.bit.SPISWRESET = 0; //Reset SPI before configuration SpiaRegs.SPICCR.bit.CLKPOLARITY =0; //rising edge SpiaRegs.SPICCR.bit.SPICHAR =7; //8-bit char bits SpiaRegs.SPICTL.bit.MASTER_SLAVE=1; //Enable master mode SpiaRegs.SPICTL.bit.CLK_PHASE=0; // phase without delay SpiaRegs.SPICTL.bit.TALK = 1; // Enable Transmit path SpiaRegs.SPICTL.bit.OVERRUNINTENA = 0; //disbale overrun interruption SpiaRegs.SPICTL.bit.SPIINTENA = 0; ////disable SPIinterruption SpiaRegs.SPIBRR =14; // SPI Baud Rate=LSPCLK/(SPIBRR+1) LSPCLK=CPU_FREQ/4 // 15MHz/(127+1)=117kHz // 15MHz/(14+1)=1MHz SpiaRegs.SPIPRI.bit.TRIWIRE=1; //3-wire SPI mode enable //(The unused pin SPISOMI is free for GPIO) //SpiaRegs.SPICCR.all =0x009F; // Relinquish SPI from Reset SpiaRegs.SPICCR.bit.SPISWRESET = 1; // Relinquish SPI from Reset SpiaRegs.SPIPRI.bit.FREE = 1; // Set so breakpoints don't disturb xmission
3. SPI 传输功能:
/********************************************************************** * Function: DAC70501_setVoltage_SPI() * * Description: Sets the output voltage to a fraction of source vref. (Value can be 0..16383 (0-0x3FFF)) output: The 14-bit value representing the relationship between the DAC's input voltage and its output voltage. **********************************************************************/ void DAC70501_setVoltage_SPI(uint16_t output) { uint16_t data; uint16_t dummy; data = (uint16_t)(output<<2); //shift to the left DAC_data reads 14bits left-aligned char byte1=DAC70501_DAC_DATA; //command value in this case 0x08 char byte2=(char) ((data >> 8) & 0xFF);// DAC DATA MSB char byte3=(char) (data); SpiaRegs.SPITXBUF = (Uint16)(byte1<<8); // Master transmits data dummy = SpiaRegs.SPIRXBUF; // Clears junk data from itself SpiaRegs.SPITXBUF = (Uint16)(byte2<<8); // Master transmits data dummy = SpiaRegs.SPIRXBUF; // Clears junk data from itself SpiaRegs.SPITXBUF = (Uint16)(byte3<<8); // Master transmits data dummy = SpiaRegs.SPIRXBUF; // Clears junk data from itself while(SpiaRegs.SPIFFRX.bit.RXFFST !=1) {} }
在最后一个函数中、是对 SPIFFRX 的检查。 可以删除 RXFFST 位、以及以下行:
"虚拟= SpiaRegs. SPIRXBUF;//自行清除无用数据"
我不知道为什么、但在没有这些线路的情况下、SPI 传输功能工作正常。 我还在 示波器中检查 SPISTE 线路、它运行良好、在3字节传输前设置为低电平、在3字节传输后立即设置为高电平。
这是我不理解的:
MCU 如何识别它必须仅传输3个字节? 我刚刚将 SPICHAR 配置为8位字符位、但未将 FIFO 级别设置为任何。
此致