controller控制器怎么写_I2C控制器编程_框架

73775dc8e1a34fec912267a3cdfdf99f.png

来源:百问网_嵌入式Linux wiki_jz2440 新1期视频维基教程 (视频文字版)

作者:韦东山

本文字数:3776,阅读时长:5分钟

我们现在来讲I2C控制器怎么写,它是I2C程序中最核心的地方,我们要先构造几个结构体,这几个结构体放在i2c_controller.h里面。

我们要发出I2c传输时,要构造出i2c_msg,把构造出的i2c_msg扔给下面的i2c_controller.c,i2c_controller.c会选择某一个i2c控制器,使用里面的master_xfer来传输数据, 所以我们需要构造出一个i2c_controller结构体。

i2c_controller.h文件

文件的内容如下所示:

#ifndef _I2C_CONTROLLER_H#define _I2C_CONTROLLER_Htypedef struct i2c_msg {unsigned int addr;  /* 7bits */int flags;  /* 0 - write, 1 - read */int len;int cnt_transferred;unsigned char *buf;}i2c_msg, *p_i2c_msg;typedef struct i2c_controller {int (*int)(void);int (*master_xfer)(i2c_msg msgs, int num);char *name;}i2c_controller, *p_i2c_controller;#endif /* _I2C_CONTROLLER_H */

解析:我们构造这两个结构体,我们要把它放在i2c_controller.c把它用起来,

i2c_controller.c文件

文件的内容如下所示:

include "i2c_controller.h"#define I2C_CONTROLLER_NUM 10/* 有一个i2c_controller数组用来存放各种不同芯片的操作结构体 */static p_i2c_controller p_i2c_controllers[I2C_CONTROLLER_NUM];static p_i2c_controller p_i2c_con_selected;void register_i2c_controller(p_i2c_controller *p){int i;for (i = 0; i < I2C_CONTROLLER_NUM; i++){if (!p_i2c_controllers[i]){p_i2c_controllers[i] = p;return;}}}

解析:register_i2c_controller函数用于把参数中的结构体指针,注册到p_i2c_controllers指针数组中。

/* 根据名字来选择某款I2C控制器 */int select_i2c_controller(char *name){int i;for (i = 0; i < I2C_CONTROLLER_NUM; i++){if (p_i2c_controllers[i] && !strcmp(name, p_i2c_controllers[i]->name)){p_i2c_con_selected = p_i2c_controllers[i];return 0;}}return -1;}

解析:select_i2c_controller函数根据参数中的名字(name) 从p_i2c_controllers指针数组中取出对应的结构体指针复制给p_i2c_con_selected结构体指针(静态全局变量)。

/* 实现 i2c_transfer 接口函数 */int i2c_transfer(i2c_msg msgs, int num){return p_i2c_con_selected->master_xfer(msgs, num);}

解析:i2c_transfer接口函数,调用选择的p_i2c_con_selected成员中master_xfer函数。

void i2c_init(void){/* 注册下面的I2C控制器 */s3c2440_i2c_con_add();/* 选择某款I2C控制器 *//* 调用它的init函数 */}

解析:s3c2440_i2c_con_add()函数,把定义的s3c2440_i2c_con结构体注册到p_i2c_controllers数组中。

s3c2440_i2c_controller.c文件

中断服务函数,当发成中断时,就会调用中断服务函数,代码如下

void i2c_interrupt_func(int irq){/* 每传输完一个数据将产生一个中断 *//* 对于每次传输, 第1个中断是"已经发出了设备地址" */}

s3c2440_i2c_con_init函数,用来初始化I2C,控制器代码如下:

void s3c2440_i2c_con_init(void){/* 设置时钟 *//* [7] : IIC-bus acknowledge enable bit, 1-enable in rx mode * [6] : 时钟源, 0: IICCLK = fPCLK /16; 1: IICCLK = fPCLK /512 * [5] : 1-enable interrupt * [4] : 读出为1时表示中断发生了, 写入0来清除并恢复I2C操作 * [3:0] : Tx clock = IICCLK/(IICCON[3:0]+1). * Tx Clock = 100khz = 50Mhz/16/(IICCON[3:0]+1) */IICCON = (0<<6) | (1<<5) | (30<<0);/* 注册中断处理函数 */register_irq(27, i2c_interrupt_func);}

解析:

1).IICCON = (0<<6) | (1<<5) | (30<<0); 设置IICCON控制寄存器。选择发送时钟,使能中断。

2).register_irq(27, i2c_interrupt_func):注册中断处理函数,当发生I2C中断的时候就会调用i2c_interrupt_func中断处理函数。

初始化完成后,就可以调用do_master_tx写I2C从机了,这个函数仅仅启动I2C传输,然后等待,直到数据在中断服务程序中传输完毕后再返回。函数代码如下:

void do_master_tx(p_i2c_msg msg){msg->cnt_transferred = 0;/* 设置寄存器启动传输 *//* 1. 配置为 master tx mode *//* 2. 把从设备地址写入IICDS */IICDS = msg->addr<<1;/* 3. IICSTAT = 0xf0 , 数据即被发送出去, 将导致中断产生 */IICSTAT = 0xf0;/* 后续的传输由中断驱动 *//* 循环等待中断处理完毕 */while (msg->cnt_transferred != msg->len);}

