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.

[FAQ] SPI 配置和使用

Other Parts Discussed in Thread: TMS320F280049C

主题中讨论的其他器件:TMS320F280049C

将 BLDC 电机驱动器与 SPI 配合使用时,务必从 MCU 正确设置 SPI 设置,以匹配所需的格式,并与 DRV 器件正确通信。此常见问题解答演示了在 BLDC 电机驱动器应用中使用 SPI 时所需的硬件连接和 SPI 设置。

SPI 硬件

下图列出了从 MCU 到 DRV 器件所需的 SPI 总线连接:

标准名称

缩写名称

TI MCU

DRV SPI 引脚

主输出辅输入

(此前称为主输出从输入)

MOSI

SIMO

SDI

主输入辅输出

(此前称为主输入从输出)

MISO

SOMI

SDO

SPI 时钟

SCK

SCK

SCLK

SPI 芯片选择

CS 或 SS

STE

nSCS

确保查看数据表,确定每个 SPI 引脚是否需要外部上拉或下拉电阻器,或者是否配置为推挽引脚。

SPI 设置

有效的 SPI 帧必须满足 DRV 数据表“SPI 编程”部分规定的多种条件。通常,有效的 SPI 帧必须满足以下条件:

-          当 nSCS 引脚从高电平转换为低电平,以及从低电平转换为高电平时,SCLK 引脚应该为低电平

-          当 nSCS 引脚被拉为高电平时,SCLK 和 SDI 引脚上的任何信号都将被忽略,并且 SDO 引脚处于高阻态

-          数据会在 SCLK 引脚的下降沿被捕捉,并在 SCLK 引脚的上升沿被传输

-          必须进行完整的 16 个 SCLK 周期,事务才有效

-          如果发送到 SDI 引脚的数据字不到 16 位或多于 16 位,会发生帧错误并且数据字会被忽略

有关如何使用 TMS320F280049C C2000 MCU 配置 SPI 的示例,请参阅“SPI 示例”中的 Config_EVM_SPI () 函数。

SPI /

数据表的“SPI 格式”部分介绍了通过 SDI 引脚传入数据字的 16 位格式。所有 DRV 器件通常具有 1 个读取或写入位 (R/W)、多个地址位和数据位。

在固件的 SPI 读取和 SPI 写入函数中,请确保生成正确的控制字:将地址位移动到控制字中地址开始的正确位置,并使用 R/W 位(如果执行读取命令)或数据位(如果执行写入命令)进行逻辑或运算。

例如,在 DRV832x SPI 器件中,SDI 和 SDO 数据字格式如下:

要执行写入操作,必须将大小为 4 位的地址向左移动 11 ,将位 3 移动到位 14,地址的 MSB 需要在该位置。数据应该用 0xFF 屏蔽并进行逻辑或运算,以免丢失 R/W 位和地址位的内容。

要执行读取操作,必须将大小为 4 位的地址向左移动 11 ,将位 3 移动到位 14,地址的 MSB 需要在该位置。R/W 位(1 表示读取)可向左移 15 位,与 B15 保持一致;还可将控制字与 0x8000 进行逻辑或运算,将 R/W 设为 1。

DRV832x 的 SPI 读取和写入命令示例可在下面的 SPI 示例中找到。

SPI 示例

以下是使用 TMS320F280049C C2000 MCU 的 SPI 和典型 DRV 栅极驱动器器件进行配置、读取和写入的示例。

void Config_evm_spi(void)
{
//Pin Config
EALLOW;
// SPI_MOSI
GPIO_SetupPinOptions(16, GPIO_INPUT, GPIO_ASYNC | GPIO_PULLUP);
// SPI_MISO
GPIO_SetupPinOptions(17, GPIO_INPUT, GPIO_ASYNC | GPIO_PULLUP);
// SPI_CS
GPIO_SetupPinOptions(56, GPIO_INPUT, GPIO_ASYNC | GPIO_PULLUP);
// SPI_CLK
GPIO_SetupPinOptions(57, GPIO_INPUT, GPIO_ASYNC | GPIO_PULLUP);

GPIO_SetupPinMux(16, GPIO_MUX_CPU1, 1);
GPIO_SetupPinMux(17, GPIO_MUX_CPU1, 1);
GPIO_SetupPinMux(56, GPIO_MUX_CPU1, 1);
GPIO_SetupPinMux(57, GPIO_MUX_CPU1, 1);
EDIS;

EALLOW;
ClkCfgRegs.LOSPCP.all = 0;
EDIS;

// 初始化 SPI FIFO 寄存器
SpiaRegs.SPIFFTX.all=0xE040;
SpiaRegs.SPIFFRX.all=0x2044;
SpiaRegs.SPIFFCT.all=0x0;

//SPI 设置
SpiaRegs.***.bit.SPISWRESET = 0; //SPI 复位
SpiaRegs.***.bit.CLKPOLARITY = 0; //SCLK 高电平有效
SpiaRegs.***.bit.*** = 0xF; //16 位 SPI 字符
SpiaRegs.***.bit.SPILBK = 0;

SpiaRegs.***.bit.OVERRUNINTENA = 0; //无超限中断
SpiaRegs.***.bit.CLK_PHASE = 0; //相位 0
SpiaRegs.***.bit.MASTER_SLAVE = 1; //主模式,变量名称尚未根据最新命名规则更新
SpiaRegs.***.bit.TALK = 1; //nSCS 启用
SpiaRegs.***.bit.SPIINTENA = 0; //TX/RX 中断禁用

SpiaRegs.SPIBRR.bit.SPI_BIT_RATE = ((25000000 / 1000000) - 1); //将波特率设为 1MHz
SpiaRegs.SPIPRI.bit.FREE = 1; //进行设置,使断点不会干扰传输
SpiaRegs.***.bit.SPISWRESET = 1; //退出 SPI 复位

}

 

Uint16 spi_xmit(Uint16 spiFrame)

{

   SpiaRegs.SPITXBUF=spiFrame;

 

   //等待 RX 标志指示 SPI 帧完成

   while(SpiaRegs.SPIFFRX.bit.RXFFST != 1)

   {

   }

 

   return SpiaRegs.SPIRXBUF;

}

 

Uint16 spi_read(Uint16 addr)

{

   Uint16 commandword = (0x8000 | (addr << 11));

   return spi_xmit(commandword);

}

 

Uint16 spi_write(Uint16 addr, Uint16 data)

{

   Uint16 commandword = ((addr << 11) | data);

   return spi_xmit(commandword);

}