协议——IIC
I²C即Inter-Integrated Circuit(集成电路总线),它是一种串行通信总线,使用多主从架构,由飞利浦公司在1980年代设计出来的一种简单、双向、二线制总线标准。多用于主机和从机在数据量不大且传输距离短的场合下的主从通信。主机启动总线,并产生时钟用于传送数据,此时任何接收数据的器件均被认为是从机。I²C总线由数据线SDA和时钟线SCL构成通信线路,既可用于发送数据,也可接收数据。在主控与被控IC之间可进行双向数据传送,数据的传输速率在标准模式下可达100kbit/s,在快速模式下可达400kbit/s,在高速模式下可达3.4Mbit/s,各种被控器件均并联在总线上,通过器件地址(SLAVE ADDR,具体可查器件手册)识别。I²C总线物理拓扑结构图如下所示:










//**************************************************************************
// *** 名称 : iic.v
// *** 作者 : xianyu_FPGA
// *** 博客 : https://www.cnblogs.com/xianyufpga/
// *** 日期 : 2019-08-10
// *** 描述 : IIC控制器
//************************************************************************** module iic
//========================< 参数 >==========================================
#(
parameter DEVICE_ID = 'b1010000 , //器件ID
parameter CLK = 'd50_000_000 , //本模块的时钟频率
parameter SCL = 'd250_000 //输出的SCL时钟频率
)
//========================< 端口 >==========================================
(
input clk , //时钟
input rst_n , //复位,低电平有效
//IIC control ---------------------------------------
input iic_en , //IIC触发信号
input addr16_en , //16位地址使能
input addr8_en , //8位地址使能
input write_en , //IIC写使能
input read_en , //IIC读使能
input [:] iic_addr , //IIC器件内地址
input [ :] iic_data_wr , //IIC要写的数据
//IIC output ----------------------------------------
output reg [ :] iic_data_rd , //IIC读出的数据
output reg iic_done , //IIC一次操作完成
output reg iic_scl , //IIC的SCL时钟信号
inout iic_sda , //IIC的SDA数据信号
//dri_clk -------------------------------------------
output reg iic_dri_clk //驱动IIC操作的驱动时钟,1Mhz
);
//========================< 参数 >==========================================
localparam IDLE = 'b0000_0001 ; //空闲状态
localparam DEVICE = 'b0000_0010 ; //写器件地址
localparam ADDR_16 = 'b0000_0100 ; //写字地址高8位
localparam ADDR_8 = 'b0000_1000 ; //写字地址低8位
localparam DATA_WR = 'b0001_0000 ; //写数据
localparam DEVICE_RD = 'b0010_0000 ; //虚写器件地址
localparam DATA_RD = 'b0100_0000 ; //读数据
localparam STOP = 'b1000_0000 ; //结束
//========================< 信号 >==========================================
reg sda_dir ; //IIC数据(SDA)方向控制
reg sda_out ; //SDA输出信号
wire sda_in ; //SDA输入信号
reg state_done ; //状态结束
reg [ :] cnt ; //计数
reg [ :] state_c ; //状态机当前状态
reg [ :] state_n ; //状态机下一状态
reg [:] iic_addr_t ; //地址
reg [ :] iic_data_rd_t ; //读取的数据
reg [ :] iic_data_wr_t ; //IIC需写的数据的临时寄存
reg [ :] clk_cnt ; //分频时钟计数
wire [ :] clk_divide ; //模块驱动时钟的分频系数 //==========================================================================
//== sda控制
//==========================================================================
assign iic_sda = sda_dir ? sda_out : 'bz; //SDA数据输出或高阻
assign sda_in = iic_sda ; //SDA数据输入 //==========================================================================
//== 生成SCL的4倍时钟来驱动后面IIC的操作,生成1Mhz的iic_dri_clk
//==========================================================================
assign clk_divide = (CLK/SCL) >> ; // >>3即除以8 always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
iic_dri_clk <= 'b1;
clk_cnt <= 'd0;
end
else if(clk_cnt == clk_divide - 'd1) begin
clk_cnt <= 'd0;
iic_dri_clk <= ~iic_dri_clk;
end
else
clk_cnt <= clk_cnt + 'b1;
end //==========================================================================
//== 状态机
//==========================================================================
always @(posedge iic_dri_clk or negedge rst_n) begin
if(!rst_n)
state_c <= IDLE;
else
state_c <= state_n;
end always @(*) begin
case(state_c)
IDLE: begin //空闲状态
if(iic_en) begin
state_n = DEVICE;
end
else
state_n = IDLE;
end
DEVICE: begin //写器件ID
if(state_done) begin
if(addr16_en)
state_n = ADDR_16;
else if(addr8_en)
state_n = ADDR_8 ;
end
else
state_n = DEVICE;
end
ADDR_16: begin //写地址高8位
if(state_done)
state_n = ADDR_8;
else
state_n = ADDR_16;
end
ADDR_8: begin //写地址低8位
if(state_done) begin
if(write_en)
state_n = DATA_WR;
else if(read_en)
state_n = DEVICE_RD;
end
else
state_n = ADDR_8;
end
DATA_WR: begin //写数据
if(state_done)
state_n = STOP;
else
state_n = DATA_WR;
end
DEVICE_RD: begin //虚写器件ID
if(state_done)
state_n = DATA_RD;
else
state_n = DEVICE_RD;
end
DATA_RD: begin //读数据
if(state_done)
state_n = STOP;
else
state_n = DATA_RD;
end
STOP: begin //结束
if(state_done)
state_n = IDLE;
else
state_n = STOP ;
end
default:state_n= IDLE;
endcase
end //==========================================================================
//== 设计各路信号
//==========================================================================
always @(posedge iic_dri_clk or negedge rst_n) begin
if(!rst_n) begin
iic_scl <= 'b1;
sda_out <= 'b1;
sda_dir <= 'b1;
iic_done <= 'b0;
cnt <= 'b0;
state_done <= 'b0;
iic_addr_t <= 'b0;
iic_data_rd <= 'b0;
iic_data_rd_t <= 'b0;
iic_data_wr_t <= 'b0;
end
else begin
state_done <= 'b0 ;
cnt <= cnt +'b1 ;
case(state_c)
//--------------------------------------------------- 空闲状态
IDLE: begin
iic_scl <= 'b1;
sda_out <= 'b1;
sda_dir <= 'b1;
iic_done <= 'b0;
cnt <= 'b0;
if(iic_en) begin
iic_addr_t <= iic_addr;
iic_data_wr_t <= iic_data_wr;
end
end
//--------------------------------------------------- 写器件ID
DEVICE: begin
case(cnt)
'd1 : sda_out <= 1'b0;
'd3 : iic_scl <= 1'b0;
'd4 : sda_out <= DEVICE_ID[6];
'd5 : iic_scl <= 1'b1;
'd7 : iic_scl <= 1'b0;
'd8 : sda_out <= DEVICE_ID[5];
'd9 : iic_scl <= 1'b1;
'd11: iic_scl <= 1'b0;
'd12: sda_out <= DEVICE_ID[4];
'd13: iic_scl <= 1'b1;
'd15: iic_scl <= 1'b0;
'd16: sda_out <= DEVICE_ID[3];
'd17: iic_scl <= 1'b1;
'd19: iic_scl <= 1'b0;
'd20: sda_out <= DEVICE_ID[2];
'd21: iic_scl <= 1'b1;
'd23: iic_scl <= 1'b0;
'd24: sda_out <= DEVICE_ID[1];
'd25: iic_scl <= 1'b1;
'd27: iic_scl <= 1'b0;
'd28: sda_out <= DEVICE_ID[0];
'd29: iic_scl <= 1'b1;
'd31: iic_scl <= 1'b0;
'd32: sda_out <= 1'b0; //0:写
'd33: iic_scl <= 1'b1;
'd35: iic_scl <= 1'b0;
'd36: begin
sda_dir <= 'b0; //从机应答
sda_out <= 'b1;
end
'd37: iic_scl <= 1'b1;
'd38: state_done <= 1'b1; //状态结束
'd39: begin
iic_scl <= 'b0;
cnt <= 'b0;
end
default : ;
endcase
end
//--------------------------------------------------- 写字地址高8位
ADDR_16: begin
case(cnt)
'd0 : begin
sda_dir <= 'b1 ;
sda_out <= iic_addr_t[];
end
'd1 : iic_scl <= 1'b1;
'd3 : iic_scl <= 1'b0;
'd4 : sda_out <= iic_addr_t[14];
'd5 : iic_scl <= 1'b1;
'd7 : iic_scl <= 1'b0;
'd8 : sda_out <= iic_addr_t[13];
'd9 : iic_scl <= 1'b1;
'd11: iic_scl <= 1'b0;
'd12: sda_out <= iic_addr_t[12];
'd13: iic_scl <= 1'b1;
'd15: iic_scl <= 1'b0;
'd16: sda_out <= iic_addr_t[11];
'd17: iic_scl <= 1'b1;
'd19: iic_scl <= 1'b0;
'd20: sda_out <= iic_addr_t[10];
'd21: iic_scl <= 1'b1;
'd23: iic_scl <= 1'b0;
'd24: sda_out <= iic_addr_t[9];
'd25: iic_scl <= 1'b1;
'd27: iic_scl <= 1'b0;
'd28: sda_out <= iic_addr_t[8];
'd29: iic_scl <= 1'b1;
'd31: iic_scl <= 1'b0;
'd32: begin
sda_dir <= 'b0; //从机应答
sda_out <= 'b1;
end
'd33: iic_scl <= 1'b1;
'd34: state_done <= 1'b1; //状态结束
'd35: begin
iic_scl <= 'b0;
cnt <= 'b0;
end
default : ;
endcase
end
//--------------------------------------------------- 写字地址低8位
ADDR_8: begin
case(cnt)
'd0: begin
sda_dir <= 'b1 ;
sda_out <= iic_addr_t[];
end
'd1 : iic_scl <= 1'b1;
'd3 : iic_scl <= 1'b0;
'd4 : sda_out <= iic_addr_t[6];
'd5 : iic_scl <= 1'b1;
'd7 : iic_scl <= 1'b0;
'd8 : sda_out <= iic_addr_t[5];
'd9 : iic_scl <= 1'b1;
'd11: iic_scl <= 1'b0;
'd12: sda_out <= iic_addr_t[4];
'd13: iic_scl <= 1'b1;
'd15: iic_scl <= 1'b0;
'd16: sda_out <= iic_addr_t[3];
'd17: iic_scl <= 1'b1;
'd19: iic_scl <= 1'b0;
'd20: sda_out <= iic_addr_t[2];
'd21: iic_scl <= 1'b1;
'd23: iic_scl <= 1'b0;
'd24: sda_out <= iic_addr_t[1];
'd25: iic_scl <= 1'b1;
'd27: iic_scl <= 1'b0;
'd28: sda_out <= iic_addr_t[0];
'd29: iic_scl <= 1'b1;
'd31: iic_scl <= 1'b0;
'd32: begin
sda_dir <= 'b0; //从机应答
sda_out <= 'b1;
end
'd33: iic_scl <= 1'b1;
'd34: state_done <= 1'b1; //状态结束
'd35: begin
iic_scl <= 'b0;
cnt <= 'b0;
end
default : ;
endcase
end
//--------------------------------------------------- 写数据
DATA_WR: begin
case(cnt)
'd0: begin
sda_out <= iic_data_wr_t[];
sda_dir <= 'b1;
end
'd1 : iic_scl <= 1'b1;
'd3 : iic_scl <= 1'b0;
'd4 : sda_out <= iic_data_wr_t[6];
'd5 : iic_scl <= 1'b1;
'd7 : iic_scl <= 1'b0;
'd8 : sda_out <= iic_data_wr_t[5];
'd9 : iic_scl <= 1'b1;
'd11: iic_scl <= 1'b0;
'd12: sda_out <= iic_data_wr_t[4];
'd13: iic_scl <= 1'b1;
'd15: iic_scl <= 1'b0;
'd16: sda_out <= iic_data_wr_t[3];
'd17: iic_scl <= 1'b1;
'd19: iic_scl <= 1'b0;
'd20: sda_out <= iic_data_wr_t[2];
'd21: iic_scl <= 1'b1;
'd23: iic_scl <= 1'b0;
'd24: sda_out <= iic_data_wr_t[1];
'd25: iic_scl <= 1'b1;
'd27: iic_scl <= 1'b0;
'd28: sda_out <= iic_data_wr_t[0];
'd29: iic_scl <= 1'b1;
'd31: iic_scl <= 1'b0;
'd32: begin
sda_dir <= 'b0; //从机应答
sda_out <= 'b1;
end
'd33: iic_scl <= 1'b1;
'd34: state_done <= 1'b1; //状态结束
'd35: begin
iic_scl <= 'b0;
cnt <= 'b0;
end
default : ;
endcase
end
//--------------------------------------------------- 虚写器件ID
DEVICE_RD: begin
case(cnt)
'd0 : begin
sda_dir <= 'b1;
sda_out <= 'b1;
end
'd1 : iic_scl <= 1'b1;
'd2 : sda_out <= 1'b0; //重新开始
'd3 : iic_scl <= 1'b0;
'd4 : sda_out <= DEVICE_ID[6];
'd5 : iic_scl <= 1'b1;
'd7 : iic_scl <= 1'b0;
'd8 : sda_out <= DEVICE_ID[5];
'd9 : iic_scl <= 1'b1;
'd11: iic_scl <= 1'b0;
'd12: sda_out <= DEVICE_ID[4];
'd13: iic_scl <= 1'b1;
'd15: iic_scl <= 1'b0;
'd16: sda_out <= DEVICE_ID[3];
'd17: iic_scl <= 1'b1;
'd19: iic_scl <= 1'b0;
'd20: sda_out <= DEVICE_ID[2];
'd21: iic_scl <= 1'b1;
'd23: iic_scl <= 1'b0;
'd24: sda_out <= DEVICE_ID[1];
'd25: iic_scl <= 1'b1;
'd27: iic_scl <= 1'b0;
'd28: sda_out <= DEVICE_ID[0];
'd29: iic_scl <= 1'b1;
'd31: iic_scl <= 1'b0;
'd32: sda_out <= 1'b1; //1:读
'd33: iic_scl <= 1'b1;
'd35: iic_scl <= 1'b0;
'd36: begin
sda_dir <= 'b0; //从机应答
sda_out <= 'b1;
end
'd37: iic_scl <= 1'b1;
'd38: state_done <= 1'b1; //状态结束
'd39: begin
iic_scl <= 'b0;
cnt <= 'b0;
end
default : ;
endcase
end
//--------------------------------------------------- 读数据
DATA_RD: begin
case(cnt)
'd0 : sda_dir <= 1'b0;
'd1 : begin
iic_data_rd_t[] <= sda_in;
iic_scl <= 'b1;
end
'd3 : iic_scl <= 1'b0;
'd5 : begin
iic_data_rd_t[] <= sda_in;
iic_scl <= 'b1;
end
'd7 : iic_scl <= 1'b0;
'd9 : begin
iic_data_rd_t[] <= sda_in;
iic_scl <= 'b1;
end
'd11: iic_scl <= 1'b0;
'd13: begin
iic_data_rd_t[] <= sda_in;
iic_scl <= 'b1;
end
'd15: iic_scl <= 1'b0;
'd17: begin
iic_data_rd_t[] <= sda_in;
iic_scl <= 'b1;
end
'd19: iic_scl <= 1'b0;
'd21: begin
iic_data_rd_t[] <= sda_in;
iic_scl <= 'b1;
end
'd23: iic_scl <= 1'b0;
'd25: begin
iic_data_rd_t[] <= sda_in;
iic_scl <= 'b1;
end
'd27: iic_scl <= 1'b0;
'd29: begin
iic_data_rd_t[] <= sda_in;
iic_scl <= 'b1 ;
end
'd31: iic_scl <= 1'b0;
'd32: begin
sda_dir <= 'b1; //非应答
sda_out <= 'b1;
end
'd33: iic_scl <= 1'b1;
'd34: state_done <= 1'b1; //状态结束
'd35: begin
iic_scl <= 'b0;
cnt <= 'b0;
iic_data_rd <= iic_data_rd_t;
end
default : ;
endcase
end
//--------------------------------------------------- 结束
STOP: begin
case(cnt)
'd0 : begin
sda_dir <= 'b1;
sda_out <= 'b0;
end
'd1 : iic_scl <= 1'b1;
'd3 : sda_out <= 1'b1;
'd15: state_done <= 1'b1; //状态结束
'd16: begin
cnt <= 'b0;
iic_done <= 'b1; //IIC配置完成
end
default : ;
endcase
end
endcase
end
end endmodule
协议——IIC的更多相关文章
- 协议—IIC
I2C总线支持任何IC生产过程NMOS CMOS双极性,两线――串行数据 SDA 和串行时钟SCL线在连接到总线的器件间传递信息,每个器件都有一个唯一的地址识别,无论是微控制器.LCD 驱动器.存储器 ...
- FPGA基础设计(四):IIC协议
很多数字传感器.数字控制的芯片(DDS.串行ADC.串行DAC)都是通过IIC总线来和控制器通信的.不过IIC协议仍然是一种慢速的通信方式,标准IIC速率为100kbit/s,快速模式速率为400kb ...
- 九、IIC驱动原理分析
学习目标:学习IIC驱动原理: 一.IIC总线协议 IIC串行总线包括一条数据线(SDA)和一条时钟线(SCL),支持“一主多从”和“多主机”模式:每个从机设备都有唯一的地址来识别. 图 1 IIC ...
- 【STM32】IIC的基本原理(实例:普通IO口模拟IIC时序读取24C02)(转载)
版权声明:本文为博主原创文章,允许转载,但希望标注转载来源. https://blog.csdn.net/qq_38410730/article/details/80312357 IIC的基本介绍 ...
- IIC通信控制的AD5259------在调试过程中遇到的奇葩问题
首先说一下的遇到的问题: 1.AD5259按照SCL是100KHz的情况下,可以正常接收上位机的数据,但是一段时间后,就不能正确的按照时序来走了 原因在于AD5259在接收到上位机的数据后需要一定的响 ...
- 51单片机下实现软件模拟IIC通信
1.IIC协议简易概述 IIC全称Inter-Integrated Circuit (集成电路总线),是由PHILIPS公司在80年代开发的两线式串行总线,用于连接微控制器及其外围设备.IIC属于半双 ...
- 嵌入式LINUX入门到实践(一)
MINI2440 IIC协议 IIC协议在工程中应用广泛,在我看来,此协议的优势就在于其硬件及其简单,结构清晰. 首先来解读一下S3C2440A这款芯片的IIC协议. 一.一个协议的解读从如上结构图中 ...
- OLED屏幕详细使用
IC扩展-OLED屏的点亮,模拟IIC功能实现C代码点亮OLED屏,只要是可以C编程且有两个GPIO口的单片机均可更改小部分代码使用.OLED屏为像素自发光,其尺寸多为128*64,表示横轴上有128 ...
- 基于STM32F429的ADS1115驱动程序
1.ADS1115中文资料:https://wenku.baidu.com/view/8bab101feef9aef8941ea76e58fafab069dc44e7.html?rec_flag=de ...
随机推荐
- cyyz : Day 1 数论整理
声明:感谢修改这篇博客的dsr Day 1 先说一下上午的听课吧,哎~,简直了,简直(⊙o⊙)…咋说呢,引人入胜???No! 是昏昏欲睡好吧...一点听课欲都没有(强撑....),一上午停下来简直怀疑 ...
- P4899 【[IOI2018] werewolf 狼人】
感觉已经几次碰到这种类型的题目了,写篇\(Blog\)总结一下 题意: 是否存在一条\((s_i, t_i)\)的路径,满足先只走编号不超过\(L_i\)的点,再走编号不超过\(R_i\)的点 \(S ...
- 干货 | 10分钟带你彻底了解column generation(列生成)算法的原理附java代码
OUTLINE 前言 预备知识预警 什么是column generation 相关概念科普 Cutting Stock Problem CG求解Cutting Stock Problem 列生成代码 ...
- CFD-Post批量添加截面
有时候我们需要在一个算例中截取多个面 我们打开CFD-Post 我们编写如下的Python代码来实现在一个算例当中截取多个面 源代码如下: 上述代码完成以后,我们重新打开CFD-Post
- MySQL8.0报错Can't connect to MySQL server on 'localhost' (10061)的解决办法
MySQL8.0报错Can't connect to MySQL server on 'localhost' (10061)的解决办法 事情的起因 今天课堂上要展示小组项目,需要用一个软件叫W ...
- SDN-based Network Management Solution
SDN-based Network Management Solution 摘要: 在此项目中,我们开发了一种网络管理应用程序,以监视和控制由支持OpenFlow的交换机和支持SNMP的设备组成的企业 ...
- SQL优化:一些简单的又实用的SQL优化方案【转】
面试过程中,面试官有极高的频率会问道数据库的优化,SQL语句的优化,网上关于SQL优化的教程很多,但是鱼目混杂,显得有些杂乱不堪.近日有空整理了一下,写出来跟大家分享一下,其中有错误和不足的地方,还请 ...
- TCP的拥塞窗口和快速恢复机制的一些备忘及一点想法
rwnd(窗口,代表接收端的处理能力).cwnd(拥塞窗口,从发送端看当前网络整体承载能力).ssthresh(快速增长切换成慢速增长的界限值) 1.慢启动,是指数增长(对面确认多少个包,就增加多少) ...
- Git push origin dev-rgq-istokenstatus 【dev-rgq-istokenstatus -> dev-rgq-istokenstatus】
RenGuoQiang@PC-RENGUOQIANG MINGW64 /d/zgg/zgg-crm (dev-rgq-istokenstatus) $ git push origin dev-rgq- ...
- ROS tf-增加坐标系
博客参考:https://www.ncnynl.com/archives/201702/1312.html ROS与C++入门教程-tf-增加坐标系 说明: 介绍如何为TF增加额外固定的坐标系 为何增 ...