rtthread工业使用_RT-Thread 设备驱动I2C浅析及使用

#include #include#include"at24cxx.h"

/** at24cxx设备结构体*/

structat24cxx_device

{structrt_device parent;struct rt_i2c_bus_device *bus;

};/*RT-Thread device interface*/

staticrt_err_t at24cxx_init(rt_device_t dev)

{returnRT_EOK;

}staticrt_err_t at24cxx_open(rt_device_t dev, rt_uint16_t oflag)

{returnRT_EOK;

}staticrt_err_t at24cxx_close(rt_device_t dev)

{returnRT_EOK;

}static rt_err_t at24cxx_control(rt_device_t dev, int cmd, void *args)

{returnRT_EOK;

}/**

* @brief at24cxx设备读操作

* @param[in] dev 设备句柄

* @param[in] pos i2c写寻址地址

* @param[in] *buffer 读出数据的指针

* @param[in] size 读出数据的长度

* @return 返回读出成功的字节数

* - 0 读出失败

* - Others 读出成功的字节数*/

static rt_size_t at24cxx_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)

{struct at24cxx_device *at24cxx;const struct at24cxx_config *cfg;struct rt_i2c_msg msg[2];

rt_uint8_t mem_addr[2] = {0,};

rt_size_t ret= 0;

RT_ASSERT(dev!= 0);

at24cxx= (struct at24cxx_device *) dev;

RT_ASSERT(at24cxx->parent.user_data != 0);

cfg= (const struct at24cxx_config *) at24cxx->parent.user_data;if(pos >= cfg->size) //寻址地址超标

{return 0;

}if(pos + size > cfg->size) //size超标

{

size= cfg->size -pos;

}

msg[0].addr = cfg->addr;

msg[0].flags = cfg->flags |RT_I2C_WR;if(cfg->size < 257) //at24c01 at24c02, 一页8字节,寻址地址8位

{

mem_addr[0] =(rt_uint8_t) pos;

msg[0].buf = (rt_uint8_t *) mem_addr;

msg[0].len = 1;

}else //at24c04/08/16 一页16字节,寻址地址9/10/11位

{

mem_addr[0] = (pos >> 8);

mem_addr[1] =(rt_uint8_t) pos;

msg[0].buf = (rt_uint8_t *) mem_addr;

msg[0].len = 2;

}

msg[1].addr = cfg->addr;

msg[1].flags = cfg->flags |RT_I2C_RD;

msg[1].buf = (rt_uint8_t *) buffer;

msg[1].len =size;

ret= rt_i2c_transfer(at24cxx->bus, msg, 2);return (ret == 2) ? size : 0;

}/**

* @brief at24cxx设备写操作

* @param[in] dev 设备句柄

* @param[in] pos i2c写寻址地址

* @param[in] *buffer 写入数据的指针

* @param[in] size 写入数据的长度

* @return 返回写入成功的字节数

* - 0 写入失败

* - Others 写入成功的字节数*/

#if 0 //连续页写测试

static rt_size_t at24cxx_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)

{struct at24cxx_device *at24cxx;const struct at24cxx_config *cfg;struct rt_i2c_msg msg[2];

rt_uint8_t mem_addr[2] = {0,};

rt_size_t ret= 0;

RT_ASSERT(dev!= 0);

at24cxx= (struct at24cxx_device *) dev;

RT_ASSERT(at24cxx->parent.user_data != 0);

cfg= (const struct at24cxx_config *) at24cxx->parent.user_data;if(pos > cfg->size)

{return 0;

}if(pos + size > cfg->size)

{

size= cfg->size -pos;

}/*计算出要写的页数和分页*/rt_uint8_t NumOfPage= 0; //总页写数,包括写的不完整页

rt_uint8_t Addr = 0; //页写的寻址地址

rt_uint8_t count = 0; //页写入的字节数

rt_uint8_t i;if(size > (PAGE_SIZE - pos%PAGE_SIZE))

{

count= PAGE_SIZE - pos%PAGE_SIZE; //写入的第一页长度

NumOfPage = (size - count)/PAGE_SIZE; //剩余写入的完整页数

if((size - (count + NumOfPage*PAGE_SIZE)) > 0)

NumOfPage= NumOfPage + 2;elseNumOfPage= NumOfPage + 1;

}else{

NumOfPage= 1;

}for(i=0; i

{if(i == 0)

{

Addr=pos;if(NumOfPage == 1)

{

count=size;

}else{

count= PAGE_SIZE - pos%PAGE_SIZE;

}

}else if((i == NumOfPage-1) && (NumOfPage > 1))

{

Addr= pos - pos%PAGE_SIZE + i*PAGE_SIZE;

count= pos + size -Addr;

}else{

Addr= pos - pos%PAGE_SIZE + i*PAGE_SIZE;

count=PAGE_SIZE;

}//写入寻址地址

msg[0].addr = cfg->addr;

msg[0].flags = cfg->flags |RT_I2C_WR;if(cfg->size < 257) //at24c01 at24c02, 一页8字节,寻址地址8位

{

mem_addr[0] =(rt_uint8_t) Addr;

msg[0].buf = (rt_uint8_t *) mem_addr;

msg[0].len = 1;

}else //at24c04/08/16 一页16字节,寻址地址9/10/11位

{

mem_addr[0] = (Addr >> 8);

mem_addr[1] =(rt_uint8_t) Addr;

msg[0].buf = (rt_uint8_t *) mem_addr;

msg[0].len = 2;

}//使用RT_I2C_NO_START,直接写入buffer数据

msg[1].addr = cfg->addr;

msg[1].flags = cfg->flags | RT_I2C_WR |RT_I2C_NO_START;

msg[1].buf = (rt_uint8_t *) buffer+count;

msg[1].len =count;

ret= rt_i2c_transfer(at24cxx->bus, msg, 2);if(ret != 2)return 0;

}returncount;

}#endif

#if 1 //不支持连续页写

static rt_size_t at24cxx_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)

