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.

[参考译文] TM4C123GH6PZ:微控制器和 ADS1292R 之间的 SPI 连接存在问题

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/604253/tm4c123gh6pz-problem-with-spi-connection-between-microcontroller-and-ads1292r

器件型号:TM4C123GH6PZ
主题中讨论的其他器件:ADS1292R

你好。

我有以下问题。 我为 通过   SPI 在 TM4C123GH6PZ 和 ADS1292R 之间进行通信而编写的代码不起作用。 我尝试从 ADS1292R (从器件)读取 ECG 和呼吸数据 、然后通过 UART 发送数据、但我只得到零、而不是实际数据。 我还尝试读取 whoami (ID)引脚、但其读数为0。 我尝试使用逻辑分析仪测量信号、但结果不是我所期望的。 对于启动器、时钟的频率为50kHz (即使在代码中我已经将频率设置为1MHz)、CS 引脚不会每次都会下降。 此外、当我在设置中设置 CPOL = 0和 CPHA = 1时、Saleae 报告错误" CLK 线路的初始(空闲)状态与设置不匹配。"、 但是、当我设置 CPOL = 1时、即使它不应该读取、它也会在发送器和接收器上读取'255'。  在 ADS1292R 数据表中、显示了正确的设置:CPOL = 0和 CPHA = 1、因此我在 SSI 配置中设置 SSI_FRF_MOTO_MOTO_MODE_1。 我正在使用面向 ADS1292R 屏蔽/分线板的 Arduino 库、我对该库进行了调整、使其适合我的 TM4C UC。

所有这些都使我感到困惑、因为我不熟悉微控制器、我非常感谢您的帮助。 我甚至不确定问题是软件还是硬件问题。 在附件中、我放置了整个项目(文件夹:'project')、Saleae 的结果(文件夹:'SALEAE Samples')、连接我使用的引脚的方案(文件夹:'scheme')和 适用于 ADS1292R Shield/Breakout 的 Arduino 库(文件夹:'Arduino_library')。

此致、
劳拉

