⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spi.c

📁 philips arm7 lpc2103的常用功能的库函数第二部分
💻 C
📖 第 1 页 / 共 2 页
字号:
/***********************************************Copyright (c)*********************************************
**                                Guangzou ZLG-MCU Development Co.,LTD.
**                                     
**                                       http://www.zlgmcu.com
**
**--------------File Info---------------------------------------------------------------------------------
** File name:			    SPI.c
** Last modified Date:      2007-10-15
** Last Version:		    1.0
** Descriptions:		    SPI函数实现,采用设备描述符来操作
**
**--------------------------------------------------------------------------------------------------------
** Created by:			    lixiaocheng
** Created date:		    2007-10-15
** Version:				    1.0
** Descriptions:		    无
**
**--------------------------------------------------------------------------------------------------------
** Modified by:			    
** Modified Date:		    
** Version:				    
** Descriptions:		    
**
*********************************************************************************************************/
#include "Config.h"
#include "SpiPrivate.h"
#include "Spi.h"                                                        
                                                                        
/*********************************************************************************************************
   定义操作SPI操作结构体,有多个器件就需要声明多个结构体
*********************************************************************************************************/
static __SPI_INFO   __GsiData0;

/*********************************************************************************************************
   下面使用指针数组来保存结构体指针,方便对该驱动的扩展
*********************************************************************************************************/
const __PSPI_INFO   __GpsiDataTab[__SPI_MAX_NUM] = { &__GsiData0};

/*********************************************************************************************************
   下面定义了SPI基地址值,如果有多个SPI器件可以在该位置添加相应的基地址即可
*********************************************************************************************************/
const uint32        __GuiSpiBaseAddrTab[__SPI_MAX_NUM] = { SPI0_BASE_ADDR};

/*********************************************************************************************************
   定义驱动使用的数据缓冲区数组
*********************************************************************************************************/
static uint8        __GucSpiSendQueue[__SPI_MAX_NUM][__SPI_MAX_SEND_QUEUE];
static uint8        __GucSpiRecvQueue[__SPI_MAX_NUM][__SPI_MAX_RECV_QUEUE];

