有关AutoSar中对于Spi模块的相关描述可参考:Autosar MCAL-SPI配置及使用_spi总线的mcal配置-优快云博客
配置Spi模块前,往往要参考从机芯片的芯片手册和项目需求,确定通讯参数。

PhyUnit、 Channel、 ExternalDevice、 Job和Sequence的关系如下图所示:

Spi功能的配置顺序为:
- 配置Port模块中MISIO、MOSI、CLK和CS四个引脚。
- 配置ExternalDevice,并关联要使用的Spi硬件单元。
- 配置Channel。
- 配置Job,包含进去一个或多个Channel,并关联一个ExternalDevice。
- 配置Sequence,包含进去一个或多个job。
Port配置
MISO

MOSI

CLK

CS

SpiExternalDevice配置
SpiExternalDevice中主要配置通讯相关的大部分Spi硬件参数。

SpiHWUnit配置

选择关联的Spi硬件单元:SCB0-SCB10。
时钟参考点与波特率配置
首先要到MCU模块中配置SCB3的PCLK时钟。

接着配置SCB3的时钟参考点。

在SpiExternalDevice中引用参考点。

波特率能配置的最大值为参考的PCLK值除以4,最小值为PCLK除以16。
(建议参考的PCLK配置频率小一些,否则可能会出现输出时钟占空比不为50%的情况)。
片选配置

-
SpiEnableCs:是否需要控制CS。勾选该选项后,下面两项才可配置。
-
SpiCsSection:选择CS_VIA_PERIPHERAL_ENGINE(通过硬件外设控制)
或者CS_VIA_GPIO(通过Spi驱动程序的通用IO控制)。
-
SpiCsIdentifier:若通过GPIO控制,则该项选择的是Dio模块中配置的通道。
若通过硬件外设控制,则该项选择的是SPI_SELECT0-SPISELECT3。
片选极性、时钟相位、时钟极性配置
SpiEnableCs中选择CS_VIA_PERIPHERAL_ENGINE才需要配置这三项。
- SpiCsPolarity:片选极性,即Cs引脚有效时输出高电平还是低电平。
- SpiDataShiftEdge:选择LEADING,在第二个边沿输出数据,第一个边沿采样数据,对应CPHA=0。
选择TRALING,在第一个边沿输出数据,第二个边沿采样数据,对应CPHA=1。
(CPHA= 0和CPHA= 1的区别可参考SPI中的CPHA,CPOL详解-优快云博客。)
- SpiShiftClockIdleLevel:时钟极性,即CLK时钟空闲时的电平为高或低。

SetupDelay、HoldupDelay配置
- SpiSetupDelay:开始传输数据时第一次选中CS到第一次拉高时钟线的时间,
- SpiHoldDelay:传输数据完成释放时钟线到释放CS的时间。

EB中SpiSetupDelay可设置为1.25或0.25,SpiHoldDelay可设置为1.75或0.75,表示的是相对于CLK一个时钟周期的倍数。

SpiChannel配置
- SpiChannelType:通道类型,EB(外部通道)/IB(内部通道)。
EB和IB区别如下:
| 类型 | 区别 |
|---|---|
| EB | 收发数据的buffer由用户(静态/动态的)提供,数据长度可输入 |
| IB | 收发数据的buffer由SPI Driver提供,数据长度固定 |
- SpiDataWidth:数据宽度,等价于传输数据的帧大小。
- SpiDefaultData:当传递给Spi_WriteIB(对于内部缓冲区)或Spi_SetupEB(对于外部缓冲区)的指针为NULL 时,要传输的默认数据。
- SpiEbMaxLength:当配置为EB类型时,允许通过Spi_SetupEB( )设置的最大数据长度。
- SpiIbNBuffers:当配置为IB类型时,Spi驱动程序内部为通道分配的缓冲区长度。
** 举例:当选择DataWidth为8,IbNBuffers为10时,Spi驱动程序内部将生成类型为uint8,长度为10的接收数组和发送数组;当选择DataWidth为16,IbNBuffers为10时,程序内部将生成类型为uint8,长度为20的接收数组和发送数组。**
.
- SpiTransferStart :每一帧数据的传输方向,MSB(先传输高位)/LSB(先传输低位)。
假如要发送的数据为0101,MSB会按0101的顺序发送,LSB则是按1010的顺序发送。
SpiJob配置
-
SpiHwUnitSynchronous:设置为SYNCHRONOUS,SpiJob以同步方式使用驱动程序(使用Spi_SyncTransmit( )传输数据)。
设置为ASYNCHRONOUS,SpiJob以异步方式使用驱动程序(使用
Spi_AsyncTransmit( )传输数据)。 -
SpiJobEndNotification:选择是否开启Job结束中断函数,开启则需要填入函数的名称。
-
SpiJobPriority:Job优先级,可设置1-3。
Job被认为是原子的,不能被打断。但是含有更高优先级Job的Sequence可以打断当前Sequence。