e2e.ti.com/.../3757.project.zip

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    请允许我赞扬您的"提供测量和程序"、它将"迄今为止"扩展到(通常)"不起作用!" (总是令人愉快的!)

    也就是说、您的"Saleae 文件"会被窒息、"LogicData"、因此我们无法(轻松)打开。 (并非此处的所有内容都熟悉特定的内容)

    我正在旅行-将在今天/晚上晚些时候审查您的代码(如果仍然需要)-但建议您(实际上)查看多个 SPI 代码示例-无法设置 SPI 时钟频率"不常被注意到"-几乎肯定是由于编码错误导致的...
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你(们)好。

    从这个"盲"的角度来看:如果您的时钟预计为1MHz、而您的时钟速度要慢20倍... 首先、确保正确配置 SPI 时钟源。

    看看您的 SPI 配置。 如果需要、请将其粘贴到此处。

    对于进一步的读者来说、"Saleae"是一个逻辑分析仪品牌、他们有一个开源可视化软件-因此我假设如果安装了此类查看器、就可以看到最初附加的文件(没有多少人愿意将其安装到生产机器中...)

    其他提示:不要让 SPI 硬件控制您的 CS 线路。 通过常规 GPIO 处理它。

    由于我前面有一段有效的 SPI 代码、因此粘贴该代码以供参考不会有任何影响(尽管配置部分不在此处):

    GPIOPinWrite (gyroHW->GPIOFSSPort、gyroHW->GPIOFSSPin、0);//降低 CSB
    SSIDataPut (gyroHW->SSIBase、frameHigh);//仅发送高16位
    while (SSIBusy (gyroHW->SSIBase));//清零前16位
    SSIDataGet (gyrohw->SSIBase、readCrap);//读取无用数据
    SSIDataPut (gyroHW->SSIBase、(frameLow));//这会发送其他16位
    while (SSIBusy (gyroHW->SSIBase));//刷新第二个16位
    GPIOPinWrite (gyroHW->GPIOFSSPort、gyroHW->GPIOFSSPin、gyroHW->GPIOFSSPin);//提升 CSB
    SSIDataGet (gyrohw->SSIBase、readCrap);//读取无用数据
    GPIOPinWrite (gyroHW->GPIOFSSPort、gyroHW->GPIOFSSPin、0);//降低 CSB
    SSIDataPut (gyroHW->SSIBase、frameHigh);//刷新第三个16位
    while (SSIBusy (gyroHW->SSIBase));//等待位被清空
    SSIDataGet (gyroHW->SSIBase、read16High);//读取16位
    SSIDataPut (gyroHW->SSIBase、frameLow);//刷新最后16位
    while (SSIBusy (gyroHW->SSIBase));//等待位被清空
    SSIDataGet (gyrohw->SSIBase、read16Low);//读取更多数据
    GPIOPinWrite (gyroHW->GPIOFSSPort、gyroHW->GPIOFSSPin、gyroHW->GPIOFSSPin);//提升 CSB
    

    谢谢

    布鲁诺

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

    今天,我尝试在 TM4C123G LaunchPadTm评估套件(未连接到 ADS1292R)上运行代码,以进行调试,并使用逻辑分析仪进行测量,以查看我是否正在从主设备正确发送数据 (另一个电路板上的引脚不太容易通过分析仪进行探测)。 在对代码进行一些修整后、这是我通过 MOSI 线路发送的内容的示例: http://imgur.com/W59EhCe
    它应该是这样吗? 对我来说、MOSI 线路上的数据与我在代码中发送的数据相匹配、时钟正常、在 LaunchPad 上显示1MHz。
    现在、我将尝试在另一个板上运行"固定"代码并返回给您。

    谢谢!

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

    劳拉

    这就是它应该是什么样的"类型"。 使用合适的工具是很棒的、不是吗?

    您的 Saleae 上还有其他渠道吗? 查看 CS 线路也很重要。

    我在时钟之前看到一些 MOSI 活动、这是可疑的。

    这是一个特定传感器的4通道捕获、它可能会对您有所帮助。

    布鲁诺

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

    布鲁诺

    我也在查看 CS 系列、它位于通道3上:

    就像上一个示例一样、他是在未连接到从器件的 Tiva LaunchPad 上测量的。 时钟前后有 MOSI 活动、如果有问题、如何解决? Saleae 似乎没有麻烦、因为它正确地解码已发送的数据、我实际上正在尝试发送0xFF 9次(作为虚拟数据)。 它们可以是起始位和停止位吗? 在您发送给我的示例中、当时钟处于非活动状态时、D2通道上似乎也有一些活动。

    这是我用于从 ADS1292R 获取数据的函数:

    char* ads1292r:::ads1292_read_Data ()
    
    {
    
    uint32_t pui32Data;
    
    静态 char SPI_Dummy_buff [10];
    
    
    GPIOPinWrite (GPIO_Porta_base、GPIO_PIN_0、0x00); //为
    
    (int j=0;j < 1000;j++)拉低 CS;//等待一段时间
    
    (int i = 0;i < 9;+i)
    
    {
    
    SSIDataPut (SSI0_BASE、0xFF);//将数据发送到从属
    
    SIDataGet (SSI0_BASE、+i);{sSSI0_DP=32j
    
    ;
    
    //将数据发送到从 SSDI_DPUGE=32_DPUGE_DP_PIN_0=0_DPUGE_DPUGE=12_SD_DP_DPUGE_DP_DPWAP_DP_0=0_DP_DP_SD_PIN_DP_DP_DPUGE_SD_0=0_
    
    
    
    J++);//等待一段时间
    
    GPIOPinWrite (GPIO_Porta_base、GPIO_PIN_0、GPIO_PIN_0);//将 CS 上拉
    
    返回 SPI_Dummy_buff;
    
    } 


    这是从 ADS1292R 获取数据的正确方法吗?
    我尝试在另一个板上运行代码(TM4C123GH6PZ 和 ADS1292R 芯片上的代码)、但我获得的数据似乎是垃圾。 我应该得到3个状态字节、然后是3个呼吸字节和3个 ECG 字节、首先是 MSB。 下面是我在打印 SPI_Dummy_buff 数组时得到的一些示例:

    0 0 127 255 127 255 255 255 192
    0 0 127 255 127 255 255 255 192
    0 0 128 0 0 127 255 255 192
    0 0 50 160 93 127 255 192
    0 0 128 0 0 127 255 255 192
    0 0 192 62 125 127 255 255 192
    0 0 128 0 0 127 255 255 192
    0 0 127 255 127 255 255 255 192
    0 0 128 0 0 127 255 255 192
    0 0 127 255 127 255 255 255 192
    0 0 128 0 0 127 255 255 192
    0 0 127 255 127 255 255 255 192

    谢谢、

    劳拉

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    你(们)好。
    今天的帮助不大、但有几个(非常快且令人困惑)要点:
    TM4C 上的发送和接收 FIFO 缓冲区均为16位-这是您可以在每个 SPI"命令"上写入或读取的最大值。 我之前发布的作为示例的代码考虑了这一点、并且由于该传感器的"word "是32位的、因此我们执行2组命令。 在示波器捕获上、您可以看到两组中每组都有一个不带时钟的短周期。
    -不、在这些示例的时钟区域之外、MISO 或 MOSI 中没有任何活动。
    我无法回答您的特定传感器、但有4种 SPI "模式"。 它们之间的区别在于它们在上升或下降时钟转换时进行采样、以及 CS 为低电平或高电平。 尝试发现您的传感器使用哪一个(到目前为止、我们所遇到的所有情况都是使用示波器捕获显示的模式)。
    -检查传感器上的每个通信字有多长时间、看看您是否正在对程序进行正确的操作...
    这是与之前发布的内容一同提供的 SPI 配置代码的简短部分:

    SSIClockSourceSet (hwSSIBase、SSI_CLOCK_SYSTEM);// SSI0_BASE -冗余但专业
    SSIConfigSetExpClk (hwSSIBase、system_clock_Hz、SSI_FRF_MOTO_mode_0、SSI_mode_master、750000016);
    SSIEnable (hwSSIBase);

    此致
    布鲁诺
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    布鲁诺 
    这是我的 SSI INIT 函数: 
    
    
    void SSI0_init (){
    
    SysCtlPeripheralEnable (SYSCTL_Periph_SSI0);
    SysCtlPeripheralEnable (SYSCTL_Periph_GPIOA);
    
    
    configureGPIOA ();//将端口 A 引脚0和1设置为非备用函数
    GPIOConfigure (GPIO_PA2_SSI0_GPIO5
    
    
    
    
    
    );GPIO_PIN_GPIO4_GPIO5_GPIO5|GPIO_PIN_0_GPIO4_GPIO5|GPIO4_PIN_GPIO4_GPIO5|GPIO4_GPIO_P0_GPIO4_GPIO5|GPIO4_GPIO4_PIN_PIN_GPIO_P0_GPIO4_GPIO4_GPIO5|GPIO4_GPIO4_GPIO4_GPIO5|GPIO4_GPIO4_GPI
    GPIOPinTypeGPIOInput (GPIO_Porta_base、GPIO_PIN_1);//DRDY
    GPIOPinTypeGPIOOutput (GPIO_Porta_base、GPIO_PIN_0);//CS
    GPIOPinTypeGPIOOutput (GPIO_Porta_base、 GPIO_PIN_6);//PWDN
    // CPOL = 0、CPHA = 1 -> SSI_FRF_MOTO_MODE_1
    SSIConfigSetExpClk (SSI0_BASE、SysTOClockGet ()、SSI_FRF_MODE_1、SSI_MODE_MASTER、1000000、 8);
    SSIEnable (SSI0_BASE);
    
    } 

    我认为该部分是可以的。 在数据表中、显示 SPI 模式为 SSI_FRF_MOTO_MODE_1、CS 在低电平时有效。 我已经在 程序和 Saleae 选项中设置了 SSI_FRF_MOTO_MODE_1。
    传感器连续发送3个"字"、每个字长24位、因此我将读取8个位9次、然后重新汇编这些字以获取正确的数据。

    此致、

    劳拉

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

    如果您仍愿意查看我的代码、则会进行一些更新、因此我将在此处发布新版本:
    e2e.ti.com/.../project_5F00_v2.zip


    下面是结果的 Putty 日志:
    e2e.ti.com/.../putty.log


    在文件夹中、我放置了 Saleae 文件的一些屏幕截图(但 MISO 行并不重要、因为 MISO 行是在 Tiva LaunchPad 上测量的、而不是在真实板上测量的)。
    提前感谢:)

    此致、  

    劳拉

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

    劳拉

    我们快速看了一下。

    您知道、您仍然可以使用 PA3连接到 CS -我们建议将其配置为 GPIO、而不是让 SSI 硬件负责。 如果您稍后实际上希望尝试使用 CS 引脚自动控制、这将更实用。

    现在、便宜信号看起来是合理的。 传感器的模式实际上是 mode_1、但您的文件 main2.c 参数是 mode_0。

    频率在1MHz 时是正确的(只需仔细检查、测量分析仪上的频率、因为 SSI 分频器有时会生成比在 Tivaware 参数上传递的值更快的值。

    您在 saleae MOSI 上看到的值是否与您在 Tiva 上实际发送的值相匹配?

    while 循环上的写入/读取序列被混淆... 您并不是在阅读所有内容。

    查看并比较我在前面一条消息中发布的代码:您将 SSI 用作8位、因此每次输出8位时、接收缓冲区上都有8位必须读取(并在稍后重构)。 而不是盲目等待循环、只需检查直到所有 SPI 位都被发送、然后读取返回的内容。

    谢谢

    布鲁诺

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

    布鲁诺

    FSS 引脚未物理 连接到电路板上的任何器件、而 GPIO_PORta_PIN0物理 连接到 CS、如方案所示:


    这就是为什么我不使用 FSS、但感谢提示。

    关于 main2.c 文件、它是一个历史版本、从我不知道我在做什么开始。 很抱歉、我忘记了从项目文件中删除它、它未包含在 Keil 项目中、因此它没有让我感到困惑。 真正重要的文件是 main.cpp 和 ads1292r.cpp、并且在 main.cpp 中定义了 SSI_MODE_1。

    我在 MOSI 线路上看到的值与我尝试发送的值相匹配。


    [引用 user="Bruno Saraiva"]每次输出8位时,接收缓冲区上都有8位必须读取[/引用]
    这是我丢失的信息。 我认为这只是一种编程做法、即使您的目标只是发送数据、也不是必须的、读取无用的数据。 我现在就解决这个问题。
    非常感谢您的观看! 希望它现在可以工作、我会以任何方式返回给您。

    谢谢!

    劳拉:)