i2c框架
title: iic框架
tags: ARM
date: 2018-11-05 13:44:58
i2c框架
寄存器



/* 配置引脚用于I2C*/
GPECON &= ~((3<<28) | (3<<30));
GPECON |= ((2<<28) | (2<<30));
/* 设置时钟 */
/* [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 = (1<<7) | (0<<6) | (1<<5) | (30<<0);
中断配置: IIC没有次中断源.直接配置INTMSK即可INTMSK &= ~(1<<27);
主机发送

int do_master_tx(p_i2c_msg msg)
{
p_cur_msg = msg;
msg->cnt_transferred = -1;
msg->err = 0;
/* 设置寄存器启动传输 */
/* 1. 配置为 master tx mode */
IICCON |= (1<<7); /* TX mode, 在ACK周期释放SDA */
IICSTAT = (1<<4);
/* 2. 把从设备地址写入IICDS */
IICDS = msg->addr<<1;
/* 3. IICSTAT = 0xf0 , 数据即被发送出去, 将导致中断产生 */
IICSTAT = 0xf0;
/* 后续的传输由中断驱动 */
/* 循环等待中断处理完毕 */
while (!msg->err && msg->cnt_transferred != msg->len);
if (msg->err)
return -1;
else
return 0;
}
主机接收

int do_master_rx(p_i2c_msg msg)
{
p_cur_msg = msg;
msg->cnt_transferred = -1;
msg->err = 0;
/* 设置寄存器启动传输 */
/* 1. 配置为 Master Rx mode */
IICCON |= (1<<7); /* RX mode, 在ACK周期回应ACK */
IICSTAT = (1<<4);
/* 2. 把从设备地址写入IICDS */
IICDS = (msg->addr<<1)|(1<<0);
/* 3. IICSTAT = 0xb0 , 从设备地址即被发送出去, 将导致中断产生 */
IICSTAT = 0xb0;
/* 后续的传输由中断驱动 */
/* 循环等待中断处理完毕 */
while (!msg->err && msg->cnt_transferred != msg->len);
if (msg->err)
return -1;
else
return 0;
}
中断处理
注意
- 连续读的最后一个字节不响应ack,以用来终止读.
- 在读写第一个字节的时候,判断是否有ack来判断是否设备存在

写
if (p_cur_msg->flags == 0) /* write */
{
/* 对于第1个中断, 它是发送出设备地址后产生的
* 需要判断是否有ACK
* 有ACK : 设备存在
* 无ACK : 无设备, 出错, 直接结束传输
*/
if (p_cur_msg->cnt_transferred == 0) /* 第1次中断 */
{
if (iicstat & (1<<0))
{ /* no ack */
/* 停止传输 */
IICSTAT = 0xd0;
IICCON &= ~(1<<4);//挂起标志
p_cur_msg->err = -1;
printf("tx err, no ack\n\r");
delay(1000);
return;
}
}
if (p_cur_msg->cnt_transferred < p_cur_msg->len)
{
/* 对于其他中断, 要继续发送下一个数据
*/
IICDS = p_cur_msg->buf[p_cur_msg->cnt_transferred];
IICCON &= ~(1<<4);//挂起标志
}
else
{
/* 停止传输 */
IICSTAT = 0xd0;
IICCON &= ~(1<<4);//挂起标志
delay(1000);
}
}
读
/* 对于第1个中断, 它是发送出设备地址后产生的
* 需要判断是否有ACK
* 有ACK : 设备存在, 恢复I2C传输, 这样在下一个中断才可以得到第1个数据
* 无ACK : 无设备, 出错, 直接结束传输
*/
if (p_cur_msg->cnt_transferred == 0) /* 第1次中断 */
{
if (iicstat & (1<<0))
{ /* no ack */
/* 停止传输 */
IICSTAT = 0x90;
IICCON &= ~(1<<4);
p_cur_msg->err = -1;
printf("rx err, no ack\n\r");
delay(1000);
return;
}
else /* ack */
{
/* 如果是最后一个数据, 启动传输时要设置为不回应ACK */
/* 恢复I2C传输 */
if (isLastData())
{
resume_iic_without_ack();
}
else
{
resume_iic_with_ack();
}
return;
}
}
/* 非第1个中断, 表示得到了一个新数据
* 从IICDS读出、保存
*/
if (p_cur_msg->cnt_transferred < p_cur_msg->len)
{
index = p_cur_msg->cnt_transferred - 1;
p_cur_msg->buf[index] = IICDS;
/* 如果是最后一个数据, 启动传输时要设置为不回应ACK */
/* 恢复I2C传输 */
if (isLastData())
{
resume_iic_without_ack();
}
else
{
resume_iic_with_ack();
}
}
else
{
/* 发出停止信号 */
IICSTAT = 0x90;
IICCON &= ~(1<<4);//清标志
delay(1000);
}
程序框架

