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.

[参考译文] EK-TM4C1294XL:SPI-read 故障- uC 行为不稳定、示波器上的信号似乎正常

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1254378/ek-tm4c1294xl-trouble-with-spi-read---erratic-behavior-of-the-uc-signal-on-scope-seems-okay

器件型号:EK-TM4C1294XL

尊敬的团队:

我在为模拟器件 ADE7913 ADC 编写 SPI 驱动器时遇到困难。 从 SSI 资源中读取值会产生奇怪的行为、我无法解释、但示波器显示了写入 MISO 行的预期值。 我将首先浏览软件步骤、描述问题并包括一些屏幕截图、然后提供最低限度的工作示例。 非常感谢任何帮助!

下面是代码的功能:

向 ADC 发出写入命令、指定要写入的寄存器:0x70

发送我们要写入寄存器的值:0xFF (我也尝试了其他值)。 该行为是相同的。)

3、向 ADC 发出读取命令、指定要读取的寄存器(与之前写入的相同):0x74

4.执行虚拟写入、以便 CS 和 SPI 时钟信号位于线路上:0x00

5.对 Tiva 执行一个读取命令并将 FIFO 内的数据写入一个变量

6.将变量和读取命令的状态打印到控制台

7.在1处重新启动循环

如示波器屏幕截图所示、ADC 发送正确的值作为对读取命令的响应- MISO 线路清楚地接收到0xFF:

但是、Tiva 只能在循环的 pass 4和 pass 8期间正确读取此值(255 = 0xFF)、随后不再:

下面是代码:

