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 + -
显示快捷键?