/*
*该驱动为new style方式
*驱动安装后,输入命令创建设备节点:mknod /dev/at24c08 c 250 1
*需在内核中的mach-mini2440.c中添加板级信息注册这个i2c设备,
*且注册的设备名必须和本文件中id_table的设备名一致;
在mach-mini2440.c中添加如下代码,并重新编译内核
0x50为at24c08设备的地址,"at24c08"为在板级信息中添加的i2c设备的名称;
static struct i2c_board_info i2c_devices[] __initdata = { { I2C_BOARD_INFO("at24c08", 0x50), },
};
static void __init mini2440_machine_init(void)
{  i2c_register_board_info(0,i2c_devices,ARRAY_SIZE(i2c_devices)); //在函数中新加的注册信息s3c24xx_fb_set_platdata(&mini2440_fb_info); s3c_i2c0_set_platdata(NULL); s3c_device_nand.dev.platform_data = &mini2440_nand_info; //添加 platform_add_devices(mini2440_devices, ARRAY_SIZE(mini2440_devices)); //smdk_machine_init();
}
*/#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/delay.h>
#include <linux/fs.h>
#include <asm/uaccess.h>#define AT24C08_MAJOR 250   //主设备号不能为89,为什么?
static int at24c08_major = AT24C08_MAJOR;
/**自定义的设备数据结构**/
struct at24c08_dev
{struct i2c_client *client;char name[30];unsigned short current_pointer;struct cdev cdev;
};
struct at24c08_dev *at24c08_devp;static int at24c08_open(struct inode *inode, struct file *file)
{ file->private_data = at24c08_devp; return 0;
} static ssize_t at24c08_read(struct file *file, char *buf, size_t count, loff_t *ppos)
{ int i = 0; int transferred = 0; int ret, my_buf[512]; struct at24c08_dev *dev = (struct at24c08_dev *)file->private_data; dev->current_pointer = *ppos; if  (i2c_check_functionality(dev->client->adapter,
I2C_FUNC_SMBUS_READ_BYTE_DATA)) { while (transferred < count){ ret = i2c_smbus_read_byte_data(dev->client,dev->current_pointer + i ); my_buf[i++] = (unsigned short)ret; transferred += 1; } copy_to_user(buf, (void *)my_buf, transferred); dev->current_pointer += transferred; }
return transferred;
} static ssize_t at24c08_write(struct file *file, char *buf, size_t count, loff_t *ppos)
{ int i = 0; int transferred = 0; int ret, my_buf[512]; struct at24c08_dev *dev = (struct at24c08_dev *)file->private_data; dev->current_pointer = *ppos; if (i2c_check_functionality(dev->client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { //判断适配器能力copy_from_user(my_buf, buf, count);  while (transferred < count){ ret = i2c_smbus_write_byte_data(dev->client,dev->current_pointer + i,my_buf[i]); //i2c_smbus_write_byte_data是从设备指定偏移处写入一个字节i += 1; transferred += 1; } dev->current_pointer += transferred; }
return transferred;
} static int at24c08_ioctl(struct inode *inodep, struct file *file, unsigned int cmd, unsigned long
arg)
{ return 0;
} static int at24c08_release(struct inode *inodep, struct file *file)
{ file->private_data = NULL; return 0;
}static const struct file_operations at24c08_fops = { .owner    = THIS_MODULE, .open    = at24c08_open, .read  = at24c08_read, .write    = at24c08_write, .ioctl    = at24c08_ioctl, .release = at24c08_release,
}; static void at24c08_setup_cdev(struct at24c08_dev *dev, int index)
{int err;dev_t devnum=MKDEV(at24c08_major,index);  //index=1;cdev_init(&dev->cdev,&at24c08_fops);dev->cdev.owner = THIS_MODULE;err=cdev_add(&dev->cdev,devnum,1);if (err) printk(KERN_NOTICE"Error %d adding at24c08b %d", err, index);}static int __devinit at24c08_probe(struct i2c_client *client,struct i2c_device_id *id)
{printk(KERN_INFO"start at24c08 probe\n");int ret;dev_t devnum=MKDEV(at24c08_major,1);if(at24c08_major) ret = register_chrdev_region(devnum, 1, "at24c08"); //执行probe后才注册设备else { ret = alloc_chrdev_region(&devnum, 0, 1, "at24c08"); at24c08_major = MAJOR(devnum); }if (ret < 0) return ret; at24c08_devp = kmalloc(sizeof(struct at24c08_dev), GFP_KERNEL); if (!at24c08_devp){ ret = -ENOMEM; goto fail_malloc; } memset(at24c08_devp, 0, sizeof(struct at24c08_dev)); at24c08_devp->client=client;at24c08_setup_cdev(at24c08_devp,1);//前面注册设备后需添加设置设备return 0; fail_malloc: unregister_chrdev_region(devnum, 1); return ret;}
static const struct i2c_device_id at24c08_id[]=
{
{"at24c08",0},  //该名称必须与板级信息中的名称一致才会调用Probe函数
{}
};
static struct i2c_driver at24c08_driver=
{.driver={.name="at24c08",.owner=THIS_MODULE;},.probe=at24c08_probe,.remove=__devexit_p(at24c08_remove),.id_table=at24c08_id,
};
static int __init at24c08_init()
{printk(KERN_INFO"Init the module success\n");return i2c_add_driver(&at24c08_driver); //初始化中添加i2c设备驱动,在执行probe后才注册
}
static void at24c08_exit()
{printk(KERN_INFO"exit the module success\n");return i2c_del_driver(&at24c08_driver);
}module_param(at24c08_major, int, S_IRUGO);
MODULE_AUTHOR("Xie");module_init(at24c08_init);
module_exit(at24c08_exit);
/*
*测试程序如下:
*交叉编译后在mini2440开发板上运行。
*交叉编译命令为arm-linux-gcc -static i2c-app.c -o 24c08-app3
*经测试,当输入的参数为4个以下时只能读到一个数,5~8个时读到2个数,9~12个时读到3个数;
*输入参数形式为:  ./程序名 数值1 数值2 数值3 ...;数值为写入设备的十六进制值
*
*/
#include <stdio.h>
#include <linux/types.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h> int main(int argc, char **argv)
{ int i,j; unsigned int value[100]; int fd;     fd = open("/dev/at24c08", O_RDWR);   //打开设备if(fd < 0) { printf("Open at24c08b Device Faild!\n"); exit(1); }
printf("you has input %d parament\n",argc);
j=argc-1;
for(i=0;i<j;i++){ sscanf(argv[i+1],"%x",&value[i]);    //将输入的数作为值存入value数组中printf("value[%d]=%x\n",i,value[i]);}write(fd, value, j);                 //将value数组的值写入设备for(i = 0; i < j; i++)  printf("write reg[%d] data: %x to at24c08\n", i, value[i]);  printf("#########################################\n"); sleep(1); for(i=0;i<j;i++)value[i]=0;                  //清0read(fd, value, j);                 //从设备中读入j个字节的值到数组for(i = 0; i < j; i++)  printf("read reg[%d] data: %x to at24c08\n", i, value[i]);  close(fd);  return 0;
} 
/*
当只写入一个数值时,能正确读出来:

当写入2个数值时,只读出来一个,不知道什么原因。
./24c08-app3 0x24 0x30
*/

i2c驱动之at24c08(1)相关推荐

  1. i2c驱动之i2c-dev驱动

    i2c的设备驱动可以直接利用内核提供的i2c-dev.c文件提供的ioctl函数接口在应用层实现对i2c设备的读写,但是在应用层使用ioctl函数对应用程序员要求较高,需要自行构建msg结构体,必须了 ...

  2. STC8H开发(十三): I2C驱动DS3231高精度实时时钟芯片

    目录 STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解) STC8H开发(二): 在Linux VSCode中配置和使用FwLib_STC8封装库(图文详解) ST ...

  3. linux i2c核心,总线与设备驱动,Linux2.6.37 I2C驱动框架分析(一)

    最近工作中又使用到了I2C,所以借S3C2440开发板GT2440为硬件平台温习一遍I2C驱动体系. linux内核中IIC驱动的体系框架 linux内核中IIC部分驱动代码位于:/drivers/i ...

  4. linux驱动:i2c驱动(四)流程图之注册驱动

    二.i2c设备的驱动部分 1.i2c驱动i2c_driver 2.通过i2c_add_driver注册 2.注册过程中 比较i2c_device_id数组中各成员的id与i2c_client中的名字, ...

  5. linux驱动:i2c驱动(二)

    3.驱动源码分析 IPNC_RDK_V3.8.0.1/Source/ti_tools/ipnc_psp_arago/kernel/sound/soc/codecs/tlv320aic3x.c 3.1 ...

  6. linux驱动:i2c驱动(一)

    I2C系统框架:I2C核心层.I2C总线驱动.I2C设备驱动 --------------------------------------------------------------------- ...

  7. 设备树与驱动的关系_Linux I2C驱动竟然如此简单?手把手教你写i2c驱动

    Linux中I2C驱动框架分析 I2C核心(i2c_core) I2C核心维护了i2c_bus结构体,提供了I2C总线驱动和设备驱动的注册.注销方法,维护了I2C总线的驱动.设备链表,实现了设备.驱动 ...

  8. 基于WinCE的I2C驱动程序设计

    http://www.mcu123.com/news/Article/rtos/WinCE/200607/88.html 引言 随着以计算机技术.通信技术和软件技术为核心的信息技术的迅速发展,嵌入式系 ...

  9. 【驱动】linux下I2C驱动架构全面分析

    I2C 概述 I2C是philips提出的外设总线. I2C只有两条线,一条串行数据线:SDA,一条是时钟线SCL ,使用SCL,SDA这两根信号线就实现了设备之间的数据交互,它方便了工程师的布线. ...

  10. Zynq linux的I2C驱动学习笔记

    最近在用米尔的Z-TURN BOARD单板做小项目.顺便也加强学习I2C驱动,记一篇做记录.  I2C总线知识非常简单,SDA,SCL,他们的时序规则是:I2C总线是由数据线SDA和时钟SCL构成的串 ...

最新文章

  1. 聚合函数的计算机控件,使用Kendo UI MVC Grid包装器的聚合函数
  2. 中专学校的计算机教什么,中专计算机学校
  3. 格“物”致知:多模态预训练再次入门
  4. 数据库事务的概念及其实现原理
  5. 用jar 命令打包war包
  6. 五周第二次课(4月19日)
  7. 一文带你看懂物联网开源操作系统
  8. 注解之RetentionPolicy,ElementType
  9. dpkg: 依赖关系问题使得 linux-headers-5.7.19-050719-generic 的配置工作不能继续
  10. flash作业_在线作业产品的基本构成与逻辑分解
  11. Redis 不安全临时文件漏洞
  12. 七月算法机器学习5 回归分析与工程应用 小案例
  13. asp版的简单留言板
  14. jlink 与 swd 接口定义
  15. linux 迅雷 命令行,Linux小迅雷:uGet下载工具加速 | 薄荷开源网
  16. 醒了自悟系列--千年老妖---1000后的重生---重新脚踏实地
  17. Minimum supported Gradle version is 6.1.1. Current version is 5.6.4.
  18. 带你深度解析断点续传原理并案例Http1.1协议
  19. free源码分析---1
  20. 今日恐慌与贪婪指数为25 等级转为极度恐慌

热门文章

  1. 智能水电表远程管理系统
  2. python nlpir_中文分词工具--NLPIR/ICTCLAS的Python版本使用
  3. AI智能电子名片开发
  4. 希捷硬盘固件修复工具_希捷3.5寸500G台式机硬盘磁头损坏后的数据恢复
  5. matlab ocx控件,matlabr.ocx控件下载
  6. 高薪设计师必修课 AE移动UI动效设计从入门到实战
  7. ArcGIS批量使用以表格显示分区统计工具
  8. 趋肤效应实验报告_GB/T 4857.2
  9. java+ selenium截图
  10. web批量打印pdf