#包含
外部"C"
{
#包含
#包含
#include "inc/hw_memmap.h"
#include "inc/hw_ssi.h"
#include "inc/hw_types.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/ssi.h"



//*****
//
//以 Hz 为单位的系统时钟速率。
//
//*****
uint32_t g_ui32SysClock;

//*****
//
//驱动程序库遇到错误时调用的错误例程。
//
//*****
#ifdef 调试

__error__(char *pcFilename,uint32_t ui32Line)
{

#endif


//全局常量
constexpr uint32_t ssiBitsPerSecond = 250'000;
constexpr uint32_t ssiDataWidthInBits = 8;//必须介于4和16之间


//全局变量
int SSIreadStatus =-1;
uint32_t data = 0xffffffff;


//函数
void spiInit (void)
{
   //使能 SSI 外设
   SysCtlPeripheralEnable (SYSCTL_Periph_SSI1);

   //启用 GPIO 端口
   SysCtlPeripheralEnable (SYSCTL_Periph_GPIOB);
   SysCtlPeripheralEnable (SYSCTL_Periph_GPIOE);

   //为 SSI1配置 GPIO 引脚多路复用器
   GPIOPinConfigure (GPIO_PB5_SSI1CLK);
   GPIOPinConfigure (GPIO_PB4_SSI1FSS);
   GPIOPinConfigure (GPIO_PE4_SSI1XDAT0);
   GPIOPinConfigure (GPIO_PE5_SSI1XDAT1);

   //配置 SSI 引脚的 GPIO 设置。 此功能还中继了
   //将这些引脚控制到 SSI 硬件。
   GPIOPinTypeSSI (GPIO_PORTB_BASE、GPIO_PIN_4 | GPIO_PIN_5);
   GPIOPinTypeSSI (GPIO_Port_BASE、GPIO_PIN_4 | GPIO_PIN_5);

   //配置并启用 SPI 主模式的 SSI1端口
   SSIConfigSetExpClk (SSI1_BASE、g_ui32SysClock、SSI_FRF_MOTO_MODE_3、
                      SSI_MODE_MASTER、ssiBitsPerSecond、ssiDataWidthInBits);

   //启用模块 SSI0、SSI1、SSI3。
   SSIEnable (SSI1_BASE);




int main (空)
{
   //以120 MHz 从 PLL 运行。
   //注意:SYSCTL_CFG_VCO_240是 TivaWare 2.2.x 和
   //稍后以更好地反映由于 SYSCTL#22而导致的实际 VCO 速度。
    g_ui32SysClock = MAP_SysCtlClockFreqSet ((SYSCTL_XTAL_25MHz |
                                            SYSCTL_OSC_MAIN |
                                            SYSCTL_USE_PLL |
                                            SYSCTL_CFG_VCO_240)、120000000);
    printf ("g_ui32SysClock =%d\n\n"、g_ui32SysClock);

   spiInit();

   int count = 0;

   while (1)
   {

       // SPI-Test:写入 ADE7912的 EMI_CTRL 寄存器。 然后从 ADE7912读取写入值。
       {
           SSIDataPut (SSI1_BASE、((0xE << 3)| 0b000));
           SSIDataPut (SSI1_BASE、0xFF);

           while (SSIBusy (SSI1_base))
           {
           }

           SSIDataPut (SSI1_BASE、((0xE << 3)| 0b100));
//           HWREG (SSI1_BASE + SSI_O_DR)=((0xE << 3)| 0b100);//寄存器级写入命令(与 TivaWare 相比)
           SSIDataPut (SSI1_BASE、0);//要在读取期间激活 SPI clk 和 CS~、需要二次写入。 可以写入任何值。
//           HWREG (SSI1_BASE + SSI_O_DR)=((0xE<< 3)| 0b000);

           SSIreadStatus = SSIDataGetNonBlocking (SSI1_base、&data);
//           data = HWREG (SSI1_BASE + SSI_O_DR);//在寄存器级读取命令(相比 TivaWare)

           printf ("Pass %d - EMI_CTRL 寄存器值:%d\n"、count、data);
           printf ("SSIreadStatus:%d\n\n"、SSIreadStatus);

           ++数量;
       }

       SysCtlDelay (g_ui32SysClock / 250 / 3);
   }

此时此刻我有点懒洋的。 有没有人知道我可能做错了什么?

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

    在我们的高级工程师帮助下、从今天的假期回来后、我们找到了一个解决方案:

    SSI 读取 FIFO 被 MISO 线上的所有内容填充、即三个0x00放在第一个0xFF 之前。 因此,这是前三个 SSIDataGet ()操作在达到所需值之前读取的内容。 为了每次都获得所需的值、需要先执行三次空读操作来将0x00从 FIFO 中清除。

    以下是工作代码(我只发布循环、其余代码保持不变):

       while (1)
       {

           // SPI-Test:写入 ADE7912的 EMI_CTRL 寄存器。 然后从 ADE7912读取写入值。
           {
               SSIDataPut (SSI1_BASE、((0xE << 3)| 0b000));
               SSIDataPut (SSI1_BASE、0xF0);

               while (SSIBusy (SSI1_base))
               {
               }

               SSIDataPut (SSI1_BASE、((0xE << 3)| 0b100));
    //           HWREG (SSI1_BASE + SSI_O_DR)=((0xE << 3)| 0b100);//寄存器级写入命令(与 TivaWare 相比)


               SSIDataPut (SSI1_BASE、0);//要在读取期间激活 SPI clk 和 CS~、需要二次写入。 可以写入任何值。
    //           HWREG (SSI1_BASE + SSI_O_DR)=((0xE<< 3)| 0b000);

               while (SSIBusy (SSI1_base))
               {
               }

               //虚拟读取以清除 FIFO 的前三个0x00条目
               HWREG (SSI1_BASE + SSI_O_DR);
               HWREG (SSI1_BASE + SSI_O_DR);
               HWREG (SSI1_BASE + SSI_O_DR);

               SSIDataGet (SSI1_base、&data);
    //           SSIreadStatus = SSIDataGetNonBlocking (SSI1_base、&data);
    //           data = HWREG (SSI1_BASE + SSI_O_DR);//在寄存器级读取命令(相比 TivaWare)

               printf ("Pass %d - EMI_CTRL 寄存器值:%d\n"、count、data);
               printf ("SSIreadStatus:%d\n\n"、SSIreadStatus);

               ++数量;
           }

           SysCtlDelay (g_ui32SysClock / 250 / 3);
       }