FPGA基础设计(四):IIC协议

时间:2022-09-22 03:42:50
FPGA基础设计(四):IIC协议

很多数字传感器、数字控制的芯片(DDS、串行ADC、串行DAC)都是通过IIC总线来和控制器通信的。不过IIC协议仍然是一种慢速的通信方式,标准IIC速率为100kbit/s,快速模式速率为400kbit/s。本文致力于讲述如何用计数器控制和分频时钟控制两种方式完成IIC的读写操作。

IIC协议

  IIC协议是一种多机通讯,由SDA数据线和SCL时钟线构成串行总线,所有的IIC设备都可以挂载到总线上,但每个设备都有唯一的设备读地址和设备写地址。在使用IIC作为数字接口的芯片datasheet中都可以看到该设备的设备读/写地址情况,并可以查找到相应的读写时序,以及对速率的要求。下图是一个通用的IIC协议时序:

FPGA基础设计(四):IIC协议

我们可以总结出五种IIC协议的时序状态:
  1. 空闲状态,当SDA和SCL两条信号线都处于高电平时总线处于空闲状态。
  2. 开始信号,SCL为高电平期间SDA信号线上产生了下降沿标志着的一次数据传输的开始。开始信号应当由主机发起。
  3. 数据传输,在SCL同步控制下SDA串行的传送每一位,因此传送8bits的数据需要8个SCL时钟。SCL为高电平时期SDA电平状态必须稳定;SCL为低电平期间才允许SDA改变状态。
  4. 应答信号,IIC总线上每传送一个8位字节,第9个脉冲期间便会释放总线,由接收器发出一个应答信号,反馈有没有成功接收。
  5. 停止信号,在SCL保持高电平期间,将SDA信号线释放恢复到高电平,标志一次数据传输的结束,IIC总线也重新回到了空闲状态。

计数器控制IIC读写

  在“FPGA基础设计(三):UART串口通信”中已经接触到了使用计数器控制时序的方法,这个方法在控制IIC通信时同样实用。一次完整的写入操作如下所示:
case( i )
0: // iic Start
begin
isOut <= 1; //SDA端口输出

if( C1 == 0 ) rSCL <= 1'b1;
else if( C1 == 200 ) rSCL <= 1'b0; //SCL由高变低

if( C1 == 0 ) rSDA <= 1'b1;
else if( C1 == 100 ) rSDA <= 1'b0; //SDA先由高变低

if( C1 == 250 -1) begin C1 <= 9'd0; i <= i + 1'b1; end
else C1 <= C1 + 1'b1;
end

