blob: 19a0a44a1098519b55b53c06100a3f73e96ba12a [file] [log] [blame]
yq.wang6bd43d52024-02-29 14:50:42 +08001#include <stdint.h>
2#include <unistd.h>
3#include <stdio.h>
4#include <stdlib.h>
5#include <string.h>
6#include <stdarg.h>
7#include <getopt.h>
8#include <fcntl.h>
9#include <sys/ioctl.h>
10#include <linux/types.h>
11#include <linux/spi/spidev.h>
12
13#define SPI_DEBUG 1
14#define DEBUG_SWITCH 1 /* 打开调试信息打印功能 */
15#define ERR_DEBUG_SWITCH 1 /* 打印错误信息打印功能 */
16
17/**
18* 简单打印调试信息
19*/
20#if DEBUG_SWITCH
21#define pr_debug(fmt,args...) printf(fmt, ##args)
22#else
23#define pr_debug(fmt,args...) /*do nothing */
24#endif
25
26/**
27* 错误信息打印
28* 自动打印发生错误时代码所在的位置
29*/
30#if ERR_DEBUG_SWITCH
31#define pr_err(fmt,args...) printf("\nError:\nFile:<%s> Fun:[%s] Line:%d\n "fmt, __FILE__, __FUNCTION__, __LINE__, ##args)
32#else
33#define pr_err(fmt,args...) /*do nothing */
34#endif
35
36
37/*
38* 说明:SPI通讯实现
39* 方式一: 同时发送与接收实现函数: SPI_Transfer()
40* 方式二:发送与接收分开来实现
41* SPI_Write() 只发送
42* SPI_Read() 只接收
43* 两种方式不同之处:方式一,在发的过程中也在接收,第二种方式,收与发单独进行
44* Created on: 2013-5-28
45* Author: lzy
46*/
47static const char *device = "/dev/spidev1.0";
48static uint8_t mode = 0; /* SPI通信使用全双工,设置CPOL=0,CPHA=0。 */
49static uint8_t bits = 8; /* 8bits读写,MSB first。*/
50static uint32_t speed = 12 * 1000 * 1000;/* 设置12M传输速度 */
51static uint16_t delay = 0;
52static int g_SPI_Fd = 0;
53
54static void pabort(const char *s)
55{
56 perror(s);
57 abort();
58}
59
60/**
61* 功 能:同步数据传输
62* 入口参数 :
63* TxBuf -> 发送数据首地址
64* len -> 交换数据的长度
65* 出口参数:
66* RxBuf -> 接收数据缓冲区
67* 返回值:0 成功
68* 开发人员:Lzy 2013-5-22
69*/
70int SPI_Transfer(const uint8_t *TxBuf, uint8_t *RxBuf, int len)
71{
72 int ret;
73 int fd = g_SPI_Fd;
74
75 struct spi_ioc_transfer tr = {
76 .tx_buf = (unsigned long) TxBuf,
77 .rx_buf = (unsigned long) RxBuf,
78 .len = len,
79 .delay_usecs = delay,
80 };
81
82 ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
83 if (ret < 1)
84 pr_err("can't send spi message");
85 else
86 {
87#if SPI_DEBUG
88 int i;
89 pr_debug("\nmbtk: send spi message Succeed");
90 pr_debug("\nmbtk: SPI Send [Len:%d]: ", len);
91 for (i = 0; i < len; i++)
92 {
93 if (i % 8 == 0)
94 printf("\n\t");
95 printf("0x%02X ", TxBuf[i]);
96 }
97 printf("\n");
98
99 pr_debug("mbtk: SPI Receive [len:%d]:", len);
100 for (i = 0; i < len; i++)
101 {
102 if (i % 8 == 0)
103 printf("\n\t");
104 printf("0x%02X ", RxBuf[i]);
105 }
106 printf("\n");
107#endif
108 }
109 return ret;
110}
111
112/**
113* 功 能:发送数据
114* 入口参数 :
115* TxBuf -> 发送数据首地址
116* len -> 发送与长度
117*返回值:0 成功
118* 开发人员:Lzy 2013-5-22
119*/
120int SPI_Write(uint8_t *TxBuf, int len)
121{
122 int ret;
123 int fd = g_SPI_Fd;
124
125 ret = write(fd, TxBuf, len);
126 if (ret < 0)
127 pr_err("SPI Write error\n");
128 else
129 {
130#if SPI_DEBUG
131 int i;
132 pr_debug("\nSPI Write [Len:%d]: ", len);
133 for (i = 0; i < len; i++)
134 {
135 if (i % 8 == 0)
136 printf("\n\t");
137 printf("0x%02X ", TxBuf[i]);
138 }
139 printf("\n");
140
141#endif
142 }
143
144 return ret;
145}
146
147/**
148* 功 能:接收数据
149* 出口参数:
150* RxBuf -> 接收数据缓冲区
151* rtn -> 接收到的长度
152* 返回值:>=0 成功
153* 开发人员:Lzy 2013-5-22
154*/
155int SPI_Read(uint8_t *RxBuf, int len)
156{
157 int ret;
158 int fd = g_SPI_Fd;
159 ret = read(fd, RxBuf, len);
160 if (ret < 0)
161 pr_err("SPI Read error\n");
162 else
163 {
164#if SPI_DEBUG
165 int i;
166 pr_debug("SPI Read [len:%d]:", len);
167 for (i = 0; i < len; i++)
168 {
169 if (i % 8 == 0)
170 printf("\n\t");
171 printf("0x%02X ", RxBuf[i]);
172 }
173 printf("\n");
174#endif
175 }
176
177 return ret;
178}
179
180/**
181* 功 能:打开设备 并初始化设备
182* 入口参数 :
183* 出口参数:
184* 返回值:0 表示已打开 0XF1 表示SPI已打开 其它出错
185* 开发人员:Lzy 2013-5-22
186*/
187int SPI_Open(void)
188{
189 int fd;
190 int ret = 0;
191
192 if (g_SPI_Fd != 0) /* 设备已打开 */
193 return 0xF1;
194
195 fd = open(device, O_RDWR);
196 if (fd < 0)
197 pabort("can't open device");
198 else
199 pr_debug("SPI - Open Succeed. Start Init SPI...\n");
200
201 g_SPI_Fd = fd;
202 /*
203 * spi mode
204 */
205 ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
206 if (ret == -1)
207 pabort("can't set spi mode");
208
209 ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
210 if (ret == -1)
211 pabort("can't get spi mode");
212
213 /*
214 * bits per word
215 */
216 ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
217 if (ret == -1)
218 pabort("can't set bits per word");
219
220 ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
221 if (ret == -1)
222 pabort("can't get bits per word");
223
224 /*
225 * max speed hz
226 */
227 ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
228 if (ret == -1)
229 pabort("can't set max speed hz");
230
231 ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
232 if (ret == -1)
233 pabort("can't get max speed hz");
234
235 pr_debug("spi mode: %d\n", mode);
236 pr_debug("bits per word: %d\n", bits);
237 pr_debug("max speed: %d KHz (%d MHz)\n", speed / 1000, speed / 1000 / 1000);
238
239 return ret;
240}
241
242/**
243* 功 能:关闭SPI模块
244*/
245int SPI_Close(void)
246{
247 int fd = g_SPI_Fd;
248
249 if (fd == 0) /* SPI是否已经打开*/
250 return 0;
251 close(fd);
252 g_SPI_Fd = 0;
253
254 return 0;
255}
256
257/**
258* 功 能:自发自收测试程序
259* 接收到的数据与发送的数据如果不一样 ,则失败
260* 说明:
261* 在硬件上需要把输入与输出引脚短跑
262* 开发人员:Lzy 2013-5-22
263*/
264int SPI_LookBackTest(void)
265{
266 int ret, i;
267 const int BufSize = 16;
268 uint8_t tx[BufSize], rx[BufSize];
269
270 bzero(rx, sizeof(rx));
271 for (i = 0; i < BufSize; i++)
272 tx[i] = i;
273
274 pr_debug("\nSPI - LookBack Mode Test...\n");
275 ret = SPI_Transfer(tx, rx, BufSize);
276 if (ret > 1)
277 {
278 ret = memcmp(tx, rx, BufSize);
279 if (ret != 0)
280 {
281 pr_err("LookBack Mode Test error\n");
282// pabort("error");
283 }
284 else
285 pr_debug("SPI - LookBack Mode OK\n");
286 }
287
288 return ret;
289}
290
291int main(int argc, char *argv[])
292{
293 int ret = 0;
294
295 ret = SPI_Open();
296 if (ret)
297 return ret;
298
299 SPI_LookBackTest();
300
301// unsigned char buf[10];
302// SPI_Write(buf, 10);
303// SPI_Read(buf, 10);
304
305 SPI_Close();
306
307return 0;
308}
309