/*********************************************************************************************************
** Function name:           __spiInit()
** Descriptions:            SPI初始化函数,内部使用
** Input parameters:        ID      设备号,例如0表示使用SPI0
**                          PARM    传入参数的结构体
** Output parameters:       NONE
** Returned value:          初始化失败:      OPERATE_FAIL
**                          管脚连接错误:    PIN_ERR
**                          初始化成功:      OPERATE_SUCCESS
*********************************************************************************************************/
static int32 __spiInit( uint32 ID, __SPI_PARM PARM )
{
    volatile uint32       *puiBaseAddr;
             uint32        uiOffBase;
             uint32        uiSpeed;
    /*
     *  参数过滤
     */
    if (ID >= __SPI_MAX_NUM) {
        return OPERATE_FAIL;
    }
    if (PARM.uiSpiSpeed > Fpclk/8) {                                    /*  过滤速度                    */
        PARM.uiSpiSpeed = Fpclk/8;
    }
    if (PARM.uiSpiSpeed == 0) {                                         /*  过滤速度                    */
        return OPERATE_FAIL;
    }
    if (PARM.ucpha > __SPI_PHA_H) {                                     /*  过滤相位                    */
        return OPERATE_FAIL;
    }
    if (PARM.ucpol > __SPI_POL_L) {                                     /*  过滤CLK高低电平             */
        return OPERATE_FAIL;
    }
    if (PARM.uclsb > __SPI_LSB) {                                       /*  过滤LSB参数                 */
        return OPERATE_FAIL;
    }
    if (PARM.ucpie > __SPI_INT_EN) {                                    /*  判断中断设置参数            */
        return OPERATE_FAIL;
    }
    
    /*
     *  管脚链接判断
     */
    if (ID == 0) {
        if (((PINSEL0 >> 8)  & 3) != P0_04_SCK0  ||                     /*  SCKO                        */
            ((PINSEL0 >> 10) & 3) != P0_05_MISO0 ||                     /*  MISO0                       */
            ((PINSEL0 >> 12) & 3) != P0_06_MOSI0 ||                     /*  MOSI0                       */
            ((PINSEL0 >> 14) & 3) != P0_07_SSEL0 ) {                    /*  SSEL0                       */                        
                return PIN_ERR;
        }
    } else {
        if (((PINSEL0 >> 28) & 3) != P0_14_SCK1  ||                      /*  SCK1                        */
            ((PINSEL1 >> 6 ) & 3) != P0_19_MISO1 ||                      /*  MISO1                       */
            ((PINSEL1 >> 8 ) & 3) != P0_20_MOSI1 ||                      /*  MOSI1                       */
            ((PINSEL1 >> 10) & 3) != P0_21_SSEL1 ) {                     /*  SSEL1                       */                        
                return PIN_ERR;
        }
    }
    
    /* 
	 *  初始化设备结构体
	 */
	QueueCreate(__GucSpiSendQueue[ID], sizeof(__GucSpiSendQueue[ID]), NULL, NULL); 
	                                                                    /*  初始化发送队列              */
	                                                                    
	QueueCreate(__GucSpiRecvQueue[ID], sizeof(__GucSpiRecvQueue[ID]), NULL, NULL); 
	                                                                    /*  初始化接收队列              */ 
	                                                                   
	__GpsiDataTab[ID]->puiAddrBase = (uint32 *)__GuiSpiBaseAddrTab[ID];
	__GpsiDataTab[ID]->uiOffBase   = 0;
	
	__GpsiDataTab[ID]->ucSpiflag   = SPI_IDLE;
	__GpsiDataTab[ID]->ucSlave     = __SPI_MASTER;
	__GpsiDataTab[ID]->sendQueue   = (__PDATA_QUEUE)__GucSpiSendQueue[ID];
	__GpsiDataTab[ID]->recvQueue   = (__PDATA_QUEUE)__GucSpiRecvQueue[ID];
	
    /* 
	 *  初始化部件功能参数
	 */
	puiBaseAddr = __GpsiDataTab[ID]->puiAddrBase;
	uiOffBase   = __GpsiDataTab[ID]->uiOffBase;
	
	puiBaseAddr[__B_SPI_PCR<<uiOffBase] = (PARM.ucpha   << 3) |         /*  初始化相位等参数          */
	                                      (PARM.ucpol   << 4) |         /*  初始化时钟极性            */
	                                      (__SPI_MASTER << 5) |         /*  初始化SPI为主机           */
	                                      (PARM.uclsb   << 6) |         /*  初始化高低字节先后顺序    */
	                                      (PARM.ucpie   << 7);          /*  初始化中断是否使能        */
	                                      
	
	 
	uiSpeed = ((Fpclk/PARM.uiSpiSpeed) % 2) ? (Fpclk/PARM.uiSpiSpeed)+1 : (Fpclk/PARM.uiSpiSpeed);
	if (uiSpeed > 255) {                                                /*  因为SPICCR是8位的         */
	    uiSpeed = 254;
	}                                      
	puiBaseAddr[__B_SPI_CCR<<uiOffBase] = uiSpeed;                      /*  确保初始化的速度为偶数    */
	return OPERATE_SUCCESS;
 }

/*********************************************************************************************************
** Function name:           spiInit()
** Descriptions:            SPI初始化函数,使用字符串传入参数
** Input parameters:        uiParmID      设备号,例如0表示使用SPI0
**                          pcParmArg     传入参数的字符串指针,参数列表和取值意义如下
**                              Spiclk:   spi的通讯速率,范围Fpclk/254 ~ Fpclk/8
**                              Cpha  :   0为第一个时钟采样,1为第二个时钟采样
**                              Cpol  :   0为CLK高电平有效,1为CLK低电平有效
**                              Lsbf  :   0表示MSB在先,1表示LSB在先
**                          pvRsv         保留参数
** Output parameters:       NONE
** Returned value:          初始化失败:      OPERATE_FAIL
**                          管脚连接错误:    PIN_ERR
**                          初始化成功:      OPERATE_SUCCESS
*********************************************************************************************************/
int32 spiInit (uint32 uiParmID, 
               char *pcParmArg, 
               void *Rsv)
{
    __SPI_PARM  spParm;
    uint32      uiParmTable[4] = {-1, -1, -1, -1};
    
    Rsv = Rsv;                                                          /*  防止编译报警                */
    
    ImpCmd(Tab_SPI, pcParmArg, uiParmTable);                            /*  转换字符按串参数            */
    
    spParm.uiSpiSpeed = uiParmTable[Spiclk];
    spParm.ucpha      = (uint8)uiParmTable[Cpha];
    spParm.ucpol      = (uint8)uiParmTable[Cpol];
    spParm.uclsb      = (uint8)uiParmTable[Lsbf];
    spParm.ucpie      = __SPI_INT_EN;                                   /*  始终使能SPI中断             */
    
    return __spiInit(uiParmID, spParm);                                 /*  传入参数进行初始化          */
}