1: // Write Device Addr
begin rData <= {4'b1010, 3'b000, 1'b0}; i <= 5'd7; Go <= i + 1'b1; end

2: // Wirte Word Addr
begin rData <= Addr_Sig; i <= 5'd7; Go <= i + 1'b1; end

3: // Write Data
begin rData <= WrData; i <= 5'd7; Go <= i + 1'b1; end

4: //iic Stop
begin
isOut <= 1'b1;

if( C1 == 0 ) rSCL <= 1'b0;
else if( C1 == 50 ) rSCL <= 1'b1; //SCL先由低变高

if( C1 == 0 ) rSDA <= 1'b0;
else if( C1 == 150 ) rSDA <= 1'b1; //SDA由低变高

if( C1 == 250 -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end
else C1 <= C1 + 1'b1;
end

5:
begin isDone <= 1'b1; i <= i + 1'b1; end //写I2C 结束

6:
begin isDone <= 1'b0; i <= 5'd0; end

7,8,9,10,11,12,13,14: //发送Device Addr/Word Addr/Write Data
begin
isOut <= 1'b1;
rSDA <= rData[14-i]; //高位先发送

if( C1 == 0 ) rSCL <= 1'b0;
else if( C1 == 50 ) rSCL <= 1'b1;
else if( C1 == 150 ) rSCL <= 1'b0;

if( C1 == F250K -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end
else C1 <= C1 + 1'b1;
end

15: // waiting for acknowledge
begin
isOut <= 1'b0; //SDA端口改为输入
if( C1 == 100 ) isAck <= SDA;

if( C1 == 0 ) rSCL <= 1'b0;
else if( C1 == 50 ) rSCL <= 1'b1;
else if( C1 == 150 ) rSCL <= 1'b0;

if( C1 == F250K -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end
else C1 <= C1 + 1'b1;
end

16:
if( isAck != 0 ) i <= 5'd0;
else i <= Go;

endcase

 向IIC总线写数据时,需要依次写入待写入的设备写地址、设备中的写地址和待写入的数据共3个8bits字节数据。i代表总线上不同的状态,通过计数器来控制状态之间的跳转。i为0时发出开始信号;i为7~14时控制8bits数据的发送;i为1、2、3时分别为设备地址、字节地址和数据,依次调用7-14完成数据的传输;其余还有停止位、应答位、IIC通信完成置位等状态。

  从器件中读取数据的方法与此一样,只不过通常都需要先向IIC总线写入待读取的设备地址和器件地址,之后再读数据。读数据整体过程比写数据要麻烦一点,但只要控制好状态之间跳转的过程即可。

分频时钟控制IIC读写

  由计数器控制通信时序的方法优点是很灵活,几乎所有的时序方法都可以用这种方法完成;缺点就是太麻烦,需要控制好状态之间的跳转,时序越复杂使用越麻烦,其实在“FPGA采集-传输-显示系统(二):基于FPGA的温度采集和以太网传输”中,我对DS18B20的时序控制就是采用计数器控制的方法。DS18B20的时序要求较多,因此其中的状态跳转已经相当复杂。

  其实在控制IIC这种时钟速率固定的串行协议时,还可以在外部分频或PLL生成一个低频的通信时钟,用这个时钟来控制数据传输过程。如下所示:
always@(posedge clock_i2c)
begin
if(reset_n==1'b0) begin
tr_end<=0;
ack1<=1;
ack2<=1;
ack3<=1;
sclk<=1;
reg_sdat<=1;
end
else
case(cyc_count)
0:begin ack1<=1;ack2<=1;tr_end<=0;sclk<=1;reg_sdat<=1;end
1:reg_sdat<=0; //开始传输
2:sclk<=0;
3:reg_sdat<=i2c_data[23];
4:reg_sdat<=i2c_data[22];
5:reg_sdat<=i2c_data[21];
6:reg_sdat<=i2c_data[20];
7:reg_sdat<=i2c_data[19];
8:reg_sdat<=i2c_data[18];
9:reg_sdat<=i2c_data[17];
10:reg_sdat<=i2c_data[16];
11:reg_sdat<=1; //应答信号
12:begin reg_sdat<=i2c_data[15];ack1<=i2c_sdat;end
13:reg_sdat<=i2c_data[14];
14:reg_sdat<=i2c_data[13];
15:reg_sdat<=i2c_data[12];
16:reg_sdat<=i2c_data[11];
17:reg_sdat<=i2c_data[10];
18:reg_sdat<=i2c_data[9];
19:reg_sdat<=i2c_data[8];
20:reg_sdat<=1; //应答信号
21:begin reg_sdat<=i2c_data[7];ack2<=i2c_sdat;end
22:reg_sdat<=i2c_data[6];
23:reg_sdat<=i2c_data[5];
24:reg_sdat<=i2c_data[4];
25:reg_sdat<=i2c_data[3];
26:reg_sdat<=i2c_data[2];
27:reg_sdat<=i2c_data[1];
28:reg_sdat<=i2c_data[0];
29:reg_sdat<=1; //应答信号
30:begin ack3<=i2c_sdat;sclk<=0;reg_sdat<=0;end
31:sclk<=1;
32:begin reg_sdat<=1;tr_end<=1;end //IIC传输结束
endcase

可以看到这个always块的敏感目标为分频后的IIC时钟信号clock_i2c,整个传输过程一目了然。这两种控制时序的方法不仅适合于IIC协议,还适合于其它的串行协议,下一章“FPGA基础设计(五):SPI协议”仍将使用这种方法。

转载:http://xilinx.eetrend.com/blog/12413

FPGA基础设计(四):IIC协议的更多相关文章

  1. 20155219实验四 Android开发基础设计实验报告

    20155219实验四 Android开发基础设计实验报告 实验内容 安装Andriod Studio并配置软件 使用Andriod Studio软件实现Hello World!+学号的小程序 实验步 ...

  2. 20155227 《Java程序设计》实验四 Android开发基础设计实验报告

    20155227 <Java程序设计>实验四 Android开发基础设计实验报告 任务一 Android Stuidio的安装测试: 参考<Java和Android开发学习指南(第二 ...

  3. 20145219 《Java程序设计》实验四 Android开发基础设计实验报告

    20145219 <Java程序设计>实验四 Android开发基础设计实验报告 实验内容 安装Andriod Studio并配置软件 使用Andriod Studio软件实现Hello ...

  4. FPGA基础入门篇&lpar;四&rpar; 边沿检测电路

    FPGA基础入门篇(四)--边沿检测电路 一.边沿检测 边沿检测,就是检测输入信号,或者FPGA内部逻辑信号的跳变,即上升沿或者下降沿的检测.在检测到所需要的边沿后产生一个高电平的脉冲.这在FPGA电 ...

  5. FPGA基础学习&lpar;9&rpar; -- 复位设计

    目录 1. 常见问题 2. 常见的复位方式 3. 合理的复位设计 3.1 复位电平 3.2 异步复位同步化 3.3 恰到好处的复位 4. 补充 4.1 所谓的上电初始化 参考文献 一开始接触到FPGA ...

  6. IIC协议建模——读写EEPROM

    案例采用明德扬设计思想完成.IIC协议是非常常用的接口协议,在电子类岗位招聘要求中经常出现它的身影.关于IIC协议这里只做简要介绍,详细信息请自行百度或查阅相关Datasheet,网上资料非常多.该篇 ...

  7. 第十六章 IIC协议详解&plus;UART串口读写EEPROM

    十六.IIC协议详解+Uart串口读写EEPROM 本文由杭电网友曾凯峰根据小梅哥FPGA IIC协议基本概念公开课内容整理并最终编写Verilog代码实现使用串口读写EEPROM的功能. 以下为原文 ...

  8. IIC协议学习笔记

    "移植"的重要性:并非所有的电路都得自己设计,到了一定阶段,"移植"也是一种学习能力.--CrazyBingo 转眼间期末又到了,最近开始了所谓的期末总预习,比 ...

  9. FPGA基础知识了解

    FPGA学习的一些误区 FPGA入门必看资源 FPGA百度百科 FPGA基础知识及其工作原理 高端设计工具为少有甚是没有硬件设计技术的工程师和科学家提供现场可编程门阵列(FPGA).无论你使用图形化设 ...

随机推荐

  1. jqGrid subGrid配置 如何首次加载动态展开所有的子表格

    有时候需求需要默认加载表格的时候把子表格的数据也显示出来,经过研究相关SubGrids API配置如下: 属性 类型 描述 默认值 subGrid boolean 设置为true启用子表格.如果启用子 ...

  2. JavaScript学习笔记-实现枚举类型&comma;扑克牌应用

    //实现枚举类型,扑克牌应用 function creatEnum(p){     //构造函数     var Enumeration = function(){throw 'can not Ins ...

  3. 【mysql启动Innodb的方法】

    点击此处进入原网页 1.存储引擎是什么? Mysql中的数据用各种不同的技术存储在文件(或者内存)中.这些技术中的每一种技术都使用不同的存储机制.索引技巧.锁定水平并且最终提供广泛的不同的功能和能力. ...

  4. android gravity属性 和 weight属性

    来看这个布局文件 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:and ...

  5. c&num;字符串及数组操作

    字符串操作(取当前时间)string time=convert.tostring(DateTime.Today).split( new char []{' '});    textbox1.text= ...

  6. ArcEngine 10&period;2 汉化问题

    开发环境:VS2010 + ArcEngine 10.2 + DEV 15.2 arcengine自带工具条提示汉化方法: 1:重写tool里的方法 2:利用工具箱里的ToopTip 3:把:ArcG ...

  7. 024&lowbar;mac配置屏保命令

    注意吃饭等离开工位的时候养成随时开启屏保的功能,养成信息保护的好习惯,mac如何配置屏幕保护呢? 一. 通过mac"设置"里的"Desktop & Screen ...

  8. c语言宏定义详解

    1,防止一个头文件被重复包含 #ifndef COMDEF_H #define COMDEF_H //头文件内容 #endif 2,重新定义一些类型,防止由于各种平台和编译器的不同,而产生的类型字节数 ...

  9. 1018 Public Bike Management &lpar;30&rpar; Dijkstra算法 &plus; DFS

    题目及题解 https://blog.csdn.net/CV_Jason/article/details/81385228 迪杰斯特拉重新认识 两个核心的存储结构: int dis[n]: //记录每 ...

  10. mysql 开发进阶篇系列 30 数据库二进制包&lpar;安装指定路径,目录介绍&rpar;

    一. 指定路径 在上一篇里,二进制包解压后,全部放入在/usr/local/mysql目录下,在安装时指定了基础目录和数据目录, --basedir=/usr/local/mysql --datadi ...