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.

[参考译文] TMS320F28379D:如何使用24位世界 SPI

Guru**** 2455790 points
Other Parts Discussed in Thread: ADS1298R, C2000WARE

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/840874/tms320f28379d-how-to-work-with-24-bits-world-spi

器件型号:TMS320F28379D
主题中讨论的其他器件:ADS1298RC2000WARE

您好!

我正在尝试了解如何使用 SPI 与向我发送9个24位字的从 SPI 外设进行通信。 我开始使用提供的使用驱动程序库的示例之一、并在阅读数据表时发现 SPI 缓冲器和 FIFO 为16位宽度。 我想我可以将 DE SPI 设置为8位字、然后将字节读取为字节、但 API 显示、正如我看到的、缓冲器只读取最后一个有效字节、而"损耗"其他字节、对吗? 如何继续?

此致、

Matheus Alexandre

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

    大家好、Matheus Alexandre、

    SPICCR 寄存器中的 SPICHAR 域决定要发送的字符的长度。 您可以针对您的案例将其设置为8。 这可以通过 SPI_setConfig API 进行控制。 在提供的示例中、它设置为16、因此配置为16个字符长度。  您是否尝试过更改它? 如果不是、您可以尝试一下吗?

    此致、
    Praveen

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

    大家好、Praveen

    谢谢、但我已经这么做了。 我现在唯一需要测试的方法是使用 SPI 作为 slaver、但我认为它不应改变预期的行为。 我从另一个 SPI 主设备(10MHz、POL 0 PHA 0)发送、两个字的24位 宽度、0x78ABCD 和0x123456。 我在 sData++上使用断点、第一次暂停时、我在  RDATA 上看到0x00000178、第二次暂停时看到 0x0000345E、然后我从主器件重新发送相同的数据、并在第三次暂停0x00005E78和第四次暂停0x00003456上看到。

    #include "driverlib.h"
    #include "device.h"
    
    //
    循环运行的次数(如果需要增加次数)
    //
    uint16_t loop_count = 100;
    
    //
    函数原型
    //
    void initSPI (void);
    
    void initSPI_gpio (void);
    
    //
    Main
    //
    void main (void)
    {
    uint16_t sData = 2; //发送数据
    uint32_t RDATA = 0; //接收数据
    
    uint32_t i = 0;
    
    //
    //初始化设备时钟和外设
    //
    device_init();
    
    //
    //禁用引脚锁定并启用内部上拉。
    //
    DEVICE_initGPIO();
    
    //
    //初始化 PIE 并清除 PIE 寄存器。 禁用 CPU 中断。
    //
    interrupt_initModule();
    
    //
    //使用指向 shell 中断的指针初始化 PIE 矢量表
    //服务例程(ISR)。
    //
    interrupt_initVectorTable();
    
    //
    //设置 SPI,将其初始化为 FIFO 模式
    //
    initspi();
    
    initspi_gpio();
    
    //
    //启用全局中断(INTM)和实时中断(DBGM)
    //
    EINT;
    ERTM;
    
    //
    //永久循环。 暂停或放置断点以观察缓冲区。
    //
    while (1)
    {
    
    RDATA = SPI_READDataBlockingNonFIFO (SPIB_BASE);
    
    sData++;
    
    Example_PassCount++;
    
    对于(i=0;i<2000000;i++)
    {
    
    }
    }
    
    
    void initSPI()
    {
    SPI_disableModule (SPIB_BASE);
    
    SPI_setConfig (SPIB_BASE、DEVICE_LSPCLK_FREQ、SPI_PROT_POL0PHA0、
    SPI_MODE_SLAVE、10000000、8);
    SPI_setEmulationMode (SPIB_BASE、SPI_emulation_free_run);
    
    spi_enableModule (SPIB_BASE);
    }
    
    void initspi_gpio()
    {
    EALLOW;
    
    //SPI B 配置
    
    GPIO_setPadConfig (63、GPIO_PIN_TYPE_PULLUP);
    GPIO_setPadConfig (64、GPIO_PIN_TYPE_PULLUP);
    GPIO_setPadConfig (65、GPIO_PIN_TYPE_PULLUP);
    GPIO_setPadConfig (66、GPIO_PIN_TYPE_PULLUP);
    
    GPIO_setDirectionMode (63、GPIO_DIR_MODE_IN);
    GPIO_setDirectionMode (64、GPIO_DIR_MODE_OUT);
    GPIO_setDirectionMode (65、GPIO_DIR_MODE_IN);
    GPIO_setDirectionMode (66、GPIO_DIR_MODE_IN);
    
    GPIO_setQualificationMode (63、GPIO_QUAL_异 步);
    GPIO_setQualificationMode (64、GPIO_QUAL_异 步);
    GPIO_setQualificationMode (65、GPIO_QUAL_异 步);
    GPIO_setQualificationMode (66、GPIO_QUAL_异 步);
    
    GPIO_setPinConfig (GPIO_63_SPISIMOB);
    GPIO_setPinConfig (GPIO_64_SPISOMIB);
    GPIO_setPinConfig (GPIO_65_SPICLKB);
    GPIO_setPinConfig (GPIO_66_SPISTEB);
    
    EDIS;
    }
    

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

    您可能需要考虑使用 McBSP。 以下是指向教程的链接... http://www.add.ece.ufl.edu/4511/references/McBSP%20Tutorial.pdf

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

    您好、Matheus、

    您将使用什么作为主器件?配置的时钟速度是多少? 请注意 、C2000器件不一定与为其他器件定义的其他"模式"保持一致。 相位和极性位意味着不同的东西。 请参阅用户指南以确定您的发送和接收边沿是什么、并将它们与主芯片进行比较。 不要只匹配相位= 0和极性= 0、并假设模式相同。 请参阅 TRM 中的 SPI 时钟方案部分。

    此致、

    Praveen

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

    感谢您的建议。 我将尝试本模块、然后返回结果。

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

    Praveen、我使用了 Analog DISCOVERY 2中的协议分析 器、f28379d 中配置的时钟频率为 DEVICE_SYSCLK_FREQ = 200MHz、DEVICE_LSPCLK_FREQ = 50MHz 和 SPI 频率10MHz。 我确信模拟发现的频率、POL 和 PHA 配置良好、因为我之前已经使用过它。 我将尝试按照 Todd 的建议使用 McBSP 模块、不要太过分。

    很抱歉、如果是双帖子、我忘记回复 Praveen。

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

    您好、Matheus、

    您是否有机会尝试它?

    此致、

    Praveen

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

    大家好、Praveen

    很抱歉耽误你的时间、我正在处理2个不同的项目。

    我想我已经明白了、我正在不间断地使用 SPI 的 FIFO 使能。 我还无法测试 MISO。

    我对 SPI 仍有一些疑问:

    1) 1)使用 SPI 的 FIFO 时是否需要使用中断?

    2) 2)启用 FIFO 时、8位字 SPI 是否正常工作? 因为正如我在程序上看到的、它仅在缓冲区获得16位时开始传输、即使我更改为8位字 SPI 配置也是如此。

    3) 3)我不习惯与 FIFO 一起工作。 据我所知、没有填充 FIFO 的指令和其他用于启动 SPI 传输的指令、有吗?

    除了驱动器库示例中的库文件之外、还有3个文件、第一个文件包含 main、SPI_ADS.c 包含与 SPI 相关的所有内容、而 spi_ads.h 包含宏。

    我的最终目标是与 ADS1298R ECFE 通信。

    include "driverlib.h"
    #include "device.h"
    #include "spi_ads.h"
    
    // main
    void main (void)
    {
    //
    //初始化设备时钟和外设
    //
    device_init();
    
    //
    //禁用引脚锁定并启用内部上拉。
    //
    DEVICE_initGPIO();
    
    //
    //初始化 PIE 并清除 PIE 寄存器。 禁用 CPU 中断。
    //
    interrupt_initModule();
    
    //
    //使用指向 shell 中断的指针初始化 PIE 矢量表
    //服务例程(ISR)。
    //
    interrupt_initVectorTable();
    
    //
    //设置 SPI,将其初始化为 FIFO 模式
    //
    init_spi_ads ();
    ads_reset ();
    
    //中断_ENABLE (INT_SPIB_TX);
    
    //
    //启用全局中断(INTM)和实时中断(DBGM)
    //
    EINT;
    ERTM;
    
    //
    //永久循环。 暂停或放置断点以观察缓冲区。
    //
    while (1)
    {
    }
    } 

    #include "spi_ads.h"
    
    void init_spi_ads ()
    {
    EALLOW;
    
    //SPI B 配置
    
    GPIO_setPadConfig (SPI_MOSI、GPIO_PIN_TYPE_PULLUP);
    GPIO_setPadConfig (SPI_MISO、GPIO_PIN_TYPE_PULLUP);
    GPIO_setPadConfig (SPI_CLK、GPIO_PIN_TYPE_PULLUP);
    GPIO_setPadConfig (SPI_CS_1、GPIO_PIN_TYPE_PULLUP);
    
    GPIO_setDirectionMode (SPI_MOSI、GPIO_DIR_MODE_OUT);
    GPIO_setDirectionMode (SPI_MISO、GPIO_DIR_MODE_IN);
    GPIO_setDirectionMode (SPI_CLK、GPIO_DIR_MODE_OUT);
    GPIO_setDirectionMode (SPI_CS_1、GPIO_DIR_MODE_OUT);
    
    GPIO_setQualificationMode (SPI_MOSI、GPIO_QUAL_异 步);
    GPIO_setQualificationMode (SPI_MISO、GPIO_QUAL_异 步);
    GPIO_setQualificationMode (SPI_CLK、GPIO_QUAL_异 步);
    GPIO_setQualificationMode (SPI_CS_1、GPIO_QUAL_异 步);
    
    GPIO_setPinConfig (GPIO_63_SPISIMOB);
    GPIO_setPinConfig (GPIO_64_SPISOMIB);
    GPIO_setPinConfig (GPIO_65_SPICLKB);
    
    EDIS;
    
    //
    //必须在配置 SPI 之前将其复位
    //
    SPI_disableModule (SPIB_BASE);
    
    //
    // SPI 配置。 使用1MHz SPICLK 和16位字大小。
    //
    
    SPI_setConfig (SPIB_BASE、DEVICE_LSPCLK_FREQ、SPI_PROT_POL0PHA1、
    SPI_MODE_MASTER、BAUD_RATE、16);
    SPI_disableLoopback (SPIB_BASE);
    SPI_setEmulationMode (SPIB_BASE、SPI_emulation_stop_after_transmit);
    
    //FIFO
    
    SPI_enableFIFO (SPIB_BASE);
    
    SPI_enableModule (SPIB_BASE);
    
    }
    
    void ads_sys_command (uint16_t 命令)
    {
    GPIO_writePin (SPI_CS_1、0);
    SPI_CYCLE (18 *波特率/DEVICE_SYSCLK_FREQ);
    
    命令=命令<<8;
    SPI_writeDataNonBlocking (SPIB_BASE、COMMAND);
    
    SPI_CYCLE (18 *波特率/DEVICE_SYSCLK_FREQ);
    GPIO_writePin (SPI_CS_1、1);
    }
    
    void ads_write_reg (uint16_t address、uint16_t reg_data)
    {
    
    GPIO_writePin (SPI_CS_1、0);
    SPI_CYCLE (18 *波特率/DEVICE_SYSCLK_FREQ);
    
    地址=(0x40|地址)<<8;
    REG_DATA = REG_DATA <<8;
    SPI_writeDataNonBlocking (SPIB_BASE、地址);
    SPI_writeDataNonBlocking (SPIB_BASE、REG_DATA);
    
    SPI_CYCLE (18 *波特率/DEVICE_SYSCLK_FREQ);
    GPIO_writePin (SPI_CS_1、1);
    }
    
    uint16_t ads_read_reg (uint16_t 地址)
    {
    uint16_t dummy_data = 0x00;
    uint16_t RDATA[3];
    字符 I = 0;
    
    GPIO_writePin (SPI_CS_1、0);
    SPI_CYCLE (18 *波特率/DEVICE_SYSCLK_FREQ);
    
    地址=(0x20|地址)<<8;
    SPI_writeDataNonBlocking (SPIB_BASE、地址);
    SPI_writeDataNonBlocking (SPIB_BASE、dummy_data);
    
    SPI_CYCLE (18 *波特率/DEVICE_SYSCLK_FREQ);
    GPIO_writePin (SPI_CS_1、1);
    
    对于(i=0;i<4;i++)
    {
    RDATA[i]= SPI_readDataNonBlocking (SPIB_BASE);
    }
    返回(RDATA[2]);
    }
    
    void ads_reset ()
    {
    ADS_SYS_COMMAND (ADS_RESET);
    
    ADS_SYS_COMMAND (ADS_SDATAC);
    
    if (ads_read_reg (ID)!= ID_value)
    {
    while (1)
    {
    
    }
    }
    
    #ifndef SPI_ADS_H_
    #define SPI_ADS_H_
    
    #include "driverlib.h"
    #include "device.h"
    
    typedef char uint8_t;
    
    #define SPI_cycle_NOP0 (n)_asm (" RPT #("#n ")|| NOP")
    #define SPI_cycle_NOP_0_NOP_RATE (n)#define SPI_RATE (n_NOP_0_NOP
    
    )#define P波特 率(n_NOP (n_NOP) 1000000
    
    #define SPI_MOSI 63
    #define SPI_MISO 64
    #define SPI_CLK 65
    #define SPI_CS_1 66
    
    #define ID_VALUE 0x62
    
    #define ID 0x00
    #define CONFIG1 0x01
    #define CONFIG2 0x02
    #define CONFIG3 0x03
    #define LOFF 0x04
    
    #define CH1SET 0x05
    #define CH2SET 0x06
    #define CH3SET 0x07
    #define CH4SET 0x08
    #define CH5SET 0x09
    #define CH6SET 0x0A
    #define CH7SET 0x0B
    #define CH8SET 0x0C
    
    #define RLD_SENSP 0x0D
    #define RLD_SENSN 0x0E
    #define LOFF_SENSP 0x0F
    #define LOFF_SENSN 0x10
    #define LOFF_FLIP 0x11
    
    #define LOFF_STATP 0x12
    #define LOFF_STATN 0x13
    
    #define GPIO 0x14
    #define PACE 0x15
    #define RESP 0x16
    #define CONFIG4 0x17
    #define WCT1 0x18
    #define WCT2 0x19
    
    #define ADS_WAKEUP 0x02
    #define ADS_STANDBY 0x04
    #define ADS_RESET 0x06
    #define ADS_START 0x08
    #define ADS_STOP 0x0A
    #define ADS_RDATAC 0x10
    #define ADS_SDATAC 0x11
    #define ADS_RDATA 0x12
    
    void init_spi_ads (void);
    void ads_sys_command (uint16_t 命令);
    void ads_write_reg (uint16_t address、uint16_t reg_data);
    uint16_t ads_read_reg (uint16_t address);
    void ads_reset (空);
    
    #endif /* SPI_ADS_H_* 

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

    您好、Matheus、

    请在下面找到我的答案:

    1) 1)使用 SPI 的 FIFO 时是否需要使用中断?
    [Praveen]:是的,如果 CPU 带宽受限,可以选择使用中断。 对于 FIFO 配置、您可以参阅 c2000ware 中的 SPI_ex2_loopback_fifo_interrupts 示例。
     
    2) 2)启用 FIFO 时、8位字 SPI 是否正常工作? 因为正如我在程序上看到的、它仅在缓冲区获得16位时开始传输、即使我更改为8位字 SPI 配置也是如此。
    [Praveen]:是的、FIFO 适用于 SPICHAR 寄存器的所有有效配置。 请参阅 TRM 中 SPI 章节下的"数据格式"部分。
    必须根据 TX/RXBUF 对数据进行正确对齐

    3) 3)我不习惯与 FIFO 一起工作。 据我所知、没有填充 FIFO 的指令和其他用于启动 SPI 传输的指令、有吗?
    [Praveen]:没有、如果移位寄存器空闲、任何写入 FIFO 的操作都会触发一个传输。

    此致、
    Praveen

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

    您好、Matheus、

    由于我们没有听到您长达一周的声音、我们假设您的疑问已得到解决。 我将该线程移至"已解决"状态。

    如果您仍面临此问题、您可以拒绝该解决方案并回复此主题。 如果线程锁定、请创建新线程

    此致、
    Praveen