/*********************************************************************************************************
** Function name:           spiWrite()
** Descriptions:            SPI写函数
** Input parameters:        uiParmID      设备号,例如0表示使用SPI0
**                          pucParmData   写入数据首指针
**                          uiParmLen     要写入数据的长度
**                          ucFlag        写模式,0为写的同时丢弃返回值,1为保留返回值,返回值的获取通过
**                                        spiRead()获取。
** Output parameters:       NONE
** Returned value:          写失败:       OPERATE_FAIL
**                          >=0           已发送数据个数
*********************************************************************************************************/
int32 spiWrite (uint32 uiParmID, 
                uint8 *pucParmData, 
                uint32 uiParmLen, 
                uint8  ucFlag)
{
    volatile uint32       *puiBaseAddr;
             uint32        uiOffBase;
             uint32        i;
    
    /*
     *  参数过滤
     */
    if (uiParmID >= __SPI_MAX_NUM) {
        return OPERATE_FAIL;
    }
    if (uiParmLen == 0) {                                               /*  不允许发送0个字节数据      */
        return OPERATE_FAIL;
    }
    if (__GpsiDataTab[uiParmID]->ucSpiflag == SPI_READ) {               /*  设备正在读返回错误         */
        return OPERATE_FAIL;
    }
    if (__GpsiDataTab[uiParmID]->ucSlave == __SPI_SLAVE) {              /*  是从设备返回错误           */
        return OPERATE_FAIL;
    }
    if (ucFlag > SPI_SAVE_BACK) {                                       /*  检查用户输入宏是否正确     */
        return OPERATE_FAIL;
    }
    
    puiBaseAddr = __GpsiDataTab[uiParmID]->puiAddrBase;                 /*  获得设备地址               */
	uiOffBase   = __GpsiDataTab[uiParmID]->uiOffBase;
	
    if (__GpsiDataTab[uiParmID]->ucSpiflag == SPI_IDLE) {               /*  设备空闲,就发送数据       */
        __SPI_CS_ENABLE(__GpsiDataTab[uiParmID]->uiSpiCsPin);           /*  使能片选                   */
        __GpsiDataTab[uiParmID]->ucSpiflag   = SPI_WRITE;               /*  标识设备为写状态           */
        __GpsiDataTab[uiParmID]->ucWriteMode = ucFlag;                  /*  确定写模式                 */
        IRQDisable();                                                   /*  关中断等待数据入队结束     */
        puiBaseAddr[__B_SPI_PDR << uiOffBase] = *pucParmData;           /*  发送数据到SPI数据寄存器    */
        uiParmLen--;                                                    /*  调整数据长度               */
        pucParmData++;                                                  /*  调整数据首指针             */
    } else {
        if (__GpsiDataTab[uiParmID]->ucWriteMode != ucFlag) {           /*  发现写操作与当前写操作模式 */
                                                                        /*  不同,则不允许把两次写重叠  */
           return  OPERATE_FAIL;
        }
        IRQDisable();                                                   /*  关中断等待数据入队结束     */
    }
    
	for (i = 0; i < uiParmLen; i++) {                                   /*  数据入队                   */
	    if (QueueWrite(__GpsiDataTab[uiParmID]->sendQueue, pucParmData[i]) != QUEUE_OK) {
	        IRQEnable();                                                /*  数据入队结束,开中断       */
	        return i;                                                   /*  返回已发送数据个数         */
	    }
	}
	IRQEnable();                                                        /*  数据入队结束,开中断       */
	return uiParmLen;                                                   /*  已全部发送成功             */
	
}

/*********************************************************************************************************
** Function name:           spiReadStart()
** Descriptions:            SPI读启动函数
** Input parameters:        uiParmID      设备号,例如0表示使用SPI0

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -