at24c08 E2PROM的I2C设备驱动实例——基于mini2440
AT24C08提供8192位的串行电可擦写可编程只读存储器(EEPROM), 16字节页写模式。
static struct at24_platform_data at24_platdata = {
.byte_len = 8192,//字节大小
.page_size = 16,//页数大小
};
static struct i2c_board_info mini2440_i2c_devices[] = {
{
I2C_BOARD_INFO("24c08",0x50),//第一个参数是硬件名称,驱动的名字匹配不上的时候,会和这个匹配,第二个参数是IIC硬件地址。
.platform_data = &at24_platdata,
}
};
i2c_register_board_info(0,mini2440_i2c_devices,ARRAY_SIZE(mini2440_i2c_devices));//注册板级信息
make zImage
#include<linux/init.h>
#include<linux/module.h>
#include<linux/i2c.h>
#include<linux/fs.h>
#include<linux/device.h>
#include<linux/slab.h>
#include<asm/uaccess.h>
#define E2PROM_MAJOR 250//可以通过cat /proc/devices查看哪些设备号没有被使用
MODULE_LICENSE("GPL");
struct e2prom_device{
struct i2c_client *at24c02_client;
struct class *at24c02_class;
struct device *at24c02_device;
};
struct e2prom_device *e2prom_dev;
struct i2c_device_id e2prom_table[]={
[0]={
.name ="24c02",
.driver_data =0,
},
[1]={
.name ="24c08",
.driver_data =0,
},
};
static int i2c_read_byte(char *buf,int count)
{
int ret=0;
struct i2c_msg msg;
msg.addr =e2prom_dev->at24c02_client->addr;//0x05
msg.flags =1;//1 代表读 0 代表写
msg.len =count;
msg.buf =buf;
ret=i2c_transfer(e2prom_dev->at24c02_client->adapter,&msg,1);
if(ret<0){
printk("i2c transfer failed!\n");
return -EINVAL;
}
return ret;
}
static int i2c_write_byte(char *buf,int count)
{
int ret=0;
struct i2c_msg msg;
msg.addr =e2prom_dev->at24c02_client->addr;//0x05
msg.flags =0; //写
msg.len =count;
msg.buf =buf;
ret=i2c_transfer(e2prom_dev->at24c02_client->adapter,&msg,1);
if(ret<0){
printk("i2c transfer failed!\n");
return -EINVAL;
}
return ret;
}
static int e2prom_open(struct inode *inode, struct file *file)
{
return 0;
}
static size_t e2prom_read(struct file *filep, char __user *buf, size_t size,
loff_t *ppos)
{
int ret = 0;
char *tmp;
tmp = kmalloc(size,GFP_KERNEL);
if(tmp==NULL){
printk("malloc failed!\n");
return -ENOMEM;
}
ret = i2c_read_byte(tmp,size);
if(ret<0){
printk("read byte failed!\n");
ret = -EINVAL;
goto err0;
}
ret = copy_to_user(buf,tmp,size);
if(ret){
printk("copy data failed!\n");
ret =-EINVAL;
goto err0;
}
kfree(tmp);
return size;
err0:
kfree(tmp);
return ret;
}
static ssize_t e2prom_write(struct file *filep, const char __user *buf, size_t size,
loff_t *ppos)
{
int ret = 0;
char *tmp;
tmp = kmalloc(size,GFP_KERNEL);
if(tmp == NULL){
printk("malloc failed!\n");
return -ENOMEM;
goto err0;
}
ret = copy_from_user(tmp,buf,size);
if(ret){
printk("copy data failed!\n");
ret =-EFAULT;
goto err0;
}
ret = i2c_write_byte(tmp,size);
if(ret<0){
printk("write byte failed!\n");
ret = -EINVAL;
goto err0;
}
kfree(tmp);
return size;
err0:
kfree(tmp);
return ret;
}
struct file_operations e2prom_fops = {
.owner =THIS_MODULE,
.open =e2prom_open,
.read =e2prom_read,
.write =e2prom_write,
};
static int e2prom_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int ret;
printk("enter probe!\n");
e2prom_dev = kmalloc(sizeof(struct e2prom_device),GFP_KERNEL);
if(e2prom_dev == NULL){
printk("malloc failed\n");
return -ENOMEM;
}
e2prom_dev->at24c02_client = client;
/*给用户提供接口*/
ret = register_chrdev(E2PROM_MAJOR,"e2prom_module",&e2prom_fops);
if(ret < 0)
{
printk("register major failded\n");
ret =-EINVAL;
goto err0;
}
/*创建设备类*/
e2prom_dev->at24c02_class = class_create(THIS_MODULE,"e2prom_class");
if(IS_ERR(e2prom_dev->at24c02_class)){
printk("class create failed\n");
ret =PTR_ERR(e2prom_dev->at24c02_client);
goto err1;
}
/*创建设备文件*/
e2prom_dev->at24c02_device=device_create(e2prom_dev->at24c02_class,NULL,MKDEV(E2PROM_MAJOR,0),NULL,"at24c08");
if(IS_ERR(e2prom_dev->at24c02_device)){
printk("class create failed\n");
ret =PTR_ERR(e2prom_dev->at24c02_device);
goto err1;
}
return 0;
err1:
unregister_chrdev(E2PROM_MAJOR,"e2prom_module");
err0:
kfree(e2prom_dev);
return ret;
}
static int e2prom_remove(struct i2c_client *client)
{
unregister_chrdev(E2PROM_MAJOR,"e2prom_module");
device_destroy(e2prom_dev->at24c02_class, MKDEV(E2PROM_MAJOR,0));
class_destroy(e2prom_dev->at24c02_class);
kfree(e2prom_dev);
return 0;
}
/*构建一个struct i2c_driver结构体*/
static struct i2c_driver e2prom_driver={
.probe =e2prom_probe,
.remove =e2prom_remove,
.id_table =e2prom_table,//记录此驱动服务于哪些设备
.driver ={
.name ="e2prom",//
},
};
static int __init e2prom_init(void)
{
/*注册平台特定驱动
*1)将i2c驱动加入i2c总线的驱动链表
*2)搜索i2c总线的设备链表,每搜索一个都会调用i2c总线的match
* 实现client->name与id->name进行匹配,匹配成功就会调用
* i2c驱动中的probe函数
*/
i2c_add_driver(&e2prom_driver);
return 0;
}
static void __exit e2prom_exit(void)
{
i2c_del_driver(&e2prom_driver);
}
module_init(e2prom_init);
module_exit(e2prom_exit);
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
/*
./i2c_test w data
./i2c_test r
*/
int main(int argc,char **argv)
{
int fd;
char register_addr = 0x78;//要写入的地址
char wbuf[2];//写缓冲区
char rbuf[2];//读缓冲区
//打开设备
fd = open("/dev/at24c08", O_RDWR);
if (fd < 0)
{
perror("open error\n");
exit(1);
}
if(strcmp(argv[1],"w") == 0)
{//写操作
Byte Writewbuf[0] = register_addr;
wbuf[1] = atoi(argv[2]);
/向
register_addr地址中写入数据,因为设备地址已经在板级信息中确定了,所以不需要通过ioctl设置设备地址*/if(res = write(fd, wbuf, 2) != 2)
{
perror("write error\n");
exit(1);
}
- }
else
{
//读操作 Random Readif(write(fd, ®ister_addr, 1) != 1) //
验证是否从
register_addr地址读出{
perror("write error\n");
exit(1);
}
if(read(fd, &rbuf, 1) != 1)
{
perror("read error\n");
exit(1);
}
else
{
printf("rbuf[0] = %d\n",rbuf[0]);
}
- }
return 0;
}
at24c08 E2PROM的I2C设备驱动实例——基于mini2440相关推荐
- i2c设备驱动实例 ds1307为例
i2c设备驱动实例 ds1307为例 http://blog.csdn.net/airk000/article/details/21345457 http://blog.csdn.net/creazy ...
- Linux 设备驱动篇之I2c设备驱动
******************************************************************************************** 装载声明:希望 ...
- Linux设备驱动篇——[I2C设备驱动-1]
Linux 设备驱动篇之I2c设备驱动 fulinux 一.I2C驱动体系 虽然I2C硬件体系结构和协议都很容易理解,但是Linux I2C驱动体系结构却有相当的复杂度,它主要由3部分组成,即I2C设 ...
- 手把手教你写Linux I2C设备驱动
手把手教你写Linux I2C设备驱动 标签:Linux 设备 驱动 详解 i2c 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http:/ ...
- linux探测i2c设备连接状态,手把手教你写Linux I2C设备驱动
Linux I2C驱动是嵌入式Linux驱动开发人员经常需要编写的一种驱动,因为凡是系统中使用到的I2C设备,几乎都需要编写相应的I2C驱动去配置和控制它,例如 RTC实时时钟芯片.音视频采集芯片.音 ...
- linux i2c detect函数,手把手教你写Linux I2C设备驱动
Linux I2C驱动是嵌入式Linux驱动开发人员经常需要编写的一种驱动,因为凡是系统中使用到的I2C设备,几乎都需要编写相应的I2C驱动去配置和控制它,例如 RTC实时时钟芯片.音视频采集芯片.音 ...
- Linux添加一个i2c设备,手把手教你写Linux I2C设备驱动
Linux I2C驱动是嵌入式Linux驱动开发人员经常需要编写的一种驱动,因为凡是系统中使用到的I2C设备,几乎都需要编写相应的I2C驱动去配置和控制它,例如 RTC实时时钟芯片.音视频采集芯片.音 ...
- 用户空间访问I2C设备驱动
2012-01-11 15:33:43 标签:Linux I2C 字符设备 设备驱动 用户空间 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任. ...
- RT-Thread I2C设备驱动框架的对接使用
I2C和SPI是MCU和板载芯片之间最常用的通讯方式,现在先介绍下I2C总线.I2C的基本原理也很简单,只需要两根线(时钟线SCL和信号线SDA)即可实现挂载在I2C总线上设备之间的相互通讯.I2C协 ...
- 使用RT-Thread Studio DIY 迷你桌面时钟(二)| 获取温湿度传感器数据(I2C设备驱动+SHT3x软件包)
寻求更清爽的阅读体验,请移步:Mculover666的个人博客. 1. 项目进度 桌面Mini时钟项目用来演示如何使用RT-Thread Stduio开发项目,整个项目的架构如下: 在上一篇博文中简单 ...
最新文章
- Flutter开发之MVC设计模式:新建文件与导入文件(八)
- 子域名/目录暴力工具Gobuster
- 安利一个我爱不释手的PDF神器网站
- 关于android开发环境的创建
- 使用脚本动态操作 SVG 文档
- python输出个数、给定一个n*n的矩阵m_简述Numpy
- ansys中模态扩展是什么意思_ANSYS模态分析教程与实例讲解.ppt
- H5动画实现简单的转盘抽奖。
- 通配符(一般用来查找文件)
- 浏览器获取服务器CA证书与认证流程-HTTPS
- 复盘 2019 ,展望 2020
- 手机扫描答题卡阅卷的小程序
- 老挑毛u盘一键装系统计算机意外地,揭谜一键Ghost的“恶”事 大白菜、老毛桃、通用都不干净...
- 关于SMTP邮件无法发送到 SMTP服务器,传输错误代码为 0x80040217
- [BugKu Web]ez_serialize
- 美国人怎么看 2020 年的产业数字化|趋势
- 世界互联网大会“互联网之光”博览会-蚂蚁金服展台掠影
- 期货价格怎么算出来的?
- valgrind 工具使用
- 携程3+2工作模式,极大刺激着领导们的安全感