spi.c

来自「MC56F802BLDC 可以使用的算法 就是电机启动有点慢」· C语言 代码 · 共 276 行

C
276
字号
/*****************************************************************************
*
* Motorola Inc.
* (c) Copyright 2001 Motorola, Inc.
* ALL RIGHTS RESERVED.
*
******************************************************************************
*
* File Name: spi.c
*
* Description: SPI driver
*
* Modules Included:
*
*****************************************************************************/

#include "types.h"
#include "arch.h"
#include "periph.h"

#include "appconfig.h"
#include "spi.h"
#include "gpio.h"


/* state global variables for read,write functions */
volatile UWord16 spi0_status;
static volatile UWord16 *spi0_TxDataPtr;
volatile UWord16 spi0_TxCounter;

static volatile UWord16 *spi0_RxDataPtr;
volatile UWord16 spi0_RxCounter;
//#define RX_BUF_LEN 16

void spiInit(arch_sSPI *pSpiBase)
{

 /* initialization of SPI */
 #ifdef SPI_0_DATA_SIZE_REG
  periphMemWrite(SPI_0_DATA_SIZE_REG, &pSpiBase->DataSizeReg);
 #endif

 #ifdef SPI_0_STATUS_CONTROL_REG
  periphMemWrite(SPI_0_STATUS_CONTROL_REG, &pSpiBase->ControlReg);
 #endif
 
 /* init of read, write status variables */
 spi0_status = 0;
 spi0_TxCounter = 0;
 spi0_RxCounter = 0;
 
}


/****************************************************************************
* SPI ISR routines skeleton
*****************************************************************************/

/* interrupt handler for uart Tx reg. empty interrupt */
#pragma interrupt
void Spi0TxEmptyISR(void)
{
 
 if (--spi0_TxCounter)
  {
   ioctl(SPI_0,SPI_WRITE,*spi0_TxDataPtr++); /* write byte to Tx reg */
  }
 else
  {
   /* all characters are written to TX reg */
   ioctl(SPI_0, SPI_TX_EMPTY_INT, SPI_DISABLE );  /* TX int disable */
   periphBitClear(SPI_STATUS_WRITE_INPROGRESS, &spi0_status);  /* write in progress clear */
   /* to notify end of TX oper. */
   /* possible to insert callback function for transmit buffer end */
  }
 
}


/* interrupt handler for SPI Rx reg. full interrupt */
/* receive number (spi_RxCounter) of characters and then */
/* SPI_STATUS_READ_INPROGRESS flag is cleared */
#pragma interrupt  
void Spi0ReceiveISR(void)
{
 register UWord16 tmp;
 /* test if any SPI error */
 if (!ioctl(SPI_0, SPI_GET_ERROR, NULL))
  {
   /* no SPI error occured */ 
   if (spi0_RxCounter) /* maybe redundant condition - only for security */
    {
     *(spi0_RxDataPtr++) = ioctl(SPI_0,SPI_READ,NULL); /* read byte from Rx reg */
     /* it clears SPRF flag automatically when Rx reg. is read */
     if (!(--spi0_RxCounter))
      {
       /* last character received */
       //ioctl(SPI_0, SPI_RX_FULL_INT, SPI_DISABLE );  /* Rx int disable */
       periphBitClear(SPI_STATUS_READ_INPROGRESS,&spi0_status);
       /* to notify end of Rx oper. */
       /* possible to insert callback function for receiving end */
      }
    }
   else
    {
     /* received more characters than defined number */
     tmp = ioctl(SPI_0,SPI_READ,NULL); /* read byte from Rx reg to supress */
     /* generating of overrun error */
     /* set buffer overflow  flag */ 
     periphBitSet(SPI_STATUS_EXCEPTION_EXIST | SPI_EXCEPTION_BUFFER_OVERFLOW,&spi0_status);
    }
   
  }
 else
  {
    /* SPI error occured - either MODE FAULT or receive OVERFLOW */
    /* hardware error */
    //periphBitSet(SPI_STATUS_EXCEPTION_EXIST,&spi0_status);   
 
    /* test which error occured */
    if (ioctl(SPI_0, SPI_GET_MODE_FAULT, NULL))
     {
      /* fault mode detected - for SLAVE /SS pin went high during transmission */
      /* for MASTER /SS pin went low during transmission  */
      ioctl(SPI_0, SPI_CLEAR_MODE_FAULT, NULL); /* clear MODF flag */

      periphBitSet(SPI_STATUS_EXCEPTION_EXIST | SPI_EXCEPTION_MODE_FAULT, &spi0_status);   
      /* insert here additional error handling code */

     }
    else
     {
      /* RX reg. overflow - previous character wasn't read and new one received */
      /* OVRF flag is cleared automatically by SPSCR reading */
      periphBitSet(SPI_STATUS_EXCEPTION_EXIST | SPI_EXCEPTION_OVERRUN, &spi0_status);   
      /* insert here error handling code */
     }
     
  } /* if (!ioctl(SPI0, SPI_GET_ERROR, 0)) */
}


/****************************************************************************
* SPI Read,Write services - nonblocking mode
*****************************************************************************/
/* add /CS (chipselect) control to code - either /CS should toggle between */
/* transmission or stay low during and change at the end */

