【通讯协议】TC275芯片——SPI通讯配置

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

随着电机控制领域的不断发展,通讯方式也越来越重要,选择合适的通讯方式对获取电机实时的电机参数有着重要的意义,而我们今天介绍的SPI通讯是电机与as5047p编码器之间进行数据传输的关键。


一、SPI通讯原理

SPI是串行外设接口(Serial Peripheral Interface)的缩写,是一种高速、全双工、同步通信总线,所以可以在同一时间发送和接收数据,SPI没有定义速度限制,通常能达到甚至超过10M/bps。
SPI有主、从两种模式,通常由一个主模块和一个或多个从模块组成(SPI不支持多主机),今天我们介绍的是单主机从机通讯即TC275芯片作为主机与从机as5047p编码器之间进行数据交换,如图所示。

在这里插入图片描述

SPI通信至少需要四根线,它们是MISO(主设备数据输入)、MOSI(主设备)、SCLK(时钟)、和CS/SS(片选):

  • MISO(Master Input Slave Output):主设备数据输入,从设备数据输出;
  • MOSI(Master Output Slave Input):主设备数据输出,从设备数据输入;
  • SCLK(Serial Clock):时钟信号,由主设备产生;
  • CS/SS(Chip Select/Slave Select):从设备使能信号,由主设备控制,一主多从时,CS/SS是从芯片是否被主芯片选中的控制信号,只有片选信号为预先规定的使能信号时(高低位或低电位),主芯片对此从芯片的操作才有效。
    在这里插入图片描述
    这里简单介绍了SPI通信基本的工作原理,如果想要深入了解SPI通讯可以参考下面这篇文章:深入了解SPI通讯

二、相关代码配置

先在英飞凌的IDE中导入有关SPI通信的代码,这里我以TC275芯片为例导入SPI通信例程,如图所示:
在这里插入图片描述
主要在引脚,时钟参数,数据交换代码这三方面来介绍代码的配置方式。

1.引脚及片选相关配置

代码如下:

#define CSPin	&MODULE_P33,10

void initQSPI3Master(void)
{
    IfxQspi_SpiMaster_Config spiMasterConfig;                           /* Define a Master configuration            */

//    IfxQspi_SpiMaster_initModuleConfig(&spiMasterConfig, QSPI1_MASTER); /* Initialize it with default values        */
    IfxQspi_SpiMaster_initModuleConfig(&spiMasterConfig, QSPI3_MASTER);

    spiMasterConfig.base.mode = SpiIf_Mode_master;                      /* Configure the mode                       */

    /* Select the port pins for communication */
    const IfxQspi_SpiMaster_Pins qspi3MasterPins = {
//        &IfxQspi1_SCLK_P10_2_OUT, IfxPort_OutputMode_pushPull,          /* SCLK Pin                       (CLK)     */
//        &IfxQspi1_MTSR_P10_3_OUT, IfxPort_OutputMode_pushPull,          /* MasterTransmitSlaveReceive pin (MOSI)    */
//        &IfxQspi1_MRSTA_P10_1_IN, IfxPort_InputMode_pullDown,           /* MasterReceiveSlaveTransmit pin (MISO)    */
        &IfxQspi3_SCLK_P33_11_OUT, IfxPort_OutputMode_pushPull,           /* SCLK Pin                       (CLK)     */
        &IfxQspi3_MTSR_P33_12_OUT, IfxPort_OutputMode_pushPull,           /* MasterTransmitSlaveReceive pin (MOSI)    */
        &IfxQspi3_MRSTD_P33_13_IN, IfxPort_InputMode_pullDown,          /* MasterReceiveSlaveTransmit pin (MISO)    */
        IfxPort_PadDriver_cmosAutomotiveSpeed3                          /* Pad driver mode                          */
    };
    spiMasterConfig.pins = &qspi3MasterPins;                            /* Assign the Master's port pins            */

    /* Set the ISR priorities and the service provider */
    spiMasterConfig.base.txPriority = ISR_PRIORITY_MASTER_TX;
    spiMasterConfig.base.rxPriority = ISR_PRIORITY_MASTER_RX;
    spiMasterConfig.base.erPriority = ISR_PRIORITY_MASTER_ER;
    spiMasterConfig.base.isrProvider = IfxSrc_Tos_cpu0;

    /* Initialize the QSPI Master module */
    IfxQspi_SpiMaster_initModule(&g_qspi.spiMaster, &spiMasterConfig);
}

这里按照自己所需配置SPI的四根引脚,MISO,MOSI,SCLK以及CS,其中尤其要注意的是需要自己配置片选的引脚#define CSPin &MODULE_P33,10.

2.时钟参数的配置

代码如下:

