/
linux-i2c_test.c
139 lines (118 loc) · 2.54 KB
/
linux-i2c_test.c
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// I2C test program for a PCA9555
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <linux/i2c-dev.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
// I2C Linux device handle
int g_i2cFile;
// open the Linux device
void i2cOpen()
{
g_i2cFile = open("/dev/i2c-1", O_RDWR);
if (g_i2cFile < 0) {
perror("i2cOpen");
exit(1);
}
}
// close the Linux device
void i2cClose()
{
close(g_i2cFile);
}
// set the I2C slave address for all subsequent I2C device transfers
void i2cSetAddress(int address)
{
if (ioctl(g_i2cFile, I2C_SLAVE, address) < 0) {
perror("i2cSetAddress");
exit(1);
}
}
// write a 16 bit value to a register pair
// write low byte of value to register reg,
// and high byte of value to register reg+1
void pca9555WriteRegisterPair(uint8_t reg, uint16_t value)
{
uint8_t data[3];
data[0] = reg;
data[1] = value & 0xff;
data[2] = (value >> 8) & 0xff;
if (write(g_i2cFile, data, 3) != 3) {
perror("pca9555SetRegisterPair");
}
}
// read a 16 bit value from a register pair
uint16_t pca9555ReadRegisterPair(uint8_t reg)
{
uint8_t data[3];
data[0] = reg;
if (write(g_i2cFile, data, 1) != 1) {
perror("pca9555ReadRegisterPair set register");
}
if (read(g_i2cFile, data, 2) != 2) {
perror("pca9555ReadRegisterPair read value");
}
return data[0] | (data[1] << 8);
}
// set IO ports to input, if the corresponding direction bit is 1,
// otherwise set it to output
void pca9555SetInputDirection(uint16_t direction)
{
pca9555WriteRegisterPair(6, direction);
}
// set the IO port outputs
void pca9555SetOutput(uint16_t value)
{
pca9555WriteRegisterPair(2, value);
}
// read the IO port inputs
uint16_t pca9555GetInput()
{
return pca9555ReadRegisterPair(0);
}
int main(int argc, char** argv)
{
// test output value
int v = 3;
// direction of the LED animation
int directionLeft = 1;
// open Linux I2C device
i2cOpen();
// set address of the PCA9555
i2cSetAddress(0x3c);
// set input for IO pin 15, rest output
pca9555SetInputDirection(1 << 15);
// LED animation loop
while (1) {
// if button is pressed, invert output
int xor;
if (pca9555GetInput() & 0x8000) {
xor = 0;
} else {
xor = 0xffff;
}
// set current output
pca9555SetOutput(v ^ xor);
// animate LED position
if (directionLeft) {
v <<= 1;
} else {
v >>= 1;
}
if (v == 0x6000) {
directionLeft = 0;
}
if (v == 3) {
directionLeft = 1;
}
// wait 100 ms for next animation step
usleep(100000);
}
// close Linux I2C device
i2cClose();
return 0;
}