![]()
i2c框架的更多相关文章
- (1)I2c的简介和特性
I2C我是想全面深入的从嵌入式软件工程师的角度做个理解,刚刚还申请了一个专栏,这个好好写. 学习技术从外文文档看起-- 要全面了解I2C,可以从<I2C-bus specific ...
- linux设备驱动程序-i2c(2)-adapter和设备树的解析
linux设备驱动程序-i2c(2)-adapter和设备树的解析 (注: 基于beagle bone green开发板,linux4.14内核版本) 在本系列linux内核i2c框架的前两篇,分别讲 ...
- linux设备驱动程序-i2c(0)-i2c设备驱动源码实现
(基于4.14内核版本) 为了梳理清楚linux内核中的i2c实现框架,从本文开始,博主将分几个章节分别解析i2c总线在linux内核中的形成过程.匹配过程.以及设备驱动程序源码实现. 在介绍linu ...
- linux设备驱动程序-i2c(1):i2c总线的添加与实现
linux设备驱动程序-i2c(1):i2c总线的添加与实现 (基于4.14内核版本) 在上一章节linux设备驱动程序-i2c(0)-i2c设备驱动源码实现中,我们演示了i2c设备驱动程序的源码实现 ...
- linux设备驱动程序--串行通信驱动框架分析
linux 串行通信接口驱动框架 在学习linux内核驱动时,不论是看linux相关的书籍,又或者是直接看linux的源码,总是能在linux中看到各种各样的框架,linux内核极其庞杂,linux各 ...
- 十四、i2c子系统
由于之后的触摸屏驱动分析中使用到了GPIO子系统和i2c子系统,因此在分析触摸屏驱动之前我准备把这两个子系统进行简单分析. 在读者学习本章以及后续i2c相关章节之前,最好了解i2c通信方式,可以参考: ...
- MTK-TP(触屏)解读一
MTK中的TP代码结构并不复杂,相比于其他的系统更为的简单些.它使用的是input子系统,通过该系统来上报触摸按键. 首先我们来看看TP的文件夹下的各代码文件的功能. 文件名 具体功能 关系文件 tp ...
- linux驱动工程面试必问知识点
linux内核原理面试必问(由易到难) 简单型 1:linux中内核空间及用户空间的区别?用户空间与内核通信方式有哪些? 2:linux中内存划分及如何使用?虚拟地址及物理地址的概念及彼此之间的转化, ...
- RTC设备驱动
问题:pcf8563 RTC设备驱动不能被正常的加载!问题分析过程. 问题在下午得到解决,虽然解决的办法比较笨,采用的是不断的使用printk来跟踪rtc-8563驱动的加载的过程,以及iic模块的工 ...
随机推荐
- hdu-3746(kmp)
题意:给你一个字符串,问你至少增添几个字符可以把这个字符串变成一个循环字符串(ababa的循环节是ab,不是aba): 解题思路:利用kmp中的next数组,首先在这样求next的数组的代码里: vo ...
- 彻底弄懂 HTTP 缓存机制及原理 | 干货
来源:www.cnblogs.com/chenqf/p/6386163.html 前言 Http 缓存机制作为 web 性能优化的重要手段,对于从事 Web 开发的同学们来说,应该是知识体系库中的一个 ...
- BZOJ3812 主旋律(状压dp+容斥原理)
设f[S]为S点集是SCC的方案数.考虑通过去掉不合法方案转移.可以枚举入度为0的SCC所含点集S',这样显然S^S'内部的边和由S'连向S^S'的边删还是不删任选.但是这样无法保证S'包含所有入度为 ...
- 洛谷P1216数字三角形题解
题目 这道题是一个典型的DP,可以用倒推,顺推的方法,来解这道题.当然用不同的方法他的循环次序是不一样的,所以我们一定要深刻地理解题目的大意,再采用状态转移方程与边界每次求出最优解,并记录循环一遍后就 ...
- Matplotlib学习---用seaborn画直方图,核密度图(histogram, kdeplot)
由于直方图受组距(bin size)影响很大,设置不同的组距可能会产生完全不同的可视化结果.因此我们可以用密度平滑估计来更好地反映数据的真实特征.具体可参见这篇文章:https://blog.csdn ...
- 【XSY2730】Ball 多项式exp 多项式ln 多项式开根 常系数线性递推 DP
题目大意 一行有\(n\)个球,现在将这些球分成\(k\) 组,每组可以有一个球或相邻两个球.一个球只能在至多一个组中(可以不在任何组中).求对于\(1\leq k\leq m\)的所有\(k\)分别 ...
- 计算几何细节梳理&模板
点击%XZY巨佬 向量的板子 #include<bits/stdc++.h> #define I inline using namespace std; typedef double DB ...
- 15 Zabbix Item类型之Zabbix trapper类型
点击返回:自学Zabbix之路 点击返回:自学Zabbix4.0之路 点击返回:自学zabbix集锦 15 Zabbix Item类型之Zabbix trapper类型 zabbix获取数据时有时会出 ...
- JSOI2014骑士游戏(最短路)
题目背景 长期的宅男生活中,JYY又挖掘出了一款RPG游戏.在这个游戏中JYY会 扮演一个英勇的骑士,用他手中的长剑去杀死入侵村庄的怪兽. 题目描述 在这个游戏中,JYY一共有两种攻击方式,一种是普通 ...
- 哈尔滨工程大学ACM预热赛 G题 A hard problem(数位dp)
链接:https://ac.nowcoder.com/acm/contest/554/G Now we have a function f(x): int f ( int x ) { if ( ...