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.

[参考译文] CCS/TM4C123GH6PM:Tiva TM4C123GXL 中的 SSI (SPI)通信

Guru**** 2538930 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/889400/ccs-tm4c123gh6pm-the-ssi-spi-communication-in-tiva-tm4c123gxl

器件型号:TM4C123GH6PM

工具/软件:Code Composer Studio

您好!

我正在尝试使用 Tiva C TM4C123GXL Launchpad 中存在的 SSI (SPI)协议来实现 LaunchPad 到 LaunchPad 的通信。  

我正在将一个 LaunchPad 配置为主模式、将另一个配置为从模式。 主机和从机都使用 SSI0进行配置。  

我的概念是、当我在主器件侧按下开关时、数据应从主器件传输到从器 件、并应在 PC 的串行监视器上打印、此部件工作正常。 同样、当我按下开关从端时、数据应该从从从端传输到主器件、并且应该在 PC 的串行监视器上打印、但这不是发生的。 有趣的是、从器件发送到主器件的数据在从主器件到从器件的数据传输过程中打印在串行监视器上。  

正如我在数据表中看到的、主器件只应启动从器件到主器件的数据传输。 我不知道如何做到这一点。 请尽快解决我的问题。 我还附上了主设备和从设备代码供您参考。

/*主设备*/
#include
#include
#include "inc/hw_memmap.h"
#include "inc/hw_ints.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/ssi.h"
#include "driverlib/sysctl.h"
#include "driverlib/interrupt.h"
#include "driverlib/uart.h"
#include "uartstdio.h"
#define NUM_SSI_DATA       3.
uint32_t pui32DataTx[NUM_SSI_DATA];
uint32_t pui32DataRx[NUM_SSI_DATA];
uint32_t ui32Index;
空 SSI0_MASTER_Interrupt (空)
uint32_t ui32Status;
ui32Status=SSIIntStatus (SSI0_BASE、1);
UARTprintf ("内部状态为 %i\n"、ui32Status);
IF (ui32Status & SSI_RXFF|SSI_RXTO)
    for (ui32Index=0;ui32Index < NUM_SSI_DATA;ui32Index++)
    {
    SSIDataGet (SSI0_BASE、&pui32DataRx[ui32Index]);
    UARTprintf ("%c"、pui32DataRx[ui32Index]);
    }
    UARTprintf ("\n");
SSIIntClear (SSI0_BASE、SSI_RXFF|SSI_RXTO|SSI_RXOR);
空 InitConsole (空)
  SysCtlPeripheralEnable (SYSCTL_Periph_GPIOA);//启用 UART0 GPIO 外设
