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.

[参考译文] TM4C1237H6PM:使用 TIvaware 进行 SPI 接收(时钟未运行)

Guru**** 2463330 points


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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/658392/tm4c1237h6pm-spi-receiving-using-tivaware-clock-not-running

器件型号:TM4C1237H6PM

你好

我尝试连接 MAX6675 (k-Type -数字转换器)“不需要 mosi” 和“在模式1下工作”  

首先、我尝试使用(ti\TivaWare_C_Series-2.1.4.178\examples\peripherals\SSI)中的 tivaware 示例  

(SPI_MASTER.c)在发送时工作良好、但在接收时 似乎无法正常工作、我尝试对 TX 部件进行环路、在示波器上一切工作正常、但当尝试对 Rx 部件进行环路时、不会生成时钟、并且 CS 始终处于高电平  

我想尝试(SOFT_SPI_MASTER.c)、TX 和 Rx 上的一切都正确、因此硬件问题是什么  

注意:我根本没有修改代码、只需使用 while (1)观察示波器上的信号

谢谢

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好 Samir、
    您尝试"循环 Rx 部件"的意思是什么? 运行示例时、硬件设置是什么? 运行示例时、您是否已将 MAX6675连接到 MCU? MCU 是主设备。 即使在接收模式下、MCU 也必须生成 SPICLK。 为了使主器件生成时钟、即使您不需要向从器件发送数据、您仍然需要在 MOSI 上生成虚拟写入。 从器件可以忽略 MOSI 上传输的数据。 但是、当从器件看到 SPICLK 时、它会将 MISO 上的数据返回到主器件。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    是的、它始终使用具有3.3V 和 GND 的 ssi0引脚(PA2-PA3-PA4)进行连接
    通过循环、我意味着我在 while (1)中有循环接收、但奇怪的是接收 现在在我使用无阻塞功能时工作、但现在发生了另一件奇怪的事情、就是最大6675 返回的值始终相同、除非我重新上传代码、如果电路板处于休息状态、则不会 提供任何输出
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    在发送过程中 CS (SSI0FSS)引脚是否为低电平有效? 请显示您的示波器上限和修改后的代码。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    //
    //
    // spi_master.c -演示如何在 SPI 主设备//中配置 SSI0的示例
    模式。
    //
    //版权所有(c) 2010-2017 Texas Instruments Incorporated。 保留所有权利。
    //软件许可协议
    //
    以源代码和二进制形式重新分发和使用,无论是否
    进行//修改,只要
    满足以下条件//:
    //
    重新分发源代码必须保留上述版权
    //声明、此条件列表和以下免责声明。
    //
    //二进制形式的再发行必须复制上述版权
    //声明、此条件列表和//
    
    分发随附的//文档和/或其他材料中的以下免责声明。
    ////
    未经
    
    事先书面许可,不能使用德州仪器公司的名称或//其贡献者的名称来认可或推广源自此软件的产品//。
    ////
    本软件由版权所有者和贡献者提供
    //“按原样”,不
    
    承认任何明示或暗示的保证,包括但不限于//适销性和对//特定用途适用性的暗示保证。 在任何情况下、版权
    //所有者或贡献者都不对任何直接、间接、偶然、
    //特殊、模范、 或相应的损害(包括但不
    限于采购替代产品或服务;丧失使用、
    //数据或利润; 或业务中断)、无论
    
    出于何种原因使用
    本软件(即使被告知可能会造成此类损坏)、还是出于任何原因而产生的任何//责任理论(无论是合同、严格责任还是侵权行为)//(包括疏忽或其他)。
    //
    //这是 Tiva 固件开发包的修订版2.1.4.178的一部分。
    ////
    *****************
    
    #include 
    #include 
    #include "inc/hw_memmap.h"
    #include "driverlib/gpio.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/ssi.h"
    #include "driverlib/sysctl.h"
    #include "utils/ustdio.h"
    
    #include "utils/uartdio.h"
    
    
    //
    //! \addtogroup SSI_examples_list
    //! 

    SPI 主器件(SPI_MASTER)

    //! //! 此示例展示了如何将 SSI0配置为 SPI 主设备。 代码将 //! 在主 Tx 上发送三个字符、然后轮询接收 FIFO、直到 //! 在主 Rx 上接收3个字符。 //! //! 此示例使用以下外设和 I/O 信号。 您必须 //! 查看这些内容并根据您自己的董事会需要进行更改: //! - SSI0外设 //! - GPIO 端口 A 外设(用于 SSI0引脚) //! SSI0Clk - PA2 //! - SSI0Fss - PA3 //! - SSI0Rx - PA4 //! - SSI0Tx - PA5 //! //! 以下 UART 信号仅配置为显示控制台 //! 消息。 SSI0的运行不需要这些。 //! - UART0外设 //! - GPIO 端口 A 外设(用于 UART0引脚) //! - UART0RX - PA0 //! - UART0TX - PA1 //! //! 此示例使用以下中断处理程序。 要使用此示例 //! 在您自己的应用程序中、您必须将这些中断处理程序添加到 您的//! 矢量表。 //! -无。 //// ***************** // // //要发送和接收的字节数。 //// ***************** #define NUM_SSI_DATA 3 //************* // //此函数将 UART0设置为用于控制台,以便 在示例运行时显示信息//。 //// ***************** void InitConsole (void) { // //启用用于 UART0引脚的 GPIO 端口 A。 // TODO:将其更改为您正在使用的 GPIO 端口。 // SysCtlPeripheralEnable (SYSCTL_Periph_GPIOA); // //为端口 A0和 A1上的 UART0功能配置引脚复用。 //如果您的器件不支持引脚复用、则无需执行此步骤。 // TODO:更改此选项以选择您正在使用的端口/引脚。 // GPIOPinConfigure (GPIO_PA0_U0RX); GPIOPinConfigure (GPIO_PA1_U0TX); // //启用 UART0以便我们可以配置时钟。 // SysCtlPeripheralEnable (SYSCTL_Periph_UART0); // //使用内部16MHz 振荡器作为 UART 时钟源。 // UARTClockSourceSet (UART0_BASE、UART_CLOCK_PIOSC); // //为这些引脚选择替代(UART)功能。 // TODO:更改此选项以选择您正在使用的端口/引脚。 // GPIOPinTypeUART (GPIO_Porta_base、GPIO_PIN_0 | GPIO_PIN_1); // //初始化控制台 I/O 的 UART // UARTStdioConfig (0、115200、16000000); } //********* // //在主 Freescale (SPI)模式下配置 SSI0。 此示例将发出 // 3个字节的数据,然后等待3个字节的数据进入。 这将全部由 //使用轮询方法完成。 //// ***************** int main (void) { #if defined (target_IS_TM4C129_RA0)|| \ 已定义(TARGET_IS_TM4C129_RA1)|| \ 已定义(TARGET_IS_TM4C129_RA2) uint32_t ui32SysClock; #endif uint32_t pui32DataTx[NUM_SSI_DATA]; uint32_t pui32DataRx[NUM_SSI_DATA]; uint32_t ui32Index; // //将时钟设置为直接从外部晶振/振荡器运行。 // TODO:必须更改 SYSCTL_XTAL_VALUE 以匹配的值 板上的//晶体。 // #if defined (target_IS_TM4C129_RA0)|| \ 已定义(TARGET_IS_TM4C129_RA1)|| \ 已定义(TARGET_IS_TM4C129_RA2) ui32SysClock = SysCtlClockFreqSet ((SYSCTL_XTAL_25MHz | SYSCTL_OSC_MAIN | SYSCTL_USE_OSC)、25000000); #else SysCtlClockSet (SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHz); #endif // //设置用于显示消息的串行控制台。 这是 //仅用于此示例程序,SSI 操作不需要。 // InitConsole(); // //在控制台上显示设置。 // UARTprintf ("SSI ->\n"); UARTprintf ("模式:SPI\n"); UARTprintf ("数据:8位\n"); // //必须启用 SSI0外设才能使用。 // SysCtlPeripheralEnable (SYSCTL_Periph_SSI0); // //对于本示例,SSI0与 Porta[5:2]一起使用。 实际端口和引脚 //您的器件上使用的可能不同、请参阅数据表以了解更多信息 //信息。 GPIO 端口 A 需要启用、以便可以使用这些引脚。 // TODO:将其更改为您正在使用的 GPIO 端口。 // SysCtlPeripheralEnable (SYSCTL_Periph_GPIOA); // //为端口 A2、A3、A4和 A5上的 SSI0功能配置引脚复用。 //如果您的器件不支持引脚复用、则无需执行此步骤。 // TODO:更改此选项以选择您正在使用的端口/引脚。 // GPIOPinConfigure (GPIO_PA2_SSI0CLK); GPIOPinConfigure (GPIO_PA3_SSI0FSS); GPIOPinConfigure (GPIO_PA4_SSI0RX); GPIOPinConfigure (GPIO_PA5_SSI0TX); // //配置 SSI 引脚的 GPIO 设置。 该函数也会提供 将这些引脚的//控制到 SSI 硬件。 请参阅中的数据表 //查看每个引脚分配的函数。 //引脚分配如下: // PA5 - SSI0Tx // PA4 - SSI0Rx // PA3 - SSI0Fss // PA2 - SSI0CLK // TODO:更改此选项以选择您正在使用的端口/引脚。 // GPIOPinTypeSSI (GPIO_Porta_base、GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_3 | GPIO_PIN_2); // //为 SPI 主控模式配置和启用 SSI 端口。 使用 SSI0、 //系统时钟电源,空闲时钟低电平和低电平有效时钟输入 //飞思卡尔 SPI 模式、主控模式、1MHz SSI 频率和8位数据。 //对于 SPI 模式,可以设置 SSI 时钟的极性 //单元空闲。 您还可以配置所需的时钟边沿 //在上捕获数据。 有关的更多信息、请参阅数据表 //不同的 SPI 模式。 // #if defined (target_IS_TM4C129_RA0)|| \ 已定义(TARGET_IS_TM4C129_RA1)|| \ 已定义(TARGET_IS_TM4C129_RA2) SSIConfigSetExpClk (SSI0_BASE、ui32SysClock、SSI_FRF_MOTO_MODE_0、 SSI_MODE_MASTER、1000000、8); #else SSIConfigSetExpClk (SSI0_BASE、SysCtlClockGet ()、SSI_FRF_MOTO_MOTO_MODE_1、 SSI_MODE_MASTER、1000000、16); #endif // //启用 SSI0模块。 // SSIEnable (SSI0_BASE); // //从 SSI 端口读取任何残留数据。 这将确保接收 // FIFO 为空,因此我们不会读取任何不需要的垃圾。 这在这里完成 //因为 SPI SSI 模式为全双工模式,允许您发送和 //同时接收。 SSIDataGetNonBlocking 函数返回 //返回数据时为"true",未返回数据时为"false"。 //“非阻塞”函数检查接收中是否有数据 // FIFO、如果没有、则不会"挂起"。 // while (SSIDataGetNonBlocking (SSI0_BASE、&pui32DataRx[0])) { } // //初始化要发送的数据。 // pui32DataTx[0]="S"; pui32DataTx[1]='p'; pui32DataTx[2]='I'; // //显示 SSI 正在发送数据的指示。 // UARTprintf ("sent:\n "); // //发送3个字节的数据。 // // //显示 SSI 正在传输的数据。 // // //使用“阻塞”Put 函数发送数据。 此函数 //将等待发送 FIFO 中有空间后再返回。 //这使您可以确保发送的所有数据都将其输入 //发送 FIFO。 // SSIDataPut (SSI0_BASE、pui32DataTx[0]); // //等待 SSI0完成传输发送 FIFO 中的所有数据。 // while (SSIBusy (SSI0_BASE)) { } // //显示 SSI 正在接收数据的指示。 // // //接收3个字节的数据。 // while (1){ SysCtlDelay (200); // //使用“阻塞”GET 函数接收数据。 此函数 //将等待接收 FIFO 中有数据后再返回。 // SSIDataPut (SSI0_BASE、&pui32DataRx[0]); // //由于我们使用的是8位数据,所以屏蔽 MSB。 // // //显示 SSI0接收到的数据。 // } // //返回无错误 // }

    这两个图像第一个是上载代码后、第二个是移除 USB 并重新连接后  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    SPICLK 和 CS 看起来正常。 没有 MISO。 MISO 来自您的 MAX6675。 检查 MISO 上是否存在任何驱动器冲突。 从 MAX6675断开 MISO 与 MCU 的连接。 您是否仍然没有看到 MISO 上的任何内容。 如果是这种情况、则需要在 MAX6675侧进行调查。 另一个需要检查的问题是 SPICLK 和 CS 上是否具有正确的电压电平。 我无法从您那里得知示波器电容器。

    如果您未断开 USB 电源而只是重置设备、该怎么办?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    如果我只是休息一下、我会得到第一幅图像、但如果我没有改变读数 拔下 USB、除非我重新上传代码、否则无法正常工作
    当我断开 MISO 时、我得到 SPIclk 和 Cs、而 MISO 上没有任何内容
    我认为问题出在 MAX 端、因此我使用 Arduino 进行了测试、工作正常
    示波器上的电压这些图像在三个通道上以2 v/div 为单位获取
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    请在重新插入 USB 电源后立即获取 CS 和 SPICLK 的示波器捕获。 也许您的 MAX 器件在加电后可能在这两条信号线上看到了一些开关活动。 MAX 器件不知道您的 MCU 刚从上电状态出来。 CS 或 SPICLK 上的任何活动都可能会将 MAX 器件混淆为认为它是有效的命令。 另一个建议是在 CS 信号上添加一个上拉电阻、您是否看到任何差异?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    在添加上拉后、没有任何新内容

     

    USB 插接的单冲模式  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    while (1)循环内的延迟可能太短。 您有一个 SysCtlDelay (200)、远小于0.17s。 MAX 数据表显示典型转换时间为0.17s。 如果是这种情况、您将在转换完成之前尝试读取。 尝试增加延迟(超过0.17s)、看看这是否会产生影响。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    感谢查尔斯解决了我的问题,我不知道我是怎么错过的:)
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    很高兴您的问题得到解决。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    很抱歉、Charles 先生、但我没有注意到、只有通过 SSIDataPut 才能使 SPI 正常工作、如果我不使用它、我仍然没有时钟、除非我在   SSIDataGet 之前使用 SSIDataPut、否则代码不起作用

    #include 
    #include 
    include "inc/hw_memmap.h"
    #include "driverlib/gpio.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/ssi.h"
    #include "driverlib/ssi.c"
    #include "driverlib/sysctl.h"
    #include "driverlib/uartdio.h"
    #include "uarts/utils"
    
    
    
    
    
    
    uint32_t pui32DataRx;
    //
    SysCtlClockSet (SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHz);
    
    SysCtlPeripheralEnable (SYSCTL_Periph_SSI0);
    SysCtlPeripheralEnable (SYSCTL_Periph_GPIOA);
    GPIOPinConfigure (GPIO_PA2_SSI0CLK);
    GPIOPinConfigure (GPIO_PA3_SSI0FSS);
    GPIOPinConfigure (GPIO_PA4_SSI0RX);
    GPIOPinConfigure (GPIO_PA5_SSI0TX);
    // PA5 - SSI0Tx PA4 - SSI0Rx PA3 - SSI0Fss PA2 - SSI0CLK
    GPIOPinTypeSSI (GPIO_Porta_base、GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_3 | GPIO_PIN_2);
    
    SSIConfigSetExpClk (SSI0_BASE、SysCtlClockGet ()、SSI_FRF_MOTO_MOTO_1、SSI_MODE_MASTER、1000000、 16);
    SSIEnable (SSI0_BASE);
    
    while (SSIDataGetNonBlocking (SSI0_BASE、&pui32DataRx))
    {
    }
    
    while (1){
    SysCtlDelay (20000000);
    SSIDataPut (SSI0_BASE、pui32DataRx);//如果不使用这条线,时钟和 cs 根本不起作用
    SSIDataGet (SSI0_BASE、&pui32DataRx);
    
    }
    }
    

    1) 1)我还注意到 SSI_SR 寄存器始终具有0x00000003的值、该值指示 SSI_SR_RNE 始终为零  

    2) 2)需要注意的另一点是、当我在 SSIDataGet 之前不使用 SSIDataPut 时、代码会被 alwyase 捕获在 SSIDataGet 函数中的内部 while 循环中  

    谢谢。

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

    [引用 USER="Samir Ibrahim ]...SIDataPut 使 SPI 正常工作 ...  除非 SSIDataPut 发生在 SSIDataGet 之前、否则不获取时钟和代码不起作用[/quot]

    我相信朋友 Charles 会同意-"SPI 协议、"全双工通信"-数据在一个时钟边沿上发送-(通常)在另一个时钟边沿上接收(时钟边沿)。

    您注意到的是"正常"-它只是生成 SPI 时钟的"SSIDataPut ()"函数!   

    "SSIDataGet ()"函数只是"恢复接收到的数据"-在"立即发出之前"、 "SSIDataPut()"期间。   

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    这里的讽刺是我的奴隶甚至不需要 mosi
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    (讽刺)是一个很好的"字选择"-然而(大多数) SPI 从器件(当然是那些更复杂的器件)确实需要时钟输入数据-并且它们返回主器件的响应(通常)是一个字节"后面"。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    这是否意味着除非我发送数据,否则我无法接收数据?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    没错。 您必须生成对 SPI 主器件的假写入、以便主器件生成 SPICLK、即使从器件不需要 MOSI。 仅 SSIDataGet ()不会为您生成 SPICLK。 这是设计所固有的。 SSIDataPut ()将数据写入 SSIDR 寄存器,这将触发 SSI 内核开始传输(SPI 时钟生成)。 请参阅我的第一次答复。 我已经提到您需要虚拟写入。