1、嵌入式计算机系统课程设计报告上海电力学院课程设计报告设计题目:基于ARM和Linux的I2C总线读写程序设计与实现专业: 自动化工程学院 班级: 000000姓名: 11111111学号: 111111111. 课题研究意义、国内外研究现状及应用分析:(1)掌握 I2C 总线控制器驱动程序的使用方法; (2)掌握使用 I2C 总线控制器驱动程序访问 CAT1025 的方法。(3)使用 I2C 总线控制器驱动程序编写应用程序,往 CAT1025 内部写入 16 个字节,然后读回并进行校验。 I2C(inter-integrated-circuit)总线,是由菲利普公司开发的一种同步串行总线协议,
2、用于连接微控制器及其外围设备,最初是为音频和视频设备开发的。如今I2C在各种电子设备中得到了广泛的应用。嵌入式系统中常常使用这个总线连接RAM,EEPROM以及LCD控制器等设备。I2C总线因协议成熟,引脚简单,传输速率高,支持的芯片多,并且有利于实现电路的标准化和模块化,得到了包括Linux在内的很多操作系统的支持,受到开发者的青睐。Linux内核中针对I2C的总线特性,其设备驱动使用了一种特殊的体系结构,开发I2C总线设备驱动程序就必须理解Linux的I2C总线驱动的体系结构。2. 课题总体方案设计及功能模块介绍:在嵌入式ARM平台及Linux环境下,掌握I2C总线控制器驱动程序的使用方法
3、,掌握使用I2C总线控制器驱动程序访问CAT1025的方法,向CAT1025内部写入多个字节,然后读回并进行校验。功能模块:CAT1025JI-30,E2PROM, I2C 总线(1) CAT1025JI-30 为了提高整个系统的可靠性,复位电路采用了带手动复位的电源监控复位芯片CAT1025JI-30。CAT1025JI-30 内置有 256 字节的 E2PROM 存储器,I2C 总线接口。工作频率高达 203MHz所以使用了 S3C2410A芯片的 I2C 总线接口与其连接,电路原理如图 1.12 所示。 图 1.12如图 1.12 所示,I2C 总线上拉电阻 R8、R9 的大小为 4.7
4、K。CAT1025JI-30 的器件地址为 0xA0, 如果用户板(即底板)上需要使用地址为 0xA0 的 I2C器件, 或者需要将 I2CSDA、I2CSCL 用作 GPIO,则可以将电阻 R19、R20 拆除(图 1.12 中的虚线框部分)。 说明:DeviceARM2410 默认配置时,R19、R20 是焊接的。CAT1025 内部包含256字节的读写空间,通过 USB 总线读/写 CAT1025 时,包括下两项操作: (1)读 CAT1025:PC 通过 USB 总线发送读命令(1 字节) ,S3C2410A从CAT1025 读取 256 字节,通过 USB 总线发回 PC。 (2)写
5、 CAT1025:PC 通过 USB 总线发送 257字节(其中包括1字节的写命令及 256字节的数据),S3C2410A 将 256 字节的数据写入CAT1025。写入成功后,将成功写入的字节数(2 字节)通过 USB 总线发回 PC。 可见,读 CAT1025 时,PC 发送 1 字节,但 S3C2410A返回 256 字节。 写 CAT1025 时,PC 发送 257 字节,但 S3C2410A返回 2 个字节。 为了编程方便起见,规定:PC 与 S3C2410A通过 USB 总线通信时,一帧的长度为 259字节,一个帧的定义如下:写 CAT1025 的过程与读 CAT1025 的过程类
6、似。写 CAT1025 的过程如图 6.4 所示。PC 作为主动方,MagicARM2410 作为被动方。(1) PC 发送一个写命令帧,命令为:写命令(1 字节) ,数据长度字段:值为 256,数据字段为:要写入 CAT1025 的 256 个字节。 (2) MagicARM2410 使用 USB 设备控制器驱动程序的读端点函数接收到写命令帧,就使用 I2C 总线控制器驱动程序提供的 API 函数将 256 字节写入 CAT1025。 (3) MagicARM2410 使用 USB 设备控制器驱动程序的写端点函数,发送响应帧到PC。响应帧的数据长度字段为:成功写入字节数,数据字段则为无效。
7、(4)PC 收到响应帧, 根据响应帧中成功写入字节数, 就可判断写 CAT1025 是否成功。至此,写 CAT1025 操作完成。(2) E2PROM 存储器电路 :EEPROM (Electrically Erasable Programmable Read-Only Memory),电可擦可编程只读存储器-一种掉电后数据不丢失的存储芯片。 EEPROM 可以在电脑上或专用设备上擦除已有信息,重新编程。一般用在即插即用。(3) I2C 总线控制器:I2C总线是器件间串行传输总线,以其规范和带I2C接口的外围器件获得广泛应用。S3C2410处理器内置有I2C总线接口。I2C总线是由数据线SDA
8、和时钟SCL构成的串行总线,可发送和接收数据,每个器件都有一个唯一的地址识别。I2C总线在传送数据过程中共有3种信号:(1)开始信号:SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据。(2)结束信号:SCL为低电平时,SDA由低电平向高电平跳变,结束传送数据。(3)应答信号:接收数据的IC接收到8 bit数据后,向发送数据的IC发出特定的低电平脉冲,表示已收到数据。CPU向受控单元发出一个信号后,等待受控单元发出应答信号,CPU接收到应答信号后,根据实际情况做出是否继续传递信号的判断。若未收到应答信号,则判断为受控单元出现故障。图1为S3C2410和ZLG7290的连接图。(a)驱动
9、模块的结构:S3C2410A 微控制器内嵌了一个 I2C 总线控制器。在 Linux 操作系统中,该控制器的字符型驱动包括以下四个模块,它们对应的源程序及简介如表 6.1 所示。当需要使用 I2C 总线控制器驱动模块时,可以使用 I2C 总线控制器驱动的设备管理文件loadi2c,其内容如程序清单6.1所示。本管理文件运行后,将自动在 Linux 的/dev/目录下创建设备节点 i2c。I2C 总线控制器驱动 (字符型) 提供的 API 函数除了 read()与 write()以外, 还提供了 ioctl()函数用于设定 I2C 总线控制器的一些参数,该函数常用的命令列表如表 6.2 所示,该
10、函数可以使用的全部命令请见驱动源码中的 i2c.h 文件的具体说明。可利用ioct1函数操纵虚终端设备文件,实现与Unix系统内核的交互,得到我们所需要的服务。使用ioct1的具体形式如下: int ioct1(int filedes,int request,/参数/) 其中filedes为打开的虚终端设备文件描述符,request为请求的服务,随后的参数可为各种数据类型,视具体情况而定。(b)驱动源文件的编译:驱动源文件包括i2c-algo-s3c2410c,i2c-devc,i2c-corec,i2c-s3c2410c4个源文件。将其编译为模块,则产生4个模块文件,编译工作由Makefil
11、e文件完成,其文件内容如图1所示:当需要使用I2C总线控制器驱动模块时,可以使用I2C总线控制器驱动的设备管理文件loadi2c。该管理文件运行后,将自动在Linux的dev目录下创建设备节点i2c,如图2所示: 图1 图23系统硬件平台及接口设计; 硬件: PC 机 一台 MagicARM2410 教学实验开发平台 一套 嵌入式系统调试模型4 . 系统软件功能设计,程序流程图及代码实现: 软件功能设计步骤:(1) 在 PC 端,打开终端或者进入虚拟控制台,进入 arm实验目录/zylinux/armwork/,为本实验新建工作目录 cat1025。 $ cd /zylinux/armwork
12、 $ mkdir cat1025 (2) 使用vi在cat1025文件中建立文件 cat1025.c,编写实验代码并保存。(退出时按Esc+:+wq) $ vi cat1025.c (3) 修改 Makefile使其适合于本实验。 EXEC = cat1025 OBJS = cat1025.o SRC = cat1025.c (4) 编译程序,生成可执行代码 cat1025。 $ make 或者跳过第三第四部直接arm-linux-gcc cat1025.c o cat1025.o(5)启动 ARM Linux。将实验箱串口 0 和 PC 主机串口相连,同时将网线插入实验箱网卡,将实验箱接入以
13、太网。在 PC 端打开 minicom 或者超级终端,并进行正确设置(6) 进行NFS连接, 将主机NFS共享目录的/zylinux/armwork目录mount到ARM Linux的/mnt 目录下。 # mount t nfs 192.168.0.94:/zylinux/armwork /mnt o nolock (7)进入 I2C总线控制器驱动程序所在目录,先加载 I2C 驱动,然后进入 cat1025 目录,运行程序,查看运行结果。 #./loadi2c# ./cat1025 程序代码:#include #include #include /* 文件操作 */ #include i2c
14、.h /* I2C总线控制器驱动命令 */ #define I2C_ADDR 0xA0 /* CAT1025从机地址 */ int main() int fd,ret,i; unsigned char suba; char buf9 = 0,1,2,3,4,5,6,7,8; fd = open(/dev/i2c/0, O_RDWR); /* 打开设备 */ if(fd = -1) printf(Cant open I2C device!n); exit(-1); ret = ioctl(fd, I2C_TENBIT, 0); /* 指定从机地址为7bit */ if (ret != 0) pr
15、intf(Cant set I2C address bit number.n); close(fd); exit(-1); ret = ioctl(fd, I2C_SLAVE, I2C_ADDR 1); /* 设置从机地址,7位地址,须右移1位*/ if (ret != 0) printf(Cant set I2C slave device address.n); close(fd); exit(-1); printf(Write CAT1025:n); for(i = 1; i 9; i+) printf(%d , bufi); ret = write(fd, buf, 9); /* 写8个
16、字节到CAT1025,第1字节为子地址*/ if (ret != 9) printf(Write CAT1025 failed.n); close(fd); exit(-1); usleep(10000); /* 等待10ms写入完成确保数据完全写入 CAT1025,也保证CAT1025 退出“忙”状态 */ printf(nRead CAT1025:n); suba = 0; ret = write(fd, &suba, 1); /* 发送从机子地址,读 CAT1025 时,必须先用“写”操作来设定从机子地址,然后才能执行读操作 */ if (ret != 1) printf(send sl
17、ave address fail.n); close(fd); exit(-1); ret = read(fd, buf, 8); /* 从CAT1025读8个字节 */ if (ret = 8) for (i = 0; i 8; i+) printf(%d , bufi); else printf(Read CAT1025 failed.n); close(fd); exit(-1); printf(nRead and Write CAT1025 sucessfully!n); return 0; 说明:“$”开始的命令为在 PC 主机输入的命令; “#”开始的命令为在实验箱端输入的命令。除
18、非特殊说明,下同。(1) EXEC:最终生成的可执行文件,需要根据应用进行修改; (2) OBJS: 生成的目标文件,需要根据应用进行修改(必须和源文件同名,不包括后缀) ; (3) SRC:源文件,需要根据应用进行修改。 (4) CC:指定了编译器为交叉编译器 arm-linux-gcc;5 . 实验测试、结果分析:1)当buf9 = 0,1,2,3,4,5,6,7,8源程序运行后在终端打印出实验结果:Write CAT1025: 1 2 3 4 5 6 7 8 Read CAT1025: 1 2 3 4 5 6 7 8 Read and Write CAT1025 sucessfully!
19、2)当buf17 = 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16时在终端打印出实验结果:Write CAT1025: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16Read CAT1025: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16Read and Write CAT1025 sucessfully!3)当buf21 = 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20运行后在终端打印出实验结果:Write CAT1025: 1 2 3
20、 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20Read CAT1025: 17 18 19 20 5 6 7 8 9 10 11 12 13 14 15 16 255 255 255 255Read and Write CAT1025 sucessfully!结果分析:如果写入 CAT1025 的数据大于 16 字节,则写正常读不正常,这是因为每次写CAT1025只能写一页 (16字节)这跟EEPROM的页写问题有关,即那应该如何编写程序实现呢?以下函数根据要求写入的字节数来决定写多少页以及写不够一页的数据。主函数6 . 总结、心得体会:通过对EEP
21、ROM,i2c以及linux的研究总结了一下几点:(1)读没有页的问题,可以从任意地址开始读取任意大小数据,只是超过整个存储器容量时地址才回卷。但一次性访问的数据长度也不要太大。AT24CXX系列的EEPROM为了提高写效率,提供了页写功能,内部有个一页大小的写缓冲RAM,页RAM的地址范围为7位007F,写入时高端地址就是页号。发生写操作,开始送入的地址对应的页被锁存,后续不论写多少,都在这个页中,只是一个页内的地址进行加一,超过就归零开始。从F0开始写32个字节,那么开始送入的地址为F0,就会锁定在1号页(第2个页)上,底端7位页内部地址开始从70H开始写,到达7F时回到00再到10H,也
22、就是写在了F0FF,808F。也就是,从01开始写也只能到7F,再往80写就跑到00上去了,这就是写操作的翻卷,datasheet上都有说明。就是从边界前写两个字节也要分两次写。页是绝对的,按整页大小排列,不是从开始写入的地址开始算。(2)由于各模块间有上下层关系,则加载模块顺序应是从上到下,最先加载i2c-core,最后加载i2c-s3c2410。而卸载则顺序相反。加载模块i2c-algo-s3c2410时,必须延时1 s以等待该模块初始化完成,否则无法加载下一个模块i2c-s3c2410。(3)当主机系统(运行编译器的系统)和目标系统(产生的程序将在其上运行的系统)不兼容时,该过程就叫做交叉编译。在宿主机上交叉编译得到可执行文件,通过调试器下载到目标系统中调试运行。刚开始时我就抱怨为什么老师总是说自己想,自己找原因,问题自己解决呢?后来终于明白了,老师也是为了我们好,如今的学生依赖性很强,独立思考能力差。这次真得感谢小飞飞老师O(_)O。7 . 附主要的参考文献 :
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1