解析:

1).IICDS = msg->addr<<1: 把从机地址(高7位,所以需要向右移一位)写入到IICDS寄存器中。

2).IICSTAT = 0xf0:设置IICSTAT寄存器,将s3c2440设为主机发送器,并发出S信号后,紧接着就发出从机地址。后续的传输工作将在中断服务程序中完成。

do_master_rx函数的实现和do_master_tx函数类似,代码如下:

void do_master_rx(p_i2c_msg msg){msg->cnt_transferred = 0;/* 设置寄存器启动传输 *//* 1. 配置为 Master Rx mode *//* 2. 把从设备地址写入IICDS */IICDS = (msg->addr<<1)|(1<<0);/* 3. IICSTAT = 0xb0 , 从设备地址即被发送出去, 将导致中断产生 */IICSTAT = 0xb0;/* 后续的传输由中断驱动 *//* 循环等待中断处理完毕 */while (msg->cnt_transferred != msg->len);}

解析: 1).IICDS = (msg->addr<<1)|(1<<0):把从设备地址写入IICDS,前7位是从机地址,第8位表示传输方向(0表示写操作,1表示读操作)。

s3c2440传输函数,根据标志位flags,来指明是读/写(1:读 0:写)。代码如下:

int s3c2440_master_xfer(p_i2c_msg msgs, int num){int i;for (i = 0; i < num; i++){if (msgs[i]->flags == 0)/* write */do_master_tx(msgs[i]);elsedo_master_rx(msgs[i]);}}

我们定义一个i2c_controller结构体s3c2440_i2c_con。下面的代码对他进行初始化。

static i2c_controller s3c2440_i2c_con = {.name = "s3c2440",.init = s3c2440_i2c_con_init,.master_xfer = s3c2440_master_xfer,};

s3c2440_i2c_con_add函数把上面定义的s3c2440_i2c_con结构体注册到上层的i2c_controller数组中。

void s3c2440_i2c_con_add(void){register_i2c_controller(&s3c2440_i2c_con);}

「新品首发」STM32MP157开发板火爆预售!首批仅300套

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/381030.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

dosbox 伪指令dd为什么会报错_什么是SQL函数?为什么使用SQL函数可能会带来问题?...

本文已收录GitHub&#xff0c;更有互联网大厂面试真题&#xff0c;面试攻略&#xff0c;高效学习资料等函数在计算机语言的使用中贯穿始终&#xff0c;在 SQL 中我们也可以使用函数对检索出来的数据进行函数操作&#xff0c;比如求某列数据的平均值&#xff0c;或者求字符串的长…

centos7 docker删除端口映射_容器Docker详解

概述基本概念Docker是一个开源的应用容器引擎&#xff0c;基于Go语言并遵从Apache2.0协议开源。Docker可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中&#xff0c;然后发布到任何流行的Linux机器上&#xff0c;也可以实现虚拟化。容器是完全使用沙箱机制&a…

深入解析结构化异常处理(SEH) - by Matt Pietrek

尽管以前写过一篇SEH相关的文章《关于SEH的简单总结》&#xff0c; 但那真的只是皮毛&#xff0c;一直对Windows异常处理的原理似懂非懂&#xff0c; 看了下面的文章 &#xff0c;一切都豁然开朗. 1997年文章&#xff0c;Windows技术的根一直没变&#xff1a;http://www.micr…

@requestbody 接受int参数_C++之指针作为函数参数

C 允许您传递指针给函数&#xff0c;只需要简单地声明函数参数为指针类型即可。下面的实例中&#xff0c;我们传递一个无符号的 long 型指针给函数&#xff0c;并在函数内改变这个值&#xff1a;#include <iostream> #include <ctime>using namespace std; void ge…

c++怎么将文件中的数据读出并赋值给字符串_web前端开发过程中如何写JavaScript程序?...

script标签使用< script >< /script >src : 外联script 标签(立即调用,不能在该标签内写代码)< script >// 在标签内书写内容< /script >< script srcjavascript.js >// 这里面不能写任何内容< /script >一切准备就绪&#xff0c;让我们从…

简美电子相册

下载地址&#xff1a;微客互联 转载于:https://www.cnblogs.com/Witkey/archive/2010/06/10/1755755.html

3说明书_知行翻译:做化妆品说明书翻译时,这3点需要谨记

经过20多年的迅猛发展&#xff0c;被称为“美丽经济”的中国化妆品产业已经取得非常大的成就&#xff0c;在这20多年里&#xff0c;中国化妆品产业从小到大&#xff0c;从弱到强&#xff0c;从简单粗放到科技领先&#xff0c;已经逐步成为全世界最大的新兴市场&#xff0c;很多…

拉拢中小网站 淘宝百度暗战升级...

拉拢中小网站 淘宝百度暗战升级... 重庆晚报 讯 近日&#xff0c;大量淘宝联盟站长反映其网站在百度搜索结果大幅缩水&#xff0c;疑遭集体封杀。百度的理由是“清扫垃圾页面”。迟迟未表态的淘宝近日对前者进行了公开回应。至此&#xff0c;淘宝跟百度之间为拉拢中小网站的暗战…

