【超小型 Linux 开发套件Quantum Tiny Linux】MPU6050驱动编写
<div class='showpostmsg'><p>前面我们确认了mpu6050对应i2c-0,地址为0x68.</p><p > </p>
<p >现在开始就可以进行驱动编写了。</p>
<p > </p>
<p >先封装IIC读写接口。</p>
<p > </p>
<pre>
<code class="language-cpp">/**
* \fn i2c_init
* 初始化,打开设备
* \param dev_path 设备路径,比如"/dev/i2c-0"
* \return 返回打开的设备的句柄,和open返回值一样
*/
int i2c_init(char* dev_path)
{
return open(dev_path, O_RDWR);
}
/**
* \fn i2c_deinit
* 解除初始化,关闭设备
* \param fd 打开的设备句柄
* \return 和close返回值一样
*/
int i2c_deinit(int fd)
{
return close(fd);
}
/**
* \fn i2c_write
* 写数据
* \param fd 打开的设备句柄
* \param dev_addr I2C设备地址
* \param reg_addr 寄存器地址
* \param data 待写入数据
* \param len 待写入数据字节数
*
* \return 0成功 其他值失败
*/
int i2c_write(int fd, uint8_t dev_addr, uint8_t reg_addr, uint8_t* data, uint32_t len)
{
int ret = -1;
uint8_t* buff = malloc(len+1);
if(buff == NULL)
{
return -1;
}
buff = reg_addr;
memcpy(&buff, data, len);
/* 构造msg */
struct i2c_msg msg = {
.addr = dev_addr,
.flags = 0,
.len = len + 1,
.buf = buff,
};
struct i2c_rdwr_ioctl_data rdwr_msg = {
.msgs = &msg,
.nmsgs = 1,
};
ret = ioctl(fd, I2C_RDWR, &rdwr_msg);
free(buff);
return ret;
}
/**
* \fn i2c_read
* 读数据
* \param fd 打开的设备句柄
* \param dev_addr I2C设备地址
* \param reg_addr 寄存器地址
* \param data 存储读出数据
* \param len 待读出数据字节数
*
* \return 0成功 其他值失败
*/
int i2c_read(int fd, uint8_t dev_addr, uint8_t reg_addr, uint8_t* data, uint32_t len)
{
int ret = -1;
/* 构造msg */
struct i2c_msg msg = {
{
.addr = dev_addr, /* 设备地址 */
.flags = 0, /* 标志,为0表示写数据 */
.len = 1, /* 要写的数据的长度 */
.buf = &reg_addr, /* 要写的数据的地址 */
},
{
.addr = dev_addr, /* 设备地址 */
.flags = I2C_M_RD, /* 标志,I2C_M_RD表示主机向主机读数据 */
.len = len, /* 要读取的数据的长度 */
.buf = data, /* 读取的数据存放的地址 */
},
};
struct i2c_rdwr_ioctl_data rdwr_msg = {
.msgs = msg,
.nmsgs = 2,
};
ret = ioctl(fd, I2C_RDWR, &rdwr_msg);
return ret;
}</code></pre>
<p>实现mpu6050驱动</p>
<p >Mpu6050.c</p>
<pre>
<code class="language-cpp">#include "mpu6050.h"
int mpu6050_init(mpu6050_dev_st* dev)
{
if(dev == (mpu6050_dev_st*)0)
{
return -1;
}
if(dev->init != (mpu6050_iic_init_pf)0)
{
dev->init();
}
}
int mpu6050_deinit(mpu6050_dev_st* dev)
{
if(dev == (mpu6050_dev_st*)0)
{
return -1;
}
if(dev->deinit != (mpu6050_iic_deinit_pf)0)
{
dev->deinit();
}
}
int mpu6050_cfg(mpu6050_dev_st* dev, mpu6050_cfg_st* cfg, uint32_t num)
{
if(dev == (mpu6050_dev_st*)0)
{
return -1;
}
if(cfg == (mpu6050_cfg_st*)0)
{
return -1;
}
for(uint32_t i=0; i<num; i++)
{
if(dev->write != (mpu6050_iic_write_pf)0)
{
dev->write(dev->dev_addr, cfg->reg, &(cfg->val), 1);
if(dev->delayms != (mpu6050_delayms_pf)0)
{
dev->delayms(cfg->delay_ms);
}
}
}
}
int mpu6050_get_gyro(mpu6050_dev_st* dev,uint16_t* val)
{
dev->read(dev->dev_addr,0x43,(uint8_t*)val,6);
for(int i=0; i<3; i++)
{
val = ((val>>8)&0x00FF) | ((val<<8)&0xFF00);
}
}
int mpu6050_get_accel(mpu6050_dev_st* dev,uint16_t* val)
{
dev->read(dev->dev_addr,0x3B,(uint8_t*)val,6);
for(int i=0; i<3; i++)
{
val = ((val>>8)&0x00FF) | ((val<<8)&0xFF00);
}
}
int mpu6050_get_temp(mpu6050_dev_st* dev,uint16_t* val)
{
dev->read(dev->dev_addr,0x41,(uint8_t*)val,2);
val = ((val>>8)&0x00FF) | ((val<<8)&0xFF00);
}
</code></pre>
<p> </p>
<p> </p>
<p>mpu6050.h</p>
<pre>
<code class="language-cpp">#ifndef MPU6050_H
#define MPU6050_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
typedef int (*mpu6050_iic_write_pf)(uint8_t dev_addr, uint8_t reg_addr, uint8_t* val, uint32_t len);
typedef int (*mpu6050_iic_read_pf)(uint8_t dev_addr, uint8_t reg_addr, uint8_t* val, uint32_t len);
typedef int (*mpu6050_iic_init_pf)(void);
typedef int (*mpu6050_iic_deinit_pf)(void);
typedef void (*mpu6050_delayms_pf)(uint32_t ms);
typedef struct{
uint8_t dev_addr;
mpu6050_iic_write_pf write;
mpu6050_iic_read_pf read;
mpu6050_iic_init_pf init;
mpu6050_iic_deinit_pf deinit;
mpu6050_delayms_pf delayms;
} mpu6050_dev_st;
typedef struct{
uint8_t reg;
uint8_t val;
uint32_t delay_ms;
} mpu6050_cfg_st;
int mpu6050_init(mpu6050_dev_st* dev);
int mpu6050_deinit(mpu6050_dev_st* dev);
int mpu6050_cfg(mpu6050_dev_st* dev, mpu6050_cfg_st* cfg, uint32_t num);
int mpu6050_get_gyro(mpu6050_dev_st* dev,uint16_t* val);
int mpu6050_get_accel(mpu6050_dev_st* dev,uint16_t* val);
int mpu6050_get_temp(mpu6050_dev_st* dev,uint16_t* val);
#ifdef __cplusplus
}
#endif
#endif
</code></pre>
<p>实现mpu6050_itf.c</p>
<pre>
<code class="language-cpp">#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
//#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include "mpu6050.h"
/**
* \fn i2c_init
* 初始化,打开设备
* \param dev_path 设备路径,比如"/dev/i2c-0"
* \return 返回打开的设备的句柄,和open返回值一样
*/
int i2c_init(char* dev_path)
{
return open(dev_path, O_RDWR);
}
/**
* \fn i2c_deinit
* 解除初始化,关闭设备
* \param fd 打开的设备句柄
* \return 和close返回值一样
*/
int i2c_deinit(int fd)
{
return close(fd);
}
/**
* \fn i2c_write
* 写数据
* \param fd 打开的设备句柄
* \param dev_addr I2C设备地址
* \param reg_addr 寄存器地址
* \param data 待写入数据
* \param len 待写入数据字节数
*
* \return 0成功 其他值失败
*/
int i2c_write(int fd, uint8_t dev_addr, uint8_t reg_addr, uint8_t* data, uint32_t len)
{
int ret = -1;
uint8_t* buff = malloc(len+1);
if(buff == NULL)
{
return -1;
}
buff = reg_addr;
memcpy(&buff, data, len);
/* 构造msg */
struct i2c_msg msg = {
.addr = dev_addr,
.flags = 0,
.len = len + 1,
.buf = buff,
};
struct i2c_rdwr_ioctl_data rdwr_msg = {
.msgs = &msg,
.nmsgs = 1,
};
ret = ioctl(fd, I2C_RDWR, &rdwr_msg);
free(buff);
return ret;
}
/**
* \fn i2c_read
* 读数据
* \param fd 打开的设备句柄
* \param dev_addr I2C设备地址
* \param reg_addr 寄存器地址
* \param data 存储读出数据
* \param len 待读出数据字节数
*
* \return 0成功 其他值失败
*/
int i2c_read(int fd, uint8_t dev_addr,uint8_t reg_addr, uint8_t* data, uint32_t len)
{
int ret = -1;
/* 构造msg */
struct i2c_msg msg = {
{
.addr = dev_addr, /* 设备地址 */
.flags = 0, /* 标志,为0表示写数据 */
.len = 1, /* 要写的数据的长度 */
.buf = &reg_addr, /* 要写的数据的地址 */
},
{
.addr = dev_addr, /* 设备地址 */
.flags = I2C_M_RD,/* 标志,I2C_M_RD表示主机向主机读数据 */
.len = len, /* 要读取的数据的长度 */
.buf = data, /* 读取的数据存放的地址 */
},
};
struct i2c_rdwr_ioctl_data rdwr_msg = {
.msgs = msg,
.nmsgs = 2,
};
ret = ioctl(fd, I2C_RDWR, &rdwr_msg);
return ret;
}
int s_fd = -1;
int mpu6050_iic_write_port(uint8_t dev_addr, uint8_t reg_addr, uint8_t* val, uint32_t len)
{
i2c_write(s_fd, dev_addr, reg_addr, val, len);
}
int mpu6050_iic_read_port(uint8_t dev_addr, uint8_t reg_addr, uint8_t* val, uint32_t len)
{
i2c_read(s_fd, dev_addr, reg_addr, val, len);
}
int mpu6050_iic_init_port(void)
{
s_fd = i2c_init("/dev/i2c-0");
}
int mpu6050_iic_deinit_port(void)
{
i2c_deinit(s_fd);
}
void mpu6050_delayms_port(uint32_t ms)
{
usleep(ms*1000);
}
mpu6050_dev_st s_mpu6050_dev =
{
.dev_addr = 0x68,
.write = mpu6050_iic_write_port,
.read = mpu6050_iic_read_port,
.init = mpu6050_iic_init_port,
.deinit = mpu6050_iic_deinit_port,
.delayms = mpu6050_delayms_port,
};
mpu6050_cfg_st s_mpu6050_cfg[] =
{
{0x6B,0x01,100},
{0x19,0x04,0},
{0x1A,0x02,0},
{0x1B,3<<3,0},
{0x1C,2<<3,0},
{0x37,0x32,0},
{0x38,0x00,0},
{0x6A,0x00,0},
};
int mpu6050_itf_init(void)
{
mpu6050_init(&s_mpu6050_dev);
mpu6050_cfg(&s_mpu6050_dev, s_mpu6050_cfg, sizeof(s_mpu6050_cfg)/sizeof(s_mpu6050_cfg));
}
int mpu6050_itf_deinit(void)
{
mpu6050_deinit(&s_mpu6050_dev);
}
int mpu6050_itf_get_gyro(uint16_t* val)
{
mpu6050_get_gyro(&s_mpu6050_dev,val);
}
int mpu6050_itf_get_accel(uint16_t* val)
{
mpu6050_get_accel(&s_mpu6050_dev,val);
}
int mpu6050_itf_get_temp(uint16_t* val)
{
mpu6050_get_temp(&s_mpu6050_dev,val);
}
int main(void)
{
uint16_t gyro;
uint16_t accel;
uint16_t temp;
mpu6050_itf_init();
int i = 60;
while(i--)
{
mpu6050_itf_get_gyro(gyro);
printf("gyro:%d,%d,%d\r\n",gyro,gyro,gyro);
mpu6050_itf_get_accel(accel);
printf("accel:%d,%d,%d\r\n",accel,accel,accel);
mpu6050_itf_get_temp(&temp);
printf("temp:%d\r\n",temp);
sleep(1);
}
mpu6050_itf_init();
}</code></pre>
<p >Mpu6050_itf.h</p>
<pre>
<code class="language-cpp">#ifndef MPU6050_ITF_H
#define MPU6050_ITF_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
int mpu6050_itf_init(void);
int mpu6050_itf_deinit(void);
int mpu6050_itf_get_gyro(uint16_t* val);
int mpu6050_itf_get_accel(uint16_t* val);
int mpu6050_itf_get_temp(uint16_t* val);
#ifdef __cplusplus
}
#endif
#endif
</code></pre>
<p >rz导入到开发板</p>
<p > </p>
<p >编译</p>
<p >gcc mpu6050.c mpu6050_itf.c -o mpu6050</p>
<p > </p>
<p >运行</p>
<p >./mpu6050</p>
<p > </p>
<p > </p>
<p >结果如下</p>
<p > </p>
</div><script> var loginstr = '<div class="locked">查看本帖全部内容,请<a href="javascript:;" style="color:#e60000" class="loginf">登录</a>或者<a href="https://bbs.eeworld.com.cn/member.php?mod=register_eeworld.php&action=wechat" style="color:#e60000" target="_blank">注册</a></div>';
if(parseInt(discuz_uid)==0){
(function($){
var postHeight = getTextHeight(400);
$(".showpostmsg").html($(".showpostmsg").html());
$(".showpostmsg").after(loginstr);
$(".showpostmsg").css({height:postHeight,overflow:"hidden"});
})(jQuery);
} </script><script type="text/javascript">(function(d,c){var a=d.createElement("script"),m=d.getElementsByTagName("script"),eewurl="//counter.eeworld.com.cn/pv/count/";a.src=eewurl+c;m.parentNode.insertBefore(a,m)})(document,523)</script> <p>结果应该是正确的吧</p>
<p>面向对象的驱动,移植起来非常之方便。</p>
Jacktang 发表于 2024-7-14 07:26
结果应该是正确的吧
<p>这一篇还没换算,下篇文章换算成最终结果了</p>
<p>谢谢分享,期待后续!</p>
页:
[1]