298 lines
7.2 KiB
C
298 lines
7.2 KiB
C
/**************************************************************************!
|
||
* 技术讨论:QQ群 123763203
|
||
* 官网 :www.navota.com
|
||
*
|
||
* @file spi.c
|
||
* @brief 串行外设接口模块(SPI)函数库
|
||
* @author Navota
|
||
* @date 2017-1-1
|
||
****************************************************************************/
|
||
#include "common.h"
|
||
#include "spi.h"
|
||
|
||
/****************************************************************************!
|
||
* @ 存放SPI回调函数接口
|
||
****************************************************************************/
|
||
|
||
SPI_CallbackType SPI_Callback[MAX_SPI_NO] = {(SPI_CallbackType)NULL};
|
||
|
||
/*****************************************************************************//*!
|
||
*
|
||
* @brief 初始化SPI模块
|
||
*
|
||
* @param[in] pSPI 指向SPI模块.
|
||
* @param[in] pConfig 指向SPI配置参数.
|
||
*
|
||
* @return none.
|
||
*
|
||
*****************************************************************************/
|
||
void SPI_Init(SPI_Type *pSPI, SPI_ConfigType *pConfig)
|
||
{
|
||
#if defined(CPU_NV32M3)
|
||
/* sanity check */
|
||
ASSERT((pSPI == SPI0));
|
||
SIM->SCGC |= SIM_SCGC_SPI0_MASK;
|
||
#else
|
||
/* sanity check */
|
||
ASSERT((pSPI == SPI0) || (pSPI == SPI1));
|
||
|
||
/*使能SPI模块总线时钟*/
|
||
if( pSPI == SPI0)
|
||
{
|
||
SIM->SCGC |= SIM_SCGC_SPI0_MASK;
|
||
}
|
||
else
|
||
{
|
||
SIM->SCGC |= SIM_SCGC_SPI1_MASK;
|
||
}
|
||
#endif
|
||
/*配置SPI控制寄存器 */
|
||
if( pConfig->sSettings.bIntEn) //使能SPI中断
|
||
{
|
||
SPI_IntEnable(pSPI);
|
||
#if defined(CPU_NV32M3)
|
||
NVIC_EnableIRQ(SPI0_IRQn);
|
||
#else
|
||
if( pSPI == SPI0 )
|
||
{
|
||
NVIC_EnableIRQ(SPI0_IRQn);
|
||
}
|
||
else
|
||
{
|
||
NVIC_EnableIRQ(SPI1_IRQn);
|
||
}
|
||
#endif
|
||
}
|
||
|
||
if( pConfig->sSettings.bTxIntEn) //使能SPI发送中断
|
||
{
|
||
SPI_TxIntEnable(pSPI);
|
||
#if defined(CPU_NV32M3)
|
||
NVIC_EnableIRQ(SPI0_IRQn);
|
||
#else
|
||
if( pSPI == SPI0 )
|
||
{
|
||
NVIC_EnableIRQ(SPI0_IRQn);
|
||
}
|
||
else
|
||
{
|
||
NVIC_EnableIRQ(SPI1_IRQn);
|
||
}
|
||
#endif
|
||
}
|
||
if( pConfig->sSettings.bMasterMode) //主/从机选择
|
||
{
|
||
SPI_SetMasterMode(pSPI); //SPI设置为主机模式
|
||
}
|
||
else
|
||
{
|
||
SPI_SetSlaveMode(pSPI); //SPI设置为从机模式
|
||
}
|
||
|
||
if( pConfig->sSettings.bClkPolarityLow) //时钟极性配置
|
||
{
|
||
SPI_SetClockPol(pSPI,1);
|
||
}
|
||
if( pConfig->sSettings.bClkPhase1) //时钟相位配置
|
||
{
|
||
SPI_SetClockPhase(pSPI,1);
|
||
}
|
||
if( pConfig->sSettings.bShiftLSBFirst) //设置SPI串行数据传输开始位
|
||
{
|
||
SPI_SetLSBFirst(pSPI); // SPI串行数据传输从最低位开始(LSB)
|
||
}
|
||
if( pConfig->sSettings.bMatchIntEn)
|
||
{
|
||
SPI_MatchIntEnable(pSPI); //使能SPI匹配中断
|
||
}
|
||
if( pConfig->sSettings.bModeFaultEn)
|
||
{
|
||
SPI_ModfEnable(pSPI); //使能主机模式模式错误功能.
|
||
}
|
||
if( pConfig->sSettings.bMasterAutoDriveSS)
|
||
{
|
||
/*设置SSOE和MODFEN位,从机模式中SS引脚为从机输出,自动驱动从机SS引脚使能*/
|
||
SPI_SSOutputEnable(pSPI);
|
||
SPI_ModfEnable(pSPI);
|
||
}
|
||
|
||
if( pConfig->sSettings.bPinAsOuput)
|
||
{
|
||
SPI_BidirPinEnable(pSPI); //使能双向引脚配置.
|
||
}
|
||
|
||
if( pConfig->sSettings.bBidirectionModeEn)
|
||
{
|
||
SPI_BidirOutEnable(pSPI); //使能双向模式输出.
|
||
}
|
||
if( pConfig->sSettings.bStopInWaitMode)
|
||
{
|
||
SPI_ClockStopEnable(pSPI); //SPI时钟在等待模式下关闭
|
||
}
|
||
|
||
if(pConfig->sSettings.bMasterMode) //设置波特率
|
||
{
|
||
SPI_SetBaudRate(pSPI,pConfig->u32BusClkHz,pConfig->u32BitRate);
|
||
}
|
||
|
||
/*使能SPI模块*/
|
||
if( pConfig->sSettings.bModuleEn)
|
||
{
|
||
SPI_Enable(pSPI);
|
||
}
|
||
}
|
||
|
||
/*****************************************************************************//*!
|
||
*
|
||
* @brief 设置SPI波特率.
|
||
*
|
||
* @param[in] pSPI 指向SPI模块
|
||
* @param[in] u32BusClock 总线时钟.
|
||
* @param[in] u32Bps SPI波特率.
|
||
*
|
||
* @return none.
|
||
*
|
||
*****************************************************************************/
|
||
void SPI_SetBaudRate(SPI_Type *pSPI,uint32_t u32BusClock,uint32_t u32Bps)
|
||
{
|
||
uint32_t u32BitRateDivisor;
|
||
uint8_t u8Sppr;
|
||
uint8_t u8Spr;
|
||
uint8_t u8ReadFlag;
|
||
u32BitRateDivisor = u32BusClock/u32Bps; /* 计算波特率因子 */
|
||
|
||
u8ReadFlag = 0;
|
||
/* 计算最适合的 SPPR 和 SPR */
|
||
for (u8Spr = 0; u8Spr <= 8; u8Spr++)
|
||
{
|
||
for(u8Sppr = 0; u8Sppr <= 7; u8Sppr++)
|
||
{
|
||
if((u32BitRateDivisor>>(u8Spr+1))<=(u8Sppr+1))
|
||
{
|
||
u8ReadFlag = 1;
|
||
break;
|
||
}
|
||
}
|
||
if(u8ReadFlag)
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
if(u8Sppr >=8)
|
||
{
|
||
u8Sppr = 7;
|
||
}
|
||
if(u8Spr >8)
|
||
{
|
||
u8Spr = 8;
|
||
}
|
||
/* 设置波特率 */
|
||
pSPI->BR = SPI_BR_SPPR(u8Sppr) | SPI_BR_SPR(u8Spr);
|
||
}
|
||
|
||
/*****************************************************************************//*!
|
||
*
|
||
* @brief 读/写数据寄存器.
|
||
*
|
||
* @param[in] pSPI 指向SPI模块.
|
||
* @param[in] pWrBuff -- 发送(写)数组指针
|
||
* @param[in] uiLength -- 读/写数据长度.
|
||
* @param[out] pRdBuff -- 接收(读)数组指针.
|
||
*
|
||
* @return if <0, means error, 0: success.
|
||
*
|
||
*****************************************************************************/
|
||
ResultType SPI_TransferWait(SPI_Type *pSPI, SPI_WidthType* pRdBuff, SPI_WidthType *pWrBuff,uint32 uiLength)
|
||
{
|
||
ResultType err = SPI_ERR_SUCCESS;
|
||
uint32_t i;
|
||
|
||
if(!uiLength)
|
||
{
|
||
return (err);
|
||
}
|
||
for(i = 0; i < uiLength; i++)
|
||
{
|
||
while(!SPI_IsSPTEF(pSPI));
|
||
SPI_WriteDataReg(pSPI,pWrBuff[i]);
|
||
while(!SPI_IsSPRF(pSPI));
|
||
pRdBuff[i] = SPI_ReadDataReg(pSPI);
|
||
}
|
||
return (err);
|
||
}
|
||
|
||
|
||
|
||
/*****************************************************************************//*!
|
||
*
|
||
* @brief 复位SPI模块
|
||
*
|
||
* @param[in] pSPI 指向SPI模块
|
||
*
|
||
* @return none.
|
||
*
|
||
*****************************************************************************/
|
||
void SPI_DeInit(SPI_Type *pSPI)
|
||
{
|
||
int16 i;
|
||
pSPI->C1 = SPI_C1_DEFAULT;
|
||
pSPI->C2 = SPI_C2_DEFAULT;
|
||
pSPI->BR = SPI_BR_DEFAULT;
|
||
pSPI->M = SPI_M_DEFAULT;
|
||
for(i = 0; i<100; i++); /*延时一段时间,等待SPI退出中断 */
|
||
}
|
||
|
||
/*****************************************************************************//*!
|
||
*
|
||
* @brief 设置SPI回调函数,在中断服务函数中调用
|
||
*
|
||
* @param[in] pSPI 指向SPI模块
|
||
* @param[in] pfnCallback 回调函数.
|
||
*
|
||
* @return none.
|
||
*
|
||
*****************************************************************************/
|
||
void SPI_SetCallback(SPI_Type *pSPI,SPI_CallbackType pfnCallback)
|
||
{
|
||
uint32_t u32Port = ((uint32_t)pSPI-(uint32_t)SPI0)>>12;
|
||
ASSERT(u32Port <2);
|
||
SPI_Callback[u32Port] = pfnCallback;
|
||
}
|
||
|
||
/*****************************************************************************//*!
|
||
*
|
||
* @brief SPI0 中断服务函数.
|
||
*
|
||
* @param none.
|
||
* @return none.
|
||
*
|
||
*****************************************************************************/
|
||
|
||
void SPI0_Isr(void)
|
||
{
|
||
if( SPI_Callback[0] )
|
||
{
|
||
SPI_Callback[0]();
|
||
}
|
||
}
|
||
#ifndef CPU_NV32M3
|
||
/*****************************************************************************//*!
|
||
*
|
||
* @brief SPI1 中断服务函数
|
||
*
|
||
* @param none.
|
||
* @return none.
|
||
*
|
||
*****************************************************************************/
|
||
|
||
void SPI1_Isr(void)
|
||
{
|
||
if( SPI_Callback[1] )
|
||
{
|
||
SPI_Callback[1]();
|
||
}
|
||
}
|
||
#endif
|
||
|
||
|