前言
1. 設備檢查命令
1.1 查看I2C驅動
- 命令:
ls /sys/bus/i2c/devices
用於查看系統上存在的 I2C 總線
- i2c-tools,安裝 i2c-tools 方便調試 i2c設備
1.2.1 I2C-detect安裝
- 使用命令:
sudo apt install i2c-tools -y
安裝 i2c-tools
- 安裝後能夠使用命令:i2cdetect、i2cdump、i2cset 和 i2cget
1.2.2 i2cdetect 命令
- i2cdetect
- 語法
i2cdetect [-y] [-a] [-q|-r] i2cbus [first last]
- 參數
- y:關閉交互模式,使用該參數時,不會提示警告信息。
- a:掃描總線上的全部設備
- q:使用SMBus的「quick write」命令進行檢測,不建議使用該參數
- r:使用SMBus的「receive byte」命令進行檢測,不建議使用該參數
- i2cbus:指定i2c總線的編號
- first、last:掃描的地址範圍
- 返回值
- '-':表示該地址被檢測,可是沒有芯片應答
- 'UU':表示該地址當前由內核驅動程序使用
- '**':** 表示以16進製表示的設備地址編號,如「68」
- 例子:
i2cdetect -a 0
- i2cdetect:i2cdetect命令
- -a:總線上全部設備
- 0:標號爲 0 的 I2C,便是 I2C 1。
- 上圖中掃描出存在設備地址爲 0x1e 和 0x68 的設備。
i2cdetect -F i2cbus
:查詢 i2c 總線的功能,參數 i2cbus 表示 i2c 總線(看上)
i2cdetect -V
:打印軟件的版本號
i2cdetect -l
:檢測當前系統有幾組 i2c 總線
1.2.3 i2cget 命令
- i2cget
- 語法
i2cget [-f] [-y] i2cbus chip-address [data-address [mode]]
- 參數
- f:強制訪問
- y:關閉交互模式,使用該參數時,不會提示警告信息
- i2cbus:指定 I2C 總線的編號
- chip-address:I2C 設備地址
- data-address:I2C 寄存器地址
- mode:指定讀取的大小, 能夠是b, w, s或i,分別對應了字節,字,SMBus塊, I2C塊
1.2.4 i2cset 命令
- i2cset
- 語法
i2cset [-f] [-y] [-m mask] [-r] i2cbus chip-address data-address [value] … [mode]
- 參數
- f:強制訪問
- y:關閉交互模式,使用該參數時,不會提示警告信息
- m:
- r:寫入後當即回讀寄存器值,並將結果與寫入的值進行比較
- i2cbus:指定 I2C 總線的編號
- chip-address:I2C 設備地址
- data-address:I2C 寄存器地址
- value:要寫入的值
- mode:指定讀取的大小, 能夠是b, w, s或i,分別對應了字節,字,SMBus塊, I2C塊
1.2.5 i2cdump 命令
- i2cdump
- 語法
i2cdump [-f] [-r first-last] [-y] i2cbus address [mode [bank [bankreg]]]
- 參數
- r:指定寄存器範圍,只能掃描從 first 到 last 區域
- f:強制訪問設備
- y:關閉人機交互模式
- i2cbus:指定 I2C 總線的編號
- address:指定設備地址
- mode:指定讀取的大小, 能夠是b, w, s或i,分別對應了字節,字,SMBus塊, I2C塊
- 例子
2. 源碼實戰
- 採用MPU6050設備進行實驗
- 步驟:
- 先編寫基礎的 I2C 基礎函數
- 編寫 MPU6050 初始化函數和關閉設備文件函數
- 編寫獲取 MPU6050 數據函數
- 編寫業務函數
2.1 編寫 bsp_mpu6050.h 文件
- 編寫好 MPU6050 須要的宏
- extern 外部函數
/** @file bsp_mpu6050.h
* @brief 簡要說明
* @details 詳細說明
* @author lzm
* @date 2020-11-28 19:22:20
* @version v1.0
* @copyright Copyright By lizhuming, All Rights Reserved
*
**********************************************************
* @LOG 修改日誌:
**********************************************************
*/
#ifndef _BSP_MPU6050_H_
#define _BSP_MPU6050_H_
/* 宏 */
#define SMPLRT_DIV 0x19
#define CONFIG 0x1A
#define GYRO_CONFIG 0x1B
#define ACCEL_CONFIG 0x1C
#define ACCEL_XOUT_H 0x3B
#define ACCEL_XOUT_L 0x3C
#define ACCEL_YOUT_H 0x3D
#define ACCEL_YOUT_L 0x3f
#define ACCEL_ZOUT_H 0x3F
#define ACCEL_ZOUT_L 0x40
#define TEMP_OUT_H 0x41
#define TEMP_OUT_L 0x42
#define GYRO_XOUT_H 0x43
#define GYRO_XOUT_L 0x44
#define GYRO_YOUT_H 0x45
#define GYRO_YOUT_L 0x46
#define GYRO_ZOUT_H 0x47
#define GYRO_ZOUT_L 0x48
#define PWR_MGMT_1 0x6B
#define WHO_AM_I 0x75
#define SlaveAddress 0xD0
#define Address 0x68 //MPU6050地址
#define I2C_RETRIES 0x0701
#define I2C_TIMEOUT 0x0702
#define I2C_SLAVE 0x0703 //IIC從器件的地址設置
#define I2C_BUS_MODE 0x0780
/* 類型轉換 */
typedef unsigned char uint8_t;
/* 函數 */
uint8_t mpu6050_init(char * i2cDev);
void mpu6050_close(void);
short getData(unsigned char regAddr);
#endif /* #define _BSP_MPU6050_H_ */
2.2 編寫 bsp_mpu6050.c 文件
- bsp_mpu6050.c
- 編寫 I2C 讀寫函數
- 編寫 MPU6050 設備初始化函數及關閉文件函數
- 編寫獲取 MPU6050 設備寄存器數據函數
/** @file bsp_mpu6050.c
* @brief 簡要說明
* @details 詳細說明
* @author lzm
* @date 2020-11-28 19:20:20
* @version v1.0
* @copyright Copyright By lizhuming, All Rights Reserved
*
**********************************************************
* @LOG 修改日誌:
**********************************************************
*/
/* 頭文件 */
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/ioctl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<sys/select.h>
#include<sys/time.h>
#include "bsp_mpu6050.h"
/* 設備句柄 */
int i2cFd; // i2c設備句柄
/**
* @brief i2c 寫
* @param fd:i2c設備句柄
* @param regAddr:寄存器地址
* @param val:須要寫入的值
* @retval 0:寫入成功
* @retval -1:寫入失敗
* @author lzm
*/
static uint8_t i2c_write(int fd, uint8_t regAddr, uint8_t val)
{
int cnt; // 寫入失敗後,重複寫入的次數
uint8_t data[2]; // data[0]爲寄存器地址,data[1]爲須要寫入的值
data[0] = regAddr;
data[1] = val;
for(cnt=5; cnt>0; cnt--)
{
if(write(fd, data, 2) == 2)
return 0; // 寫入成功
}
return -1; // 寫入失敗
}
/**
* @brief i2c 讀
* @param fd:i2c設備句柄
* @param regAddr:寄存器地址
* @param val:讀取到數據保存的地方
* @retval 0:讀取成功
* @retval -1:讀取失敗
* @author lzm
*/
static uint8_t i2c_read(int fd, uint8_t regAddr, uint8_t * val)
{
int cnt; // 讀取失敗後,從新讀取的次數
for(cnt=5; cnt>0; cnt--)
{
if(write(fd, ®Addr, 1) == 1)
{
if(read(fd, val, 1) == 1)
return 0;
}
}
return -1;
}
/**
* @brief mpu6050初始化
* @param i2cDev
* @retval 1:初始化成功
* @retval 0:初始化失敗
* @author lzm
*/
uint8_t mpu6050_init(char * i2cDev)
{
i2cFd = open(i2cDev, O_RDWR); // 打開i2c設備文件
if(i2cFd < 0)
{
printf("Can't open %s!\n", i2cDev);
exit(1);
}
printf("Open %s success!", i2cDev);
if(ioctl(i2cFd, I2C_SLAVE, Address) < 0)
{
printf("fail to set i2c device slave address!");
close(i2cFd); // 關閉i2c設備文件
return -1;
}
printf("set slave address to 0x%x success!", Address);
i2c_write(i2cFd, PWR_MGMT_1, 0X00);
i2c_write(i2cFd, SMPLRT_DIV, 0X07);
i2c_write(i2cFd, CONFIG, 0X06);
i2c_write(i2cFd, ACCEL_CONFIG, 0X01);
return 1;
}
/**
* @brief 關閉設備文件
* @param
* @retval
* @author lzm
*/
void mpu6050_close(void)
{
close(i2cFd);
}
/**
* @brief 獲取數據
* @param regAddr:寄存器地址
* @retval 獲取到的數據
* @author lzm
*/
short getData(unsigned char regAddr)
{
char chH; // 高字節
char chL; // 低字節
i2c_read(i2cFd, regAddr, &chH);
usleep(1000);
i2c_read(i2cFd, regAddr, &chL);
return ((chH << 8) + chL);
}
2.3 編寫 main.c 文件
/** @file main.c
* @brief 簡要說明
* @details 詳細說明
* @author lzm
* @date 2020-11-28 19:18:20
* @version v1.0
* @copyright Copyright By lizhuming, All Rights Reserved
*
**********************************************************
* @LOG 修改日誌:
**********************************************************
*/
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/ioctl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<sys/select.h>
#include<sys/time.h>
#include "mpu6050/bsp_mpu6050.h"
int main(int argc, char * argv[])
{
/* 程序開始標語 */
printf("This is a mpu6050 test!\n");
/* 初始化 MCPU6050 */
mpu6050_init("/dev/i2c-0");
sleep(1);
/* mpu6050 應用測試 */
while(1)
{
printf("get mpu6050 data!\n");
usleep(1000 * 100);
printf("ACCE_X:%6d\n ", getData(ACCEL_XOUT_H));
usleep(1000 * 100);
printf("ACCE_Y:%6d\n ", getData(ACCEL_YOUT_H));
usleep(1000 * 100);
printf("ACCE_Z:%6d\n ", getData(ACCEL_ZOUT_H));
usleep(1000 * 100);
printf("GYRO_X:%6d\n ", getData(GYRO_XOUT_H));
usleep(1000 * 100);
printf("GYRO_Y:%6d\n ", getData(GYRO_YOUT_H));
usleep(1000 * 100);
printf("GYRO_Z:%6d\n\n ", getData(GYRO_ZOUT_H));
sleep(1);
}
/* 退出 mpu6050 */
mpu6050_close();
}
相關連接