.Net Remoting(基本操作) - Part.2 (转)

Remoting 构架 1.客户端(客户应用程序) 客户端的处理包含三个基本的组成部分&#xff0c;代理(Proxy)、格式器(Formatter) 和 通道(Channel)。 2.服务端(宿主应用程序) 服务端主要由 通道(Channel)、格式器(Formatter)、Stack Builder组成。 在服务端&#xff0c;宿主程序保持着…

转载——CVE-2019-0807

译文声明 本文是翻译文章&#xff0c;文章原作者mcafee&#xff0c;文章来源&#xff1a;securingtomorrow.mcafee.com 原文地址&#xff1a;https://securingtomorrow.mcafee.com/other-blogs/mcafee-labs/rdp-stands-for-really-do-patch-understanding-the-wormable-rdp-v…

angular移除事件绑定事件绑定_Vue.js子组件利用事件向父组件传输数据,以及sync修饰符和双向绑定...

在Vue.js的组件中&#xff0c;prop是“单向绑定”的&#xff0c;数据只能从父组件传输到子组件。Vue文档中的说了这样做的原因&#xff1a;所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定&#xff1a;父级 prop 的更新会向下流动到子组件中&#xff0c;但是反过来则…

1!+2!+3!+…+10!的和

1!2!3!…10!的和 代码 public class Test {public static void main(String[] args) {/*输出1&#xff01;2&#xff01;***10&#xff01;的和*/int sum0;int n1;for (int i 1; i <10 ; i) {for (int j1;j<i;j){nn*j;}sumn;n1;}System.out.println("sum"su…

ipad无法充电怎么办_IPAD充电线破损无法保修,资深“果粉”吐槽:店大欺客!...

应该有不少人都是在使用苹果的电子产品吧&#xff1f;包括iphone、ipad之类的。您在使用的过程中有没有发现一个问题&#xff0c;这些电子产品的充电线似乎很不经用&#xff0c;没多久就会发生断裂或者破损&#xff0c;但大部分人都很少会去较真&#xff0c;一般都是自己花钱再…

有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少?

代码 import java.util.Scanner;public class Testified {public static void main(String[] args) {Scanner scanner new Scanner(System.in);System.out.println("请输入月数:");int n scanner.nextInt();System.out.println("第"n"个月的兔子总…

jbod ugood 磁盘驱动状态_如何检查Mac磁盘空间,mac磁盘空间其他怎么清理

致力于成为您终身的苹果管家点击上方蓝字 关注我们检查Mac磁盘空间的时候&#xff0c;你会发现“其他存储”占用了驱动器太多的空间。你知道Mac上的其他存储在哪里&#xff0c;mac磁盘空间其他怎么清理吗&#xff1f;这里macw小编为大家带来了详细的mac 清理磁盘空间教程&…

最强鸿蒙系统txt_鸿蒙系统升级时间确认,哪些手机有望成为首批“宠儿”?

在华为麒麟芯片受到打压的这段时间&#xff0c;鸿蒙系统可以说是华为近阶段最受瞩目的研发项目之一。鸿蒙系统不仅仅是一个手机操作系统&#xff0c;它还可以安装在PC、智能家居设备。它的强大除了体现在很多方面。例如传统APP开发代码复杂&#xff0c;劳动强度大&#xff0c;后…

关于Tomcat双击startup.bat文件一闪而过问题

原因&#xff1a; 这是因为我们没有配置JAVA_HOME环境变量&#xff0c;Tomcat本身就是java写的解决方法 找到我们电脑的属性&#xff0c;打开&#xff0c;显示以下界面&#xff1a; 点击高级系统设置&#xff0c;进入下面的界面&#xff1a; 点击环境变量吗&#xff0c;进…

windows内核情景分析---进程线程2

二、线程调度与切换 众所周知&#xff1a;Windows系统是一个分时抢占式系统&#xff0c;分时指每个线程分配时间片&#xff0c;抢占指时间片到期前&#xff0c;中途可以被其他更高优先级的线程强制抢占。 背景知识&#xff1a;每个cpu都有一个TSS&#xff0c;叫‘任务状态段’…

asp.net mvc 2 DisplayTemplates 的使用

asp.net mvc 2 官方给的例子有些简单&#xff0c;主要介绍了新的功能。下面主要介绍下DisplayTemplates 给我们带来的实用的功能&#xff0c;可以自定义字段显示的方式&#xff0c;按类型分&#xff1a;String、Boolean、Decimal。按显示的方式&#xff1a;EmailAddress、Html、…

关于Tomcat端口8080占用问题(解决方法)

解决方法 打开cmd命令提示符&#xff0c;输入netstat -aov&#xff0c;在本地地址下找到8080端口&#xff0c;显示如下&#xff1a; 这个时候我们要记得PID后面的数字&#xff0c;我的是8740&#xff1a; 然后打开任务管理器&#xff0c;在详细信息下找的PID为8740的&#…