本文主要讲述TX2开发板和BMP280高度计采用IIC通讯。
1、首先,要用杜邦线对两者进行连接,连接示意图如下:
对于高度计来说,SCL和SDA分别是IIC通讯的时钟线和地址线,CSB是高度计的激活位,必须连接3.3V的高电平,SDO是地址选择位,若SDO接地,则高度计的地址为0X76,若接3.3V的高电平,则高度计地址为0X77。
对于TX2开发板来说,我们选择J21模块,其中J21_1表示J21模块的1接口。J21_1和J21_17是3.3V的高电平,J21_6和J21_39是低电平(接地),J21_3是SDA接口,J21_5是SCL接口。
2、接下来是查找地址。
采用i2c-tools命令行工具
i2cdetect----用来查找所连接的设备的地址
i2cdump----用来读出特定地址中所有寄存器中的内容
i2cset--------对特定寄存器写入内容
i2cget-------从特定寄存器中读值
我们采用如下命令来查找当前设备的地址:
1i2cdetect -y -r -a 1
其中-y表示无视交互问题,-r是SMBus read byte命令,-a是所有地址,0表示TX2开发板的i2c-1(TX2有好几个I2C接口)。
3、Linux环境中IIC代码框架讲解
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181#include <stdio.h> #include <stdint.h> #include <fcntl.h> #include <unistd.h> #include <sys/ioctl.h> #include "i2c.h" #include <linux/i2c-dev.h> #define BMP280_ADD 0x76 //高度计的地址 #define DIG_START 0x88 //温度补偿寄存器的起始地址 #define TEMP_START 0xFA //温度测量寄存器的起始地址 #define DIGP_START 0X8E //压强补偿寄存器的起始地址 #define PRESS_START 0XF7 //压强测量寄存器的起始地址 #define CTRL_MEAS 0xF4 //选择模式控制寄存器的地址 #define TEMP_ONLY_NORMAL_MODE 0xFF // 111 111 11 对寄存器的读写方式 int32_t t_fine=0; //向特定的寄存器写值,用于设置读写方式 int writeReg(int pt, unsigned char add, char value){ unsigned char w_buff[2]; w_buff[0] = add; w_buff[1] = value; if (write(pt, w_buff, 2) != 2){ perror("Failed write to device"); return 1; } return 0; } //从特定的寄存器中读取数据,先写地址寻找这个寄存器,然后读取寄存器中的内容 int readReg(int pt, unsigned char s_add, char buf[], int size){ char writeBuff[1] = {s_add}; if(write(pt, writeBuff, 1)!=1) { perror("Failed to reset the read addressn"); return 1; } if(read(pt, buf, size)!=size){ perror("Failed to read in the buffern"); return 1; } return 0; } //温度补偿 float myFunc(int32_t adc_T, unsigned short dig_T1, short dig_T2, short dig_T3){ double var1, var2, T; var1 = (((double)adc_T)/16384.0-((double)dig_T1)/1024.0)*((double)dig_T2); var2 = ((((double)adc_T)/131072.0-((double)dig_T1)/8192.0)*(((double)adc_T)/131072.0-((double)dig_T1)/8192.0))*((double)dig_T3); t_fine =(int32_t)(var1+var2); T = (var1+var2)/5120.0; return T; } //压强补偿 float myFunc_p(int32_t adc_P,unsigned short dig_P1,short dig_P2,short dig_P3,short dig_P4,short dig_P5,short dig_P6,short dig_P7,short dig_P8,short dig_P9) { double var1,var2,p; if(t_fine==0) printf("t_fine is 0!The pressure measurement is not right!Please check temperament measurementn"); var1 = ((double)t_fine/2.0)-64000.0; var2 = var1 * var1 * ((double)dig_P6) / 32768.0; var2 = var2 + var1 * ((double)dig_P5) * 2.0; var2 = (var2/4.0)+(((double)dig_P4) * 65536.0); var1 = (((double)dig_P3) * var1 * var1 / 524288.0 + ((double)dig_P2) * var1) / 524288.0; var1 = (1.0 + var1 / 32768.0)*((double)dig_P1); if (var1 == 0.0) return 0; // avoid exception caused by division by zero p=1048576.0-(double)adc_P; p=(p-(var2/4096.0))*6250.0/var1; var1=((double)dig_P9)*p*p/2147483648.0; var2=p*((double)dig_P8)/32768.0; p = p+(var1+var2+((double)dig_P7))/16.0; return p; } int main(){ int file; if((file=open("/dev/i2c-1", O_RDWR)) < 0) { //以只读方式打开i2c地址 perror("failed to open the busn"); return 1; } if(ioctl(file, I2C_SLAVE, BMP280_ADD) < 0) { //让高度计作为IIC从设备 perror("Failed to connect to the sensorn"); return 1; } char dig_buff[6]; // temperament compensation data char tmp_buff[3]; // temperament data char digp_buff[18]; // pressure compensation data char pre_buff[3]; //pressure data if(writeReg(file, CTRL_MEAS, TEMP_ONLY_NORMAL_MODE)==1){ return 1; } //读取温度计的值 if(readReg(file, DIG_START, dig_buff, 6)==1){ return 1; } if(readReg(file, TEMP_START, tmp_buff, 3)==1){ return 1; } //读取压强的值 if(readReg(file, DIGP_START, digp_buff, 18)==1){ return 1; } if(readReg(file, PRESS_START, pre_buff, 3)==1){ return 1; } close(file); printf("temperament:n"); int i; for (i=0; i<6; i++){ printf("%02x ",dig_buff[i]); } printf("n"); for (i=0; i<3; i++){ printf("%02x ",tmp_buff[i]); } printf("n"); printf("pressure:n"); for (i=0;i<18;i++){ printf("%02x ",digp_buff[i]); } printf("n"); for(i=0;i<3;i++){ printf("%02x ",pre_buff[i]); } printf("n"); //temperament int adc_T = ((tmp_buff[0]<<16)|(tmp_buff[1]<<8)|(tmp_buff[2]))>>4; //pressure int adc_P = ((pre_buff[0]<<16)|(pre_buff[1]<<8)|(pre_buff[2]))>>4; // for temperament unsigned short dig_T1 = (dig_buff[1]<<8)|(dig_buff[0]); short dig_T2 = (dig_buff[3]<<8)|(dig_buff[2]); short dig_T3 = (dig_buff[5]<<8)|(dig_buff[4]); // for pressure unsigned short dig_P1 = (digp_buff[1]<<8)|(digp_buff[0]); short dig_P2 = (digp_buff[3]<<8)|(digp_buff[2]); short dig_P3 = (digp_buff[5]<<8)|(digp_buff[4]); short dig_P4 = (digp_buff[7]<<8)|(digp_buff[6]); short dig_P5 = (digp_buff[9]<<8)|(digp_buff[8]); short dig_P6 = (digp_buff[11]<<8)|(digp_buff[10]); short dig_P7 = (digp_buff[13]<<8)|(digp_buff[12]); short dig_P8 = (digp_buff[15]<<8)|(digp_buff[14]); short dig_P9 = (digp_buff[17]<<8)|(digp_buff[16]); printf("adc_T is : %d n", adc_T); printf("dig_T1 is : %d n", dig_T1); printf("dig_T2 is : %d n", dig_T2); printf("dig_T3 is : %d n", dig_T3); printf("Temperature is : %f DegCn", myFunc(adc_T, dig_T1, dig_T2, dig_T3)); printf("adc_P is : %d n", adc_P); printf("dig_P1 is : %d n", dig_P1); printf("dig_P2 is : %d n", dig_P2); printf("dig_P3 is : %d n", dig_P3); printf("dig_P4 is : %d n", dig_P4); printf("dig_P5 is : %d n", dig_P5); printf("dig_P6 is : %d n", dig_P6); printf("dig_P7 is : %d n", dig_P7); printf("dig_P8 is : %d n", dig_P8); printf("dig_P9 is : %d n", dig_P9); printf("pressure is :%f KPan",myFunc_p(adc_P,dig_P1,dig_P2,dig_P3,dig_P4,dig_P5,dig_P6,dig_P7,dig_P8,dig_P9)/1000.0); return 0; }
以上代码一般只要看懂关键部分即可(用汉语标注的地方),这样就可以学会写适用于自己IIC设备的通讯代码了。
关于BMP280的资料,可以下去自己查资料,或者查看这个博客:http://www.cnblogs.com/leptonation/p/5210331.html
就会明白这些寄存器地址的意义了。
写这篇博客的主要出发点有两个,一个是讲解TX2与IIC设备的连接方式,另一个是讲解Linux下IIC通信的大概思路(即代码框架),BMP280高度计的具体细节不在讲解之内。有问题欢迎提问。
最后
以上就是火星上面包最近收集整理的关于NVIDIA TX2开发板的I2C(IIC)通信的全部内容,更多相关NVIDIA内容请搜索靠谱客的其他文章。
发表评论 取消回复