1. SPI介绍
2. 全局结构体 和 用到的函数
/***封装的SPI结构体**/ typedef struct { int nSpiFd; //spi文件描述符 char nDevName[32]; //spi名称,例/dev/spidev2.0 int nSpeed; //spi通信速率 int nBit; //为8,写死的 int nOpenFlag; //true表示已打开 pthread_mutex_t nBusLock; //没啥用,未用到,也未进行初始化 }TSpiDev;
外部函数: /*该函数做的事情: (1)打开SPI控制器的设备文件; (2)设置SPI工作模式、一个字节位数(8位)、最高波特率。 (3)malloc一个TSpiDev结构,然后返回指针。 */ (1)HANDLE SpiOpen(char *pDevice,int nSpeed,int nMode) /*该函数做的事情:同时实现SPI的发送和接收函数*/ (2)bool SpiTransfer(HANDLE nHandle,char *pTxBuf,int nTxLen,char *pRxBuf,int nRxLen); /*该函数做的事情:只进行SPI数据的发送*/ (3)bool SpiWrite(HANDLE nHandle,char *pTxBuf,int nTxLen) /*该函数做的事情:改变一个字节的位数*/ (4)bool SpiBit(HANDLE nHandle,int nBit) /*该函数做的事情: (1)关闭SPI控制器的设备文件; (2)将打开标志置为false; (3)并未释放TSpiDev结构空间。 */ (5)int SpiClose(HANDLE *pHandle);
3. 函数源码注释
3.1 SpiOpen
/********************************** *function: SpiOpen *input : * pDevice : Spi device * nSpeed : Spi max speed *output : *return : * success : return bus handle,else return -1; */ HANDLE SpiOpen(char *pDevice,int nSpeed,int nMode) { int nFd = 0; int ret = 0; TSpiDev *pDev = NULL; /* Default Mode to 0 */ unsigned char mode = nMode; /* Default Bit Width to 8 */ unsigned char bits = 8; if(pDevice == NULL) { LOG_ERROR("Get null device name."); return -1; } /* Open Device */ nFd = open(pDevice,O_RDWR); //打开SPI控制器 if(nFd <= 0) { LOG_ERROR("Open %s error with %s.",pDevice,strerror(errno)); return -1; } /*Initialize SPI*/ /* *spi mode */ ret = ioctl(nFd, SPI_IOC_WR_MODE, &mode); //设置SPI的工作模式,一共有4种 if (ret == -1) { LOG_ERROR("SPI_IOC_WR_MODE with %s.",strerror(errno)); close(nFd); return -1; } /* * bits per word */ ret = ioctl(nFd, SPI_IOC_WR_BITS_PER_WORD, &bits); //设置一个字节的位数,默认情况下设置为 8 即可 if (ret == -1) { LOG_ERROR("SPI_IOC_WR_BITS_PER_WORD with %s.",strerror(errno)); close(nFd); return -1; } /* * max speed hz */ ret = ioctl(nFd, SPI_IOC_WR_MAX_SPEED_HZ, &nSpeed); //设置 最高波特率 if (ret == -1) { LOG_ERROR("SPI_IOC_WR_MAX_SPEED_HZ with %s.",strerror(errno)); close(nFd); return -1; } /*Initialize Muter*/ pDev = (TSpiDev *)malloc(sizeof(TSpiDev)); if(pDev == NULL) { close(nFd); LOG_ERROR("Get SPI hanlde error wiyh %s.",strerror(errno)); return -1; } /*Save Status*/ snprintf(pDev->nDevName,sizeof(pDev->nDevName),"%s",pDevice); pDev->nOpenFlag = true; pDev->nSpeed = nSpeed; pDev->nSpiFd = nFd; pDev->nBit = 8; return (HANDLE)pDev; }
3.2 SpiTransfer
/********************************** *function: SpiTransfer *input : * nHandle : Spi device Handle * pTxBuf : TxBuffer * nTxLen : Tx Len * pRxBuf : Rx Buffer * nRxLen : Rx Len *output : *return : * success : return true,else return false; */ bool SpiTransfer(HANDLE nHandle,char *pTxBuf,int nTxLen,char *pRxBuf,int nRxLen) //同时发送和接收 { int ret; unsigned char tx[512] = {0}; unsigned char rx[512] = {0}; TSpiDev *pDev = (TSpiDev *)nHandle; /* Spi Transfer Message 定义并初始化SPI传输结构体 */ struct spi_ioc_transfer tr ={ .tx_buf = (unsigned long)tx, // .rx_buf = (unsigned long)rx, //接收到的数据会暂存到rx中 .len = nTxLen, //一次传输的数据长度 .delay_usecs = 0, //如果不为零则用于设置两次传输之间的时间延迟。 .speed_hz = pDev->nSpeed, //指定 SPI 通信的比特率 /* Default to 8 bit */ .bits_per_word = pDev->nBit, //一个字节占用8比特 }; LOG_DEBUG("{%s-%d}-Start Transmessge.",pDev->nDevName,pDev->nSpiFd); if(pDev->nOpenFlag) { memcpy(tx,pTxBuf,nTxLen); //把发送的数据拷贝到tx中 if(pRxBuf == NULL) { tr.rx_buf = 0; } //MESSAGE(1)表示:半双工;MESSAGE(2)表示全双工; ret = ioctl(pDev->nSpiFd, SPI_IOC_MESSAGE(1), &tr); //参数 SPI_IOC_MESSAGE(1) 用于指定执行传输次数 if (ret < 1) { LOG_ERROR("SPI Transfer error with %s.",strerror(errno)); return false; } if(pRxBuf) { memcpy(pRxBuf,rx,nRxLen); //把接收到的到的数据拷贝出来到pRxBuf } return true; } LOG_ERROR("SPI device not open."); return false; }
3.3 SpiWrite
/********************************** *function: SpiTransfer *input : * nHandle : Spi device Handle * pTxBuf : TxBuffer * nTxLen : Tx Len *output : *return : * success : return true,else return false; */ bool SpiWrite(HANDLE nHandle,char *pTxBuf,int nTxLen) //只发送 { TSpiDev *pDev = (TSpiDev *)nHandle; if(pDev->nOpenFlag) { if(write(pDev->nSpiFd,pTxBuf,nTxLen) != nTxLen) //只需要往设备文件中写入即可。 如果仅仅读的话,也可以从设备文件中read即可 { LOG_ERROR("Spi write error with %s.",strerror(errno)); return false; } } return true; }
3.4 SpiBit
/********************************** *function: SpiBit *input : * pHandle : Spi device Handle * nBit : Spi Bit for each word *output : *return : * success : return bus handle,else return -1; */ bool SpiBit(HANDLE nHandle,int nBit) //改变一个字节的位数 { int ret = 0; unsigned char bits = nBit; TSpiDev *pDev = (TSpiDev *)nHandle; pDev->nBit = nBit; /* * bits per word */ ret = ioctl(pDev->nSpiFd, SPI_IOC_WR_BITS_PER_WORD, &bits); if (ret == -1) { LOG_ERROR("SPI_IOC_WR_BITS_PER_WORD %d with %s.",bits,strerror(errno)); return false; } return true; }
3.5 SpiClose
/********************************** *function: SpiClose *input : * pHandle : Spi device Handle *output : *return : * success : return bus handle,else return -1; */ bool SpiClose(HANDLE *pHandle) { if(pHandle) { TSpiDev * pDev = (TSpiDev *)(*pHandle); if(pDev->nOpenFlag) { close(pDev->nSpiFd); pDev->nOpenFlag = false; } *pHandle = 0; return true; } LOG_ERROR("Get NUll pointer."); return false; }标签:return,SPI,--,TSpiDev,char,spi,int,pDev,库函数 From: https://www.cnblogs.com/dkhlaojogo/p/18206599