SysCtlPeripheralEnable (SYSCTL_Periph_UART0);
GPIOPinConfigure (GPIO_PA0_U0RX);
GPIOPinConfigure (GPIO_PA1_U0TX);
GPIOPinTypeUART (GPIO_Porta_base、GPIO_PIN_0 | GPIO_PIN_1);
UARTStdioConfig (0、9600、SysCtlClockGet ());
int main (空)
  SysCtlClockSet (SYSCTL_SYSDIV_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHz);
  InitConsole();
  UARTprintf ("SSI 主机->\n");
  UARTprintf (" 模式:SPI\n");
  UARTprintf (" 数据:8位\n");
  SysCtlPeripheralEnable (SYSCTL_Periph_GPIOF);
  GPIOPinTypeGPIOInput (GPIO_PORTF_BASE、GPIO_PIN_4);
  GPIOPadConfigSet (GPIO_PORTF_BASE、GPIO_PIN_4、GPIO_Strength _4mA、GPIO_PIN_TYPE_STD_WPU);
  SysCtlPeripheralEnable (SYSCTL_Periph_SSI0);
  SysCtlPeripheralEnable (SYSCTL_Periph_GPIOA);
  GPIOPinTypeSSI (GPIO_Porta_base、GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_3 |GPIO_PIN_2);
  GPIOPinConfigure (GPIO_PA2_SSI0CLK);
  GPIOPinConfigure (GPIO_PA3_SSI0FSS);
  GPIOPinConfigure (GPIO_PA4_SSI0RX);
  GPIOPinConfigure (GPIO_PA5_SSI0TX);
  SSIConfigSetExpClk (SSI0_BASE、SysCtlClockGet ()、SSI_FRF_MOTO_MOTO_3、SSI_MODE_MASTER、4000000、8);
  SSIEnable (SSI0_BASE);
  SSIIntRegister (SSI0_BASE、SSI0_MASTER_Interrupt);
  IntEnable (INT_SSI0);
  SSIIntEnable (SSI0_BASE、SSI_RXFF|SSI_RXTO);
  while (SSIDataGetNonBlocking (SSI0_BASE、&pui32DataRx[0]))
  {
  }
  SSIIntClear (SSI0_BASE、SSI_RXFF|SSI_RXTO);
  pui32DataTx[0]="S";
  pui32DataTx[1]='p';
  pui32DataTx[2]='I';
  while (SSIBusy (SSI0_BASE))
  {
  }
  while (1)
  {
if (!GPIOPinRead (GPIO_PORTF_BASE、GPIO_PIN_4))
  UARTprintf ("发送到从属设备的数据\n");
  for (ui32Index = 0;ui32Index < NUM_SSI_DATA;ui32Index++)
  {
  SSIDataPut (SSI0_BASE、pui32DataTx[ui32Index]);
  }
   SysCtlDelay (13333333/2);
  }
/*从属设备*/
#include
#include
#include "inc/hw_memmap.h"
#include "inc/hw_ints.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/ssi.h"
#include "driverlib/sysctl.h"
#include "driverlib/interrupt.h"
#include "driverlib/uart.h"
#include "uartstdio.h"
#define NUM_SSI_DATA       3.
uint32_t pui32DataTx[NUM_SSI_DATA];
uint32_t pui32DataRx[NUM_SSI_DATA];
uint32_t ui32Index;
volatile unsigned long g_ulSSI2RXTO = 0;
空 SSI0_SLAVE_Interrupt (空)
uint32_t ui32Status;
ui32Status=SSIIntStatus (SSI0_BASE、1);
UARTprintf ("内部状态为 %i\n"、ui32Status);
IF (ui32Status & SSI_RXFF|SSI_RXTO)
    for (ui32Index=0;ui32Index < NUM_SSI_DATA;ui32Index++)
    {
    SSIDataGet (SSI0_BASE、&pui32DataRx[ui32Index]);
    UARTprintf ("%c"、pui32DataRx[ui32Index]);
    }
 UARTprintf ("\n");
SSIIntClear (SSI0_BASE、ui32Status);
空 InitConsole (空)
  SysCtlPeripheralEnable (SYSCTL_Periph_GPIOA);//启用 UART0 GPIO 外设