- SpiDeviceAssignment :引用要关联的ExternalDevice。

在ChannelList中引用要包含的Channel。
SpiSequence配置

- SpiInterruptibleSequence:是否允许该序列被其他序列打断。
- SpiSeqEndNotification:选择是否开启序列结束中断函数,开启则需要填入函数的名称。

在jobAssignment中引用要包含的Job。
SpiGeneral配置
SpiChannelBuffersAllowed :选择允许分配的缓冲区类型。
- 0:只允许内部缓冲区IB。
- 1:只允许外部缓冲区EB。
- 3:同时允许内部缓冲区IB和外部缓冲区EB。

SpiLevelDelivered :Spi驱动程序传输等级。
- 0:简单同步SPI处理程序/驱动程序,只允许同步方式。
- 1:基本异步SPI处理器/驱动程序,只允许异步方式。
- 3:增强的(同步/异步)SPI处理器/驱动程序。
使用示例
同步传输、EB
初始化
Std_ReturnType Ret_Val1,Ret_Val2;
Spi_DataBufferType u8TXBuff[4U] = {0x66u,0x77u,0x66u,0x77u};/*发送缓冲区*/
Spi_DataBufferType u8RXBuff[4U] ; /*接收缓冲区*/
void bsp_Init_1(void)
{
Mcu_Init(&McuConf_McuModuleConfiguration_McuModuleConfiguration_0);
Mcu_SetMode(McuConf_McuModeSettingConf_McuModeSetting_CM7_0_Active);
Mcu_InitClock(McuConf_McuClockSettingConfig_McuClockSettingConfig_Active);
while(Mcu_GetPllStatus() != MCU_PLL_LOCKED)
{
}
Mcu_DistributePllClock();
Port_Init(&PortConf_PortConfigSet_PortConfigSet_0); /* PORT 初始化 */
Spi_Init(NULL); /* Spi 初始化 */
/* Cpt 初始化,开启10ms中断函数 */
Gpt_Init(&GptConf_GptChannelConfigSet_GptChannelConfigSet_0);
Gpt_EnableNotification(GptConf_GptChannelConfiguration_Timer_16bit_1kHz);
Gpt_StartTimer(GptConf_GptChannelConfiguration_Timer_16bit_1kHz, 10-1);
}
在10ms中断函数中调用
void Gpt_Notification_Timer_16bit_1KHz(void)
{
Ret_Val1 = Spi_SetupEB(SpiChannel_HSD_1,u8TXBuff,u8RXBuff,4U);/*设定EB通道的数据,长度为4*/
Ret_Val2 = Spi_SyncTransmit(SpiSequence_HSD_1);/*同步方式传输序列*/
}
同步传输、IB
初始化
Std_ReturnType Ret_Val1,Ret_Val2,Ret_Val3;
Spi_DataBufferType u8TXBuff[4U] = {0x66u,0x77u,0x66u,0x77u};/*发送缓冲区*/
Spi_DataBufferType u8RXBuff[4U] ; /*接收缓冲区*/
void bsp_Init_1(void)
{
Mcu_Init(&McuConf_McuModuleConfiguration_McuModuleConfiguration_0);
Mcu_SetMode(McuConf_McuModeSettingConf_McuModeSetting_CM7_0_Active);
Mcu_InitClock(McuConf_McuClockSettingConfig_McuClockSettingConfig_Active);
while(Mcu_GetPllStatus() != MCU_PLL_LOCKED)
{
}
Mcu_DistributePllClock();
Port_Init(&PortConf_PortConfigSet_PortConfigSet_0); /* PORT 初始化 */
Spi_Init(NULL); /* Spi 初始化 */
/* Cpt 初始化,开启10ms中断函数 */
Gpt_Init(&GptConf_GptChannelConfigSet_GptChannelConfigSet_0);
Gpt_EnableNotification(GptConf_GptChannelConfiguration_Timer_16bit_1kHz);
Gpt_StartTimer(GptConf_GptChannelConfiguration_Timer_16bit_1kHz, 10-1);
}
在10ms中断函数中调用
void Gpt_Notification_Timer_16bit_1KHz(void)
{
Ret_Val1 = Spi_WriteIB(SpiChannel_HSD_1,u8TXBuff);/*设定IB通道发送缓冲区*/
Ret_Val2 = Spi_SyncTransmit(SpiSequence_HSD_1);/*同步传输*/
Ret_Val3 = Spi_ReadIB(SpiChannel_HSD_1,u8RXBuff);/*读取IB通道数据到接收缓冲区*/
}
异步中断传输、EB
初始化
Std_ReturnType Ret_Val1,Ret_Val2;
Spi_DataBufferType u8TXBuff[4U] = {0x66u,0x77u,0x66u,0x77u};/*发送缓冲区*/
Spi_DataBufferType u8RXBuff[4U] ; /*接收缓冲区*/
void bsp_Init_1(void)
{
Mcu_Init(&McuConf_McuModuleConfiguration_McuModuleConfiguration_0);
Mcu_SetMode(McuConf_McuModeSettingConf_McuModeSetting_CM7_0_Active);
Mcu_InitClock(McuConf_McuClockSettingConfig_McuClockSettingConfig_Active);
while(Mcu_GetPllStatus() != MCU_PLL_LOCKED)
{
}
Mcu_DistributePllClock();
Port_Init(&PortConf_PortConfigSet_PortConfigSet_0); /* PORT 初始化 */
Spi_Init(NULL); /* Spi 初始化 */
Spi_SetAsyncMode(SPI_INTERRUPT_MODE); /*设置Spi异步模式为中断模式*/
/* Cpt 初始化,开启10ms中断函数 */
Gpt_Init(&GptConf_GptChannelConfigSet_GptChannelConfigSet_0);
Gpt_EnableNotification(GptConf_GptChannelConfiguration_Timer_16bit_1kHz);
Gpt_StartTimer(GptConf_GptChannelConfiguration_Timer_16bit_1kHz, 10-1);
}
开启SCB3中断
Cy_SysInt_SetSystemIrqVector((cy_en_intr_t)scb_3_interrupt_IRQn,Spi_Interrupt_SCB3_Cat1);/*设置中断向量*/
/*初始化中断寄存器*/
Cy_SysInt_InitIRQ( &(cy_stc_sysint_irq_t){ .sysIntSrc=(cy_en_intr_t)scb_3_interrupt_IRQn, .intIdx = CPUIntIdx4_IRQn, .isEnabled = true});
NVIC_EnableIRQ(CPUIntIdx4_IRQn);/*设置NVIC中断*/
在10ms中断函数中调用
void Gpt_Notification_Timer_16bit_1KHz(void)
{
Ret_Val1 = Spi_SetupEB(SpiChannel_HSD_1,u8TXBuff,u8RXBuff,4U);/*设定EB通道的数据,长度为4*/
Ret_Val2 = Spi_AsyncTransmit(SpiSequence_HSD_1);/*异步方式传输序列*/
}
2000

被折叠的 条评论
为什么被折叠?