/* send buffer <buf> through SPI interface - nonblocking mode */
/* operation finishing can be tested by - if (spi_TxEndFlag) */
void write_SPI_0_NON_BLOCKING(const void *buf, unsigned char size)
{   
 if (!spi0_TxCounter)  /* test if previous transmit operation not finished yet */
  {
   /* prepare buffer pointer and count variable */
   spi0_TxDataPtr = (UWord16 *) buf;
   spi0_TxCounter = size;

   periphBitSet(SPI_STATUS_WRITE_INPROGRESS, &spi0_status);  /* write in progress */
   ioctl(SPI_0,SPI_WRITE,*spi0_TxDataPtr++); /* write 1St byte to Tx reg */
   							   /* - it starts transmission of the buffer */
   ioctl(SPI_0, SPI_TX_EMPTY_INT, SPI_ENABLE ); /* TX int enable */
  }
}


/* receive "num" words from SPI to buffer - nonblocking mode - prepares buffer and pointer */
/* operation finishing can be tested by - if (spi_RxEndFlag) */
void read_SPI_0_NON_BLOCKING(void *buf, unsigned char size)
{   
 if (!spi0_RxCounter)  /* test if previous receive operation not finished yet */
  {
   /* prepare buffer pointer and count variable */   
   spi0_RxDataPtr = (UWord16 *) buf;
   spi0_RxCounter = size;

   periphBitSet(SPI_STATUS_READ_INPROGRESS,&spi0_status);  /* read in progress */
   ioctl(SPI_0, SPI_RX_FULL_INT, SPI_ENABLE);  /* Rx int enable */
   /* receive operations are started when 1St char. is received */
   /* in MASTER mode it is necessary write to SPI to receive char. concurently */
   /* with transmition - transfer is initiated by writing */        
  }
}


/* SPI end operation testing */
/* WRITE
if (ioctl(SPI_0, SPI_GET_STATUS, NULL) & SPI_STATUS_WRITE_INPROGRESS)
   - write in progress
if (!(ioctl(SPI_0, SPI_GET_STATUS, NULL) & SPI_STATUS_WRITE_INPROGRESS))
   - no write operation is carried out, possible to start another
     write operation

if (!spi0_TxCounter) - the last character from buffer written to TX reg

*/

/* READ
if (ioctl(SPI_0, SPI_GET_STATUS, NULL) & SPI_STATUS_READ_INPROGRESS)
   - read in progress
if (!(ioctl(SPI_0, SPI_GET_STATUS, NULL) & SPI_STATUS_READ_INPROGRESS))
   - no read operation is carried out, possible to start another
     read operation

 spi0_RxCounter  - number of characters remaining to complete receive 

*/


/****************************************************************************
* SPI read_SPI_0_BLOCKING, write_SPI_0_BLOCKING services - blocking mode - 
* routines waits till the end of bus operations - they blocks CPU resources
* - only interrupts can be carried out simultaneously
*****************************************************************************/

/* send buffer <buf> through SPI interface - blocking mode */
/* tranmits words and waits till all words are transmitted */
/* it means that it blocks all CPU resources, it is recomended */
/* to use NONBLOCKING mode rather */
void write_SPI_0_BLOCKING(const void *buf, unsigned char size)
{   
 if (!spi0_TxCounter)  /* test if previous transmit operation not finished yet */
  {
   /* prepare buffer pointer and count variable */
   spi0_TxDataPtr = (UWord16 *) buf;
   spi0_TxCounter = size;

   periphBitSet(SPI_STATUS_WRITE_INPROGRESS, &spi0_status);  /* write in progress */

   do
    {
     while (!ioctl(SPI_0, SPI_GET_TX_EMPTY, NULL))
      {
       /* wait to finisch 1 word send */
      }
     ioctl(SPI_0,SPI_WRITE,*spi0_TxDataPtr++);
    }
   while (--spi0_TxCounter); 

   periphBitClear(SPI_STATUS_WRITE_INPROGRESS, &spi0_status);  /* write in progress */

  }
}

/* receive "num" words from SPI to buffer - blocking mode - */
/* receives words and waits till all words are received */
/* it means that it blocks all CPU resources, it is highly recomended */
/* to use NONBLOCKING mode for receive operations */
void read_SPI_0_BLOCKING(void *buf, unsigned char size)
{   
 if (!spi0_RxCounter)  /* test if previous receive operation not finished yet */
  {
   /* prepare buffer pointer and count variable */   
   spi0_RxDataPtr = (UWord16 *) buf;
   spi0_RxCounter = size;
   
   periphBitSet(SPI_STATUS_READ_INPROGRESS,&spi0_status);  /* read in progress */

   do
    {
     while (!ioctl(SPI_0, SPI_GET_RX_FULL, NULL))
      {
       /* wait to 1 word is ready in RX reg. */
      }
     *(spi0_RxDataPtr++) = ioctl(SPI_0, SPI_READ, NULL);
    }
   while (--spi0_RxCounter); 

   periphBitClear(SPI_STATUS_READ_INPROGRESS,&spi0_status);  /* read in progress */

   /* in MASTER mode it is necessary write to SPI to receive char. concurently */
   /* with transmition - transfer is initiated by writing, in blocking mode */
   /* the only 1 word is possible to receive and transmit simultaneously */
  }
}

⌨️ 快捷键说明

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