主题中讨论的其他器件: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);
}