{struct at24cxx_device *at24cxx;const struct at24cxx_config *cfg;struct rt_i2c_msg msg[2];

rt_uint8_t mem_addr[2] = {0,};

rt_size_t ret= 0;

RT_ASSERT(dev!= 0);

at24cxx= (struct at24cxx_device *) dev;

RT_ASSERT(at24cxx->parent.user_data != 0);

cfg= (const struct at24cxx_config *) at24cxx->parent.user_data;if(pos > cfg->size)

{return 0;

}if(pos + size > cfg->size)

{

size= cfg->size -pos;

}//写入寻址地址

msg[0].addr = cfg->addr;

msg[0].flags = cfg->flags |RT_I2C_WR;if(cfg->size < 257) //at24c01 at24c02, 一页8字节,寻址地址8位

{

mem_addr[0] =(rt_uint8_t) pos;

msg[0].buf = (rt_uint8_t *) mem_addr;

msg[0].len = 1;

}else //at24c04/08/16 一页16字节,寻址地址9/10/11位

{

mem_addr[0] = (pos >> 8);

mem_addr[1] =(rt_uint8_t) pos;

msg[0].buf = (rt_uint8_t *) mem_addr;

msg[0].len = 2;

}//使用RT_I2C_NO_START,直接写入buffer数据

msg[1].addr = cfg->addr;

msg[1].flags = cfg->flags | RT_I2C_WR |RT_I2C_NO_START;

msg[1].buf = (rt_uint8_t *) buffer;

msg[1].len =size;

ret= rt_i2c_transfer(at24cxx->bus, msg, 2);return (ret == 2) ? size : 0;

}#endif#ifdef RT_USING_DEVICE_OPS/** at24cxx设备操作ops*/

const static struct rt_device_ops at24cxx_ops ={

at24cxx_init,

at24cxx_open,

at24cxx_close,

at24cxx_read,

at24cxx_write,

at24cxx_control

};#endif

/**

* @brief at24cxx设备注册

* @param[in] *fm_device_name 设备名称

* @param[in] *i2c_bus i2c总线设备名称

* @param[in] *user_data 用户数据 at24cxx_config

* @return 函数执行结果

* - RT_EOK 执行成功

* - Others 失败*/rt_err_t at24cxx_register(const char *fm_device_name, const char *i2c_bus, void *user_data)

{static structat24cxx_device at24cxx_drv;struct rt_i2c_bus_device *bus;

bus=rt_i2c_bus_device_find(i2c_bus);if (bus ==RT_NULL)

{returnRT_ENOSYS;

}

at24cxx_drv.bus=bus;

at24cxx_drv.parent.type=RT_Device_Class_Block;

#ifdef RT_USING_DEVICE_OPS

at24cxx_drv.parent.ops= &at24cxx_ops;#elseat24cxx_drv.parent.init=at24cxx_init;

at24cxx_drv.parent.open=at24cxx_open;

at24cxx_drv.parent.close=at24cxx_close;

at24cxx_drv.parent.read=at24cxx_read;

at24cxx_drv.parent.write=at24cxx_write;

at24cxx_drv.parent.control=at24cxx_control;#endifat24cxx_drv.parent.user_data=user_data;return rt_device_register(&at24cxx_drv.parent, fm_device_name, RT_DEVICE_FLAG_RDWR);

}

你可能感兴趣的:(rtthread工业使用)