一、前言
前文中介绍了普通IO口的使用以及引脚功能互查表的用法,主要想通过简单的IO操作熟悉BBB的使用流程,在BBB的接口中,还在一类功能复用的引脚,如I2C、spi等,本节通过介绍I2C的使用方法,希望能够加深对BBB引脚功能使用的理解。
二 I2C-tool使用
1. i2c-tool基本命令
i2cdetect -l //罗列出系统所有i2c接口
i2cdetect -y -r 1 //罗列出第1个i2c接口下的所有可用设备
i2cdump -y -f 1 0x3a //第一个i2c接口下地址0x3a处的所有寄存器的值
i2cget -y -f 1 0x3a 0x02 //得到第一个i2c接口下地址0x3a处寄存器0x02的值
i2cset -y -f 1 0x3a 0x02 0x05 //设置第一个i2c接口下地址0x3a处寄存器0x02的值为0x05
2. 查看i2C接口
BBB系统中自带了i2c工具,可以通过相关命令查看i2c相关内容,如:
输入i2cdetect -l
命令:
i2c-0 i2c OMAP I2C adapter I2C adapter
i2c-2 i2c OMAP I2C adapter I2C adapter
从结果中可知:BBB已经配置了两个i2c接口可以供使用。
3. 查看IO口
实际上BBB的i2c接口如下图,可以看出如果要使用i2c2则接口可以是P9_19 P9_20或P9-21 P9-22,通过前文BBB引脚功能互查表的用法,可以查出是哪个引脚当前处于I2C功能状态。经查本文中是采用P9_19和P9_20
4. 连接设备
本文采用DS3231时钟模块测试i2C接口,采用BBB板上3.3V给模块供电。如下图:
5. 查看设备地址
通过命令i2cdetect -y -r 2
可以查看总线2下的设备有哪些,如下图,从图中可以看出在地址0x68处有设备,是刚连接的RTC设备:
6. 查看设备寄存器
通过命令i2cdump -y -f 2 0x68
可以查看该设备下的所以寄存器的值,如下图所示,可以看出,从0x00到0x12这18个寄存器可以操作。
7. DS3231的寄存器介绍
通过ds3231的datasheet可以知道各个寄存器的功能,如下图所示,可以得到从0x00到0x06寄存器中分别是秒、分、时、日、月、年。因此程序中我们只需要读取这几个寄存器的值就可以确定时间。
三、程序实现
1. 程序代码
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <linux/i2c-dev.h>
#include <sys/ioctl.h>
#include<iostream>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#define I2C_DIR "/dev/i2c-2" //i2c接口路径
#define CHIP_ADDR 0x68 //RTC设备地址
using namespace std;
char readRegesiterAddr[2];
char readRegesiterData[20];
int main()
{
int fp;
int i = 0, res = 0;
char ioStatus = 0;
fp = open(I2C_DIR, O_RDWR); /*读写模式打开direction*/
if (fp < 0) {
cout << "open failed!" << endl;
return 0;
}
if (ioctl(fp, I2C_TENBIT, 0) < 0) //not 10bi
{
printf("set failed!\r\n");
close(fp);
return 0;
}
if (ioctl(fp, I2C_SLAVE, CHIP_ADDR) < 0) //设置为slave模式
{ /* 设置芯片地址 */
printf("oictl:set slave address failed\n");
close(fp);
return 0;
}
for (i = 0; i<5; i++)
{
readRegesiterAddr[0] = 0x00;
if (write(fp, readRegesiterAddr, 1) != 1) //定稿寄存器地址,从0x00开始读取
{
printf("write addr failed\n");
}
res = read(fp, readRegesiterData, 10); //读取10个寄存器的值
printf("read data len:%d\n", res);
printf("%x, %x, %x, %x, %x, %x\n", readRegesiterData[0], readRegesiterData[1], readRegesiterData[2], readRegesiterData[3], readRegesiterData[4], readRegesiterData[5]);
sleep(1); /*延时一秒*/
}
close(fp);
return 0;
}
2. 程序编译及结果对比
该程序通过上文操作BBB普通IO口进行编译,首先将程序通过nano工具复制保存为i2ctest.cpp
文件,通过前文方法编译为可运行程序test,运行程序可以得到以下结果:
而通过i2cdump -y -f 2 0x68
命令可以对比其读出的寄存器值是否正确,如下图:
由以上两图中红色方框中可以看出除了保存秒的寄存器外,其他寄存器的值均正确。由此实现了通过i2c读取RTC寄存器的值
结语
本文主要通过读取i2c接口上的RTC芯片的寄存器的值来进一步熟悉BBB的一些常用IO口的使用,程序中主要是通过i2c的设备文件/dev/i2c-2
实现i2c接口的打开,并读写i2c设备(如RTC DS3231)的相关寄存器,本次操作中主要为了进一步加深前两节内容的理解。