SysCtlPeripheralEnable (SYSCTL_Periph_UART0);
GPIOPinConfigure (GPIO_PA0_U0RX);
GPIOPinConfigure (GPIO_PA1_U0TX);
GPIOPinTypeUART (GPIO_Porta_base、GPIO_PIN_0 | GPIO_PIN_1);
UARTStdioConfig (0、9600、SysCtlClockGet ());// 115200波特
int main (空)
SysCtlClockSet (SYSCTL_SYSDIV_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHz);
  uint32_t ui32clock= SysCtlClockGet ();
  InitConsole();
  UARTprintf ("SSI 从站->\n");
  UARTprintf (" 模式:SPI\n");
  UARTprintf (" 数据:8位\n");
  SysCtlPeripheralEnable (SYSCTL_Periph_GPIOF);
  GPIOPinTypeGPIOInput (GPIO_PORTF_BASE、GPIO_PIN_4);
  GPIOPadConfigSet (GPIO_PORTF_BASE、GPIO_PIN_4、GPIO_Strength _4mA、GPIO_PIN_TYPE_STD_WPU);
  SysCtlPeripheralEnable (SYSCTL_Periph_SSI0);
  SysCtlPeripheralEnable (SYSCTL_Periph_GPIOA);
  GPIOPinTypeSSI (GPIO_Porta_base、GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_3 |GPIO_PIN_2);
  GPIOPinConfigure (GPIO_PA2_SSI0CLK);
  GPIOPinConfigure (GPIO_PA3_SSI0FSS);
  GPIOPinConfigure (GPIO_PA4_SSI0RX);
  GPIOPinConfigure (GPIO_PA5_SSI0TX);
  SSIConfigSetExpClk (SSI0_BASE、SysCtlClockGet ()、SSI_FRF_MOTO_MOTO_3、SSI_MODE_SLAVE、4000000、8);
  SSIEnable (SSI0_BASE);
  SSIIntRegister (SSI0_BASE、SSI0_SLAVE_Interrupt);
  SSIIntEnable (SSI0_BASE、SSI_RXFF|SSI_RXTO);
  while (SSIDataGetNonBlocking (SSI0_BASE、&pui32DataRx[0]))
  {
  }
  SSIIntClear (SSI0_BASE、SSI_RXFF|SSI_RXTO);
  pui32DataTx[0]="S";
  pui32DataTx[1]='P';
  pui32DataTx[2]='I';
  while (SSIBusy (SSI0_BASE))
  {
  }
  IntEnable (INT_SSI0);
  while (1)
  {
  if (!GPIOPinRead (GPIO_PORTF_BASE、GPIO_PIN_4))
  {
   UARTprintf ("发送给主设备的数据\n");
    for (ui32Index = 0;ui32Index < NUM_SSI_DATA;ui32Index++)
    {
    SSIDataPut (SSI0_BASE、pui32DataTx[ui32Index]);
    }
    SysCtlDelay (13333333/2);
  }
  }

 

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您的读取正确、SPI 从器件无法启动传输。 您必须让 SPI 主器件持续传输虚拟数据并检查从器件的有效返回数据、或者在两个电路板之间添加另一个信号。 从器件到主器件输入的数字输出、可生成中断或轮询以指示从器件有新数据要发送。

    如果您需要独立的双向通信、请考虑改用 UART。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    我们的小型技术团队同意供应商的 Bob -但(也许)此海报有(有效)理由寻求基于 SPI 的解决方案。   (和"那"-需要解释...)

    如果情况确实如此-我们的团队成功实施了两个基于 SPI 的 MCU (每个 MCU)能够切换到"主模式"。   (当然-"一次只有一个"担任硕士。)

    此"多主器件"SPI 实施方案的关键设计元素包括:

    • 两个 MCU 默认为从模式
    • 除了4个"正常" SPI 互连外、我们总共添加了2条 GPIO 线-这样(任一) MCU 就会向另一条发出"切换到主模式"( 并很快将传递"命令控制"消息)的警报
    • 消息完成后、"Master MCU"会恢复为从模式。  (接收 MCU 将唯一地对其 GPIO 输出线路进行脉冲以确认"消息接收"。)

    这种方法的优点是(任一) MCU 可以随时发起通信。   事实证明、(从不)两个 MCU 都能够"切换到主模式"且存在任何重叠至关重要。   (因为这可能会在(每个) MCU 的 SPI 时钟线路上产生破坏性的"输出争用"!)

    此外、我们还研究了"基于时间的乒乓方式启用主设备"。   (这"节省了"上述"警报 GPIO "的使用、但需要在 MCU 之间定期进行"时钟同步")  这种方法也成功了、但添加了"响应延迟"、因此被旁路为"警报/信令" GPIO。

    如前所述-除非"对 SPI 的需求得到证明(否则)合理"-否则不建议使用此"解决方案"(尽管它有效)!   (由于复杂性...)

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    它现在正在工作。 谢谢你。  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Bob Crosby、感谢您解决我的疑问。 您所说的方法现在很简单、可以正常工作。