使用 c++ 实现一个 SPI 接口操作类
使用 c++ 实现一个 SPI 接口操作类
记录一下在项目中我常用到的 SPI 接口操作代码。
串口代码
spi.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#ifndef __SPI_H__
#define __SPI_H__
#include <fcntl.h>
#include <linux/spi/spidev.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <cstdint>
#include <cstring>
#include <string>
#include <vector>
class Spi {
public:
explicit Spi(
const std::string &dev_node = "/dev/spidev0.0",
uint8_t mode = SPI_MODE_0,
uint32_t speed = 1000000,
uint8_t bits = 8)
: _dev_node(dev_node),
_mode(mode),
_speed(speed),
_bits(bits),
_fd(-1),
_is_open(false) {
}
~Spi() {
close();
}
void open() {
_fd = ::open(_dev_node.c_str(), O_RDWR);
if (_fd < 0) {
return;
}
// 设置SPI参数
if (ioctl(_fd, SPI_IOC_WR_MODE, &_mode) < 0
|| ioctl(_fd, SPI_IOC_WR_MAX_SPEED_HZ, &_speed) < 0
|| ioctl(_fd, SPI_IOC_WR_BITS_PER_WORD, &_bits) < 0) {
::close(_fd);
_fd = -1;
_is_open = false;
return;
}
_is_open = true;
return;
}
void close() {
if (_fd >= 0) {
::close(_fd);
}
_fd = -1;
_is_open = false;
}
int32_t write(uint8_t *tx_data, uint32_t len) {
if (_fd < 0) {
open();
}
if (!_is_open) {
return -1;
}
return spi_transfer(tx_data, nullptr, len);
}
int32_t read(uint8_t *rx_data, uint32_t len) {
if (_fd < 0) {
open();
}
if (!_is_open || len == 0) {
return -1;
}
std::vector<uint8_t> tx_data(len, 0);
return spi_transfer(tx_data.data(), rx_data, len);
}
int32_t spi_transfer(uint8_t *tx_buf, uint8_t *rx_buf, uint32_t len) {
if (_fd < 0) {
open();
}
spi_ioc_transfer tr = {};
tr.tx_buf = reinterpret_cast<unsigned long long>(tx_buf);
tr.rx_buf = reinterpret_cast<unsigned long long>(rx_buf);
tr.len = len;
tr.speed_hz = _speed;
tr.delay_usecs = 0;
tr.bits_per_word = _bits;
tr.cs_change = 0; // 保持CS激活
if (ioctl(_fd, SPI_IOC_MESSAGE(1), &tr) < 0) {
return -1;
}
return 0;
}
private:
bool _is_open;
int32_t _fd;
uint8_t _mode;
uint32_t _speed;
uint8_t _bits;
std::string _dev_node;
};
#endif // __SPI_H__
使用示例
main.cpp
1
2
3
4
5
6
7
8
9
#include "spi.h"
int main() {
Spi spi("/dev/spidev0.1", SPI_MODE_0, 1000000, 8);
spi.open();
// TODO:
spi.close();
return 0;
}
本文由作者按照 CC BY 4.0 进行授权