/*
* 说明:SPI通讯实现* 方式一: 同时发送与接收实现: SPI_Transfer()* 方式二:发送与接收分开来实现* SPI_Write() 只发送* SPI_Read() 只接收* 两种方式不同之处:方式一,在发的过程中也在接收,第二种方式,收与发单独进行* Created on: 2013-5-28* Author: lzy*/#include <stdint.h>#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <getopt.h>#include <fcntl.h>#include <sys/ioctl.h>#include <linux/types.h>#include <linux/spi/spidev.h>#include "Debug.h"#define SPI_DEBUG 0static const char * = "/dev/spidev0.0";static uint8_t mode = 0; /* SPI通信使用全双工,设置CPOL=0,CPHA=0。 */static uint8_t bits = 8; /* 8bits读写,MSB first。*/static uint32_t speed = 12 * 1000 * 1000;/* 设置12M传输速度 */static uint16_t delay = 0;static int g_SPI_Fd = 0;static void pabort(const char *s){ ror(s);abort();}/*** 功 能:同步* 入口参数 :* TxBuf -> 发送数据首地址* len -> 交换数据的长度* 出口参数:* RxBuf -> 接收数据缓冲区* 返回值:0 成功* 开发人员:Lzy 2013-5-22*/int SPI_Transfer(const uint8_t *TxBuf, uint8_t *RxBuf, int len){ int ret;int fd = g_SPI_Fd;struct spi_ioc_transfer tr ={ .tx_buf = (unsigned long) TxBuf,.rx_buf = (unsigned ) RxBuf,.len =len,.delay_usecs = delay,};ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);if (ret < 1)pr_err("can't send spi message");else{ #if SPI_DEBUGint i;pr_debug("nsend spi message Succeed");pr_debug("nSPI Send [Len:%d]: ", len);for (i = 0; i < len; i++){ if (i % 8 == 0)printf("nt");printf("0x%02X ", TxBuf[i]);}printf("n");pr_debug("SPI Receive [len:%d]:", len);for (i = 0; i < len; i++){ if (i % 8 == 0)printf("nt");printf("0x%02X ", RxBuf[i]);}printf("n");#endif}return ret;}/*** 功 能:发送数据* 入口参数 :* TxBuf -> 发送数据首地址*len -> 发送与长度*返回值:0 成功* 开发人员:Lzy 2013-5-22*/int SPI_Write(uint8_t *TxBuf, int len){ int ret;int fd = g_SPI_Fd;ret = write(fd, TxBuf, len);if (ret < 0)pr_err("SPI Write errorn");else{ #if SPI_DEBUGint i;pr_debug("nSPI Write [Len:%d]: ", len);for (i = 0; i < len; i++){ if (i % 8 == 0)printf("nt");printf("0x%02X ", TxBuf[i]);}printf("n");#endif}return ret;}/*** 功 能:接收数据* 出口参数:* RxBuf -> 接收数据缓冲区* rtn -> 接收到的长度* 返回值:>=0 成功* 开发人员:Lzy 2013-5-22*/int SPI_Read(uint8_t *RxBuf, int len){ int ret;int fd = g_SPI_Fd;ret = read(fd, RxBuf, len);if (ret < 0)pr_err("SPI Read errorn");else{ #if SPI_DEBUGint i;pr_debug("SPI Read [len:%d]:", len);for (i = 0; i < len; i++){ if (i % 8 == 0)printf("nt");printf("0x%02X ", RxBuf[i]);}printf("n");#endif}return ret;}/*** 功 能:打开设备 并初始化设备* 入口参数 :* 出口参数:* 返回值:0 表示已打开 0XF1 表示SPI已打开 其它出错* 开发人员:Lzy 2013-5-22*/int SPI_Open(void){ int fd;int ret = 0;if (g_SPI_Fd != 0) /* 设备已打开 */return 0xF1;fd = open(device, O_RDWR);if (fd < 0)pabort("can't ");elsepr_debug("SPI - Open Succeed. Start Init SPI...n");g_SPI_Fd = fd;/** spi mode*/ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);if (ret == -1)pabort("can't set spi mode");ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);if (ret == -1)pabort("can't get spi mode");/** bits word*/ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);if (ret == -1)pabort("can't set bits per word");ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);if (ret == -1)pabort("can't get bits per word");/** max speed hz*/ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);if (ret == -1)pabort("can't set max speed hz");ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);if (ret == -1)pabort("can't get max speed hz");pr_debug("spi mode: %dn", mode);pr_debug("bits word: %dn", bits);pr_debug("max speed: %d KHz (%d MHz)n", speed / 1000, speed / 1000 / 1000);return ret;}/*** 功 能:关闭SPI模块*/int SPI_Close(void){ int fd = g_SPI_Fd;if (fd == 0) /* SPI是否已经打开*/return 0;close(fd);g_SPI_Fd = 0;return 0;}/*** 功 能:自发自收测试程序* 接收到的数据与发送的数据如果不一样 ,则失败* 说明:* 在硬件上需要把输入与输出引脚短跑* 开发人员:Lzy 2013-5-22*/int SPI_LookBackTest(void){ int ret, i;const int BufSize = 16;uint8_t tx[BufSize], rx[BufSize];bzero(rx, sizeof(rx));for (i = 0; i < BufSize; i++)tx[i] = i;pr_debug("nSPI - LookBack Mode Test...n");ret = SPI_Transfer(tx, rx, BufSize);if (ret > 1){ ret = memcmp(tx, rx, BufSize);if (ret != 0){ pr_err("LookBack Mode Test errorn");//pabort("error");}elsepr_debug("SPI - LookBack Mode OKn");}return ret;}