void initQSPI3MasterChannel(void)
{
    IfxQspi_SpiMaster_ChannelConfig spiMasterChannelConfig;             /* Define a Master Channel configuration    */

    /* Initialize the configuration with default values */
    IfxQspi_SpiMaster_initChannelConfig(&spiMasterChannelConfig, &g_qspi.spiMaster);

    spiMasterChannelConfig.base.baudrate = MASTER_CHANNEL_BAUDRATE;     /* Set SCLK frequency to 1 MHz              */
    spiMasterChannelConfig.base.mode.dataHeading = SpiIf_DataHeading_msbFirst;
    spiMasterChannelConfig.base.mode.dataWidth = 16;
    spiMasterChannelConfig.base.mode.shiftClock = 1;// 相位
    spiMasterChannelConfig.base.mode.clockPolarity = 0; //极性
    spiMasterChannelConfig.base.mode.autoCS=0;

    /* Select the port pin for the Chip Select signal */
    const IfxQspi_SpiMaster_Output qspi3SlaveSelect = {                 /* QSPI1 Master selects the QSPI3 Slave     */
//        &IfxQspi1_SLSO9_P10_5_OUT, IfxPort_OutputMode_pushPull,         /* Slave Select port pin (CS)               */
        &IfxQspi3_SLSO11_P33_10_OUT, IfxPort_OutputMode_pushPull,
        IfxPort_PadDriver_cmosAutomotiveSpeed1                          /* Pad driver mode                          */
    };
    spiMasterChannelConfig.sls.output = qspi3SlaveSelect;

    /* Initialize the QSPI Master channel */
    IfxQspi_SpiMaster_initChannel(&g_qspi.spiMasterChannel, &spiMasterChannelConfig);
}
  • 根据as5147p芯片手册,设置时钟极性为0,即时钟空闲的默认状态为低电平,设置时钟相位为1,即在时钟信号SCK的第二个跳变沿采样,所以数据采样时机是在一个波形下降沿如图所示。
  • 如图所示,需要发送16bits的数据,因此设置数据大小为16位,同时由于数据传输顺序为最高位优先,因此设置dataHeading SpiIf_DataHeading_msbFirst
  • 如下图所示,由于需要满足特殊的时序要求,因此令autoCS=0选择软件手动控制片选信号,在后面的发送函数会有代码实现。
  • SPI通讯频率可以需求设置,受限于每个系统能提供多大的系统时钟频率,以及最大的SPI传输速率,这里的波特率我设置为800KHZ。
    在这里插入图片描述

3.数据交换

void transferData(void)
{
    IfxPort_setPinModeOutput(CSPin, IfxPort_OutputMode_pushPull, IfxPort_OutputIdx_general);
    IfxPort_setPinLow(CSPin);

        uint32 ticks = IfxStm_getTicksFromMilliseconds(&MODULE_STM0, 10);
        IfxStm_waitTicks(&MODULE_STM0, ticks);

        g_qspi.spiBuffers.spiMasterTxBuffer[0] = 0xFFFF;
        //g_qspi.spiBuffers.spiMasterTxBuffer[1] = 0xFF;

//        for(int i = 0; i < 1; i++)
       {
            while(IfxQspi_SpiMaster_getStatus(&g_qspi.spiMasterChannel) == SpiIf_Status_busy);

            IfxQspi_SpiMaster_exchange(&g_qspi.spiMasterChannel, &g_qspi.spiBuffers.spiMasterTxBuffer[0],  &g_qspi.spiBuffers.spiSlaveRxBuffer[0], 1);
            while(IfxQspi_SpiMaster_getStatus(&g_qspi.spiMasterChannel) == SpiIf_Status_busy);
        }


        IfxPort_setPinModeOutput(CSPin, IfxPort_OutputMode_pushPull, IfxPort_OutputIdx_general);
        IfxPort_setPinHigh(CSPin);
//
//        ticks = IfxStm_getTicksFromMilliseconds(&MODULE_STM0, 10);
//        IfxStm_waitTicks(&MODULE_STM0, ticks);

}

这里我通过SPI通信对as5047p编码器发送0xFFFF获取电机绝对位置信息(有时间我会更一篇关于as5047p编码器SPI通信获取位置的文章),这里和例程不一样的是:

  • 在发送信息前后都手动拉高和拉低了片选信号,拉低数据开始传输,拉高数据传输结束
  • 第一个Busy状态,等待SPI通道准备好,第二个Busy状态,等待数据传输完成
  • 同时自己修改了发送数组spiBuffers.spiSlaveRxBuffer[0],从8位修改为16位,以及下面这个交换函数:
   IfxQspi_SpiMaster_exchange(&g_qspi.spiMasterChannel, &g_qspi.spiBuffers.spiMasterTxBuffer[0],  &g_qspi.spiBuffers.spiSlaveRxBuffer[0], 1);
  • g_qspi.spiBuffers.spiMasterTxBuffer[0]指向发送缓冲区的指针,表示要发送的数据的起始地址,g_qspi.spiBuffers.spiSlaveRxBuffer[0]是一个指向接收缓冲区的指针,表示存储接收到的数据的位置,1表示发送Buffer数组个数

最终成功实现了SPI通讯获取了电机位置(这些都是自己查资料和不断调试最终试出来的,都是泪啊),大家如果发现SPI通信未通,可以尝试一下我这种方式。下面看看我出来的波形吧,蓝色为时钟信号,绿色为MOSI信号:
在这里插入图片描述

总结

TC275芯片的SPI配置无非就是一些引脚配置,以及与SPI相关的特定参数配置例如片选,时钟参数等,其中最关键就是要读懂芯片提供的例程中SPI通信实现的逻辑,这个是最重要的,引脚等配置是提供了一个好的平台,而如何使用则在于你对一些函数API的调用。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值