概述
本文主要讲述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-------从特定寄存器中读值
我们采用如下命令来查找当前设备的地址:
i2cdetect -y -r -a 1
其中-y表示无视交互问题,-r是SMBus read byte命令,-a是所有地址,0表示TX2开发板的i2c-1(TX2有好几个I2C接口)。
3、Linux环境中IIC代码框架讲解
#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 TX2开发板的I2C(IIC)通信所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复