最近学习英飞凌的TC264相关知识,在使用时需要用到带DMA的SPI通信,但是逐飞和龙邱等主流的库当中的SPI都没有使用DMA功能,于是去学习iLLD库,由于是全英文的,并且网上相关资料太少,在学习时踩了不少坑。这里SPI协议、DMA之类的基础知识就不讲了。笔者对单片机了解不是很透彻,下面内容中可能有许多错误,望读者指正。
1.1使用TC264的iLLD库的时候,首先使用有道翻译之类的软件进行翻译,看的时候同时对比英文版和中文版,只看机翻可能会导致部分代码被翻译了或者理解出错。
1.2iLLD例程中提到的头文件包含只讲了这个头文件本身,在调用某些函数要注意一下添加相应的头文件。
1.3iLLD例程中IfxCpu_Irq_installInterruptHandler这个函数是否调用和中断管理模式(?)有关,在龙邱和逐飞的库中无需调用。
宏定义
#define SPI_BUFFER_SIZE //发送长度
#define BAUD //设置波特率
//中断优先级 设置时主要不要冲突
#define IFX_INTPRIO_QSPI0_TX 99 // DMA channel 1
#define IFX_INTPRIO_QSPI0_RX 100 // DMA channel 2
#define IFX_INTPRIO_QSPI0_ER 0x30
#define IFX_INTPRIO_DMA_CH1 101
#define IFX_INTPRIO_DMA_CH2 102
首先为收发定义两个数组,在发送时请直接调用发送数组,以减少CPU的占用。
//为数据传输声明全局传输和接收缓冲区
uint8 spiTxBuffer [SPI_BUFFER_SIZE];
uint8 spiRxBuffer [SPI_BUFFER_SIZE];
设置相关变量
IfxQspi_SpiMaster spi;
IfxQspi_SpiMaster_Channel spiChannel;
IfxQspi_SpiMaster_ChannelConfig spiMasterChannelConfig;
IfxQspi_SpiMaster_Config spiMasterConfig;
IFX_INTERRUPT(qspi0TxISR, 0, IFX_INTPRIO_QSPI0_TX)
{
IfxQspi_SpiMaster_isrTransmit(&spi);
}
IFX_INTERRUPT(qspi0RxISR, 0, IFX_INTPRIO_QSPI0_RX)
{
IfxQspi_SpiMaster_isrReceive(&spi);
}
IFX_INTERRUPT(qspi0DmaTxISR, 0, IFX_INTPRIO_DMA_CH1 )
{
IfxQspi_SpiMaster_isrDmaTransmit(&spi);
}
IFX_INTERRUPT(qspi0DmaRxISR, 0, IFX_INTPRIO_DMA_CH2)
{
IfxQspi_SpiMaster_isrDmaReceive(&spi);
}
IFX_INTERRUPT(qspi0ErISR, 0, IFX_INTPRIO_QSPI0_ER)
{
IfxQspi_SpiMaster_isrError(&spi);
}
//创建模块配置
IfxQspi_SpiMaster_initModuleConfig(&spiMasterConfig, &MODULE_QSPI3); //注意 改模块时这里也要改 例程中为MODULE_QSPI0
//设置所需的模式和最大波特率
spiMasterConfig.base.mode = SpiIf_Mode_master; //主机
spiMasterConfig.base.maximumBaudrate = 10000000;
// ISR优先级和中断目标(带有Dma使用)
spiMasterConfig.base.txPriority = IFX_INTPRIO_DMA_CH1;
spiMasterConfig.base.rxPriority = IFX_INTPRIO_DMA_CH2;
spiMasterConfig.base.erPriority = IFX_INTPRIO_QSPI0_ER;
//dma配置
spiMasterConfig.dma.txDmaChannelId = IfxDma_ChannelId_1;
spiMasterConfig.dma.rxDmaChannelId = IfxDma_ChannelId_2;
spiMasterConfig.dma.useDma = 1;
//引脚配置
const IfxQspi_SpiMaster_Pins pins = {
&IfxQspi3_SCLK_P33_11_OUT , IfxPort_OutputMode_pushPull, // SCLK 例程为IfxQspi0_SCLK_P20_11_OUT
&IfxQspi3_MTSR_P33_12_OUT, IfxPort_OutputMode_pushPull, // MTSR 例程为IfxQspi0_MTSR_P20_14_OUT
&IfxQspi3_MRSTD_P33_13_IN , IfxPort_InputMode_pullDown, // MRST 例程为IfxQspi0_MRSTA_P20_12_IN
IfxPort_PadDriver_cmosAutomotiveSpeed3 // pad driver mode
};
spiMasterConfig.pins = &pins;
//初始化模块
IfxQspi_SpiMaster_initModule(&spi, &spiMasterConfig);
/*安装中断处理器 不使用
* IfxCpu_Irq_installInterruptHandler (&qspi0TxISR IFX_INTPRIO_QSPI0_TX);
* IfxCpu_Irq_installInterruptHandler (&qspi0RxISR IFX_INTPRIO_QSPI0_RX);
* IfxCpu_Irq_installInterruptHandler (&qspi0ErISR IFX_INTPRIO_QSPI0_ER);
* IfxCpu_enableInterrupts ();
*/
//创建通道配置
IfxQspi_SpiMaster_initChannelConfig(&spiMasterChannelConfig, &spi);
//设置该通道的波特率
spiMasterChannelConfig.base.baudrate = BAUD;
//选择引脚配置
const IfxQspi_SpiMaster_Output slsOutput = {
&IfxQspi3_SLSO7_P33_7_OUT, //cs 例程为IIfxQspi0_SLSO7_P33_5_OUT
IfxPort_OutputMode_pushPull,
IfxPort_PadDriver_cmosAutomotiveSpeed1
};
spiMasterChannelConfig.sls.output = slsOutput;
spiMasterChannelConfig.mode = IfxQspi_SpiMaster_Mode_short;
//初始化通道
IfxQspi_SpiMaster_initChannel(&spiChannel, &spiMasterChannelConfig);
至此,初始化完成。
不需要发送的数据或者收到的数据使用NULL_PTR:
//发送和接收数据流:
//等待前一个数据流的传输完成
while(IfxQspi_SpiMaster_getStatus(&spiChannel) == SpiIf_Status_busy);
//接收新流
IfxQspi_SpiMaster_exchange(&spiChannel, spiTxBuffer, spiTxBuffer, SPI_BUFFER_SIZE);
//只发送,丢弃接收到的数据:
//等待前一个数据流的传输完成
while(IfxQspi_SpiMaster_getStatus(&spiChannel) == SpiIf_Status_busy);
//发送新流
IfxQspi_SpiMaster_exchange(&spiChannel, &spiTxBuffer[i], NULL_PTR, SPI_BUFFER_SIZE);
//只接收
//等待前一个数据流的传输完成
while(IfxQspi_SpiMaster_getStatus(&spiChannel) == SpiIf_Status_busy);
//接收新流
IfxQspi_SpiMaster_exchange(&spiChannel, NULL_PTR, &spiRxBuffer[i], SPI_BUFFER_SIZE);