当前位置: 首页 > wzjs >正文

模板建站代理怎么让百度搜索靠前

模板建站代理,怎么让百度搜索靠前,想在网站卖房怎么做,天翼云虚拟主机I2C总线通信详解-CSDN博客 首先是参考了上述博文的有关iic时序的讲解。 下面是根据正点原子的iic驱动模块的程序结合自己的理解画的时序图,程序中有些计数器对应的时序省略掉了,下面的时序图予以补全。 其次是状态转移图: 其中需要注意的是…

 I2C总线通信详解-CSDN博客

首先是参考了上述博文的有关iic时序的讲解。

    下面是根据正点原子的iic驱动模块的程序结合自己的理解画的时序图,程序中有些计数器对应的时序省略掉了,下面的时序图予以补全。

其次是状态转移图:

其中需要注意的是,当状态机当前状态处于st_data_rd,也就是从机逐位从sda线上读取数据(输入模式)时,是不需要等待从机的ack应答信号的。

以下是组合逻辑对应的状态转换的程序:

/组合逻辑判断状态转移:
//always@(posedge dri_clk or negedge rst_n)为时序逻辑的判断条件
always@(*)beginnext_state = st_idle;case(cur_state)st_idle : beginif(iic_exec)next_state <= st_sladdr;elsenext_state <= st_idle;endst_sladdr :beginif(st_done)beginif(bit_ctrl)next_state <= st_addr16;elsenext_state <= st_addr8;endelsenext_state <= st_sladdr;endst_addr16 :beginif(st_done)next_state <= st_addr8;elsenext_state <= st_addr16;endst_addr8 : beginif(st_done)beginif(wr_flag)next_state <= st_addr_rd;elsenext_state <= st_addr8;endelsenext_state <=st_data_wr;endst_data_wr :beginif(st_done)next_state <= st_stop;elsenext_state <= st_data_wr;endst_addr_rd :beginif(st_done)next_state <= st_data_rd;elsenext_state <= st_addr_rd;endst_data_rd :beginif(st_done)next_state <= st_stop;elsenext_state <= st_data_rd;endst_stop :beginif(st_done)next_state <= st_idle;elsenext_state <= st_stop;enddefault : next_state= st_idle;endcaseend

再次是时钟分频的过程:

因为iic时钟有三种模式,对应的频率分别魏为:mode1:100k;mode2:400k;mode3:3.4M

        一般取mode2快速模式对应的频率,但zynq板载一般为50M时钟,所以需要分频供iic驱动,再者为保证sda输出的数据可以刚好在scl对应的高电平的中间时刻,需要对应的驱动iic的时钟为scl时钟频率的四倍左右。

以下是分频部分对应的程序:

//右移两位表示除以4,模块驱动时钟的分频系数(200->50)
assign  clk_divide = (clk_freq/iic_freq) >> 2'd2;//(clk_divide[8:1])此时是25,因为需要的是50倍,所以需要在25时候翻转
always@(posedge clk or negedge rst_n)beginif(!rst_n)begindri_clk <= 1'b0 ;clk_cnt <= 10'b0; //分频时钟计数器endelse if(clk_cnt == ((clk_divide[8:1])-9'd1)beginclk_cnt <= 10'b0;dri_clk = ~ dri_clk;endelseclk_cnt = clk_cnt + 10'b1;end

最后放上全部的程序:

module  iic_dri
#(
parameter  slave_addr = 7'b10100000,
parameter  clk_freq   = 26'd50_000_000,//mode1:100k;mode2:400k;mode3:3.4M
parameter  iic_freq   = 18'd250_000)
(
input           clk        ,
input           rst_n      ,input           iic_exec,      //触发执行信号
input           bit_ctrl,      //8/16字节控制位
input           iic_rh_wl,     //读写控制位read(1)  write(0)
input  [15:0]   iic_addr,      //器件内地址
input   [7:0]   iic_data_w,    //写入的数据
output  [7:0]   iic_data_r,    //读出的数据 (从机发给主机的数据)
output  reg     iic_done,
output  reg     iic_ack,       //应答位,0表示正确应答
output  reg     scl,
inout           sda,
output  reg     dri_clk       //驱动I2C操作的驱动时钟
//驱动iic_scl的时钟频率一般是scl时钟的4倍
);//状态机切换,各种状态定义
localparam  st_idle     = 8'b0000_0001; //空闲状态
localparam  st_sladdr   = 8'b0000_0010; //发送器件地址(slave address)
localparam  st_addr16   = 8'b0000_0100; //发送16位字地址
localparam  st_addr8    = 8'b0000_1000; //发送8位字地址
localparam  st_data_wr  = 8'b0001_0000; //写数据(8 bit)
localparam  st_addr_rd  = 8'b0010_0000; //发送器件地址读
localparam  st_data_rd  = 8'b0100_0000; //读数据(8 bit)
localparam  st_stop     = 8'b1000_0000; //结束I2C操作//在I2C通信中,SDA线的方向需要根据通信状态动态切换。
//写操作时,SDA线配置为输出模式;读操作时,SDA线配置为输入模式。reg            sda_dir   ; //I2C数据(SDA)方向控制
reg            sda_out   ; //SDA输出信号
reg            st_done   ; //状态结束
reg            wr_flag   ; //写标志
reg    [ 6:0]  cnt       ; //计数
reg    [ 7:0]  cur_state ; //状态机当前状态
reg    [ 7:0]  next_state; //状态机下一状态
reg    [15:0]  addr_t    ; //器件内寄存器地址
reg    [ 7:0]  data_r    ; //读取的数据
reg    [ 7:0]  data_wr_t ; //I2C需写的数据的临时寄存
reg    [ 9:0]  clk_cnt   ; //分频时钟计数//wire define
wire          sda_in     ; //SDA输入信号(数据)
wire   [8:0]  clk_divide ; //模块驱动时钟的分频系数//(sda_dir,是判断条件,确定sda是输出还是输入模式)
assign  sda = sda_dir ? sda_out : 1'bz;
assign  sda_in  = sda ;                          //SDA数据输入(主设备释放总线后)
assign  clk_divide = (clk_freq/iic_freq) >> 2'd2;//模块驱动时钟的分频系数(200->50)//(clk_divide[8:1])此时是25,因为需要的是50倍,所以需要在25时候翻转
always@(posedge clk or negedge rst_n)beginif(!rst_n)begindri_clk <= 1'b0 ;clk_cnt <= 10'b0; //分频时钟计数器endelse if(clk_cnt == ((clk_divide[8:1])-9'd1)beginclk_cnt <= 10'b0;dri_clk = ~ dri_clk;endelseclk_cnt = clk_cnt + 10'b1;end//状态转换 同步时钟
always@(posedge dri_clk or negedge rst_n)beginif(!rst_n)cur_state <= st_idle;else cur_state <= next_state;end//组合逻辑判断状态转移:
//always@(posedge dri_clk or negedge rst_n)为时序逻辑的判断条件
always@(*)beginnext_state = st_idle;case(cur_state)st_idle : beginif(iic_exec)next_state <= st_sladdr;elsenext_state <= st_idle;endst_sladdr :beginif(st_done)beginif(bit_ctrl)next_state <= st_addr16;elsenext_state <= st_addr8;endelsenext_state <= st_sladdr;endst_addr16 :beginif(st_done)next_state <= st_addr8;elsenext_state <= st_addr16;endst_addr8 : beginif(st_done)beginif(wr_flag)next_state <= st_addr_rd;elsenext_state <= st_addr8;endelsenext_state <=st_data_wr;endst_data_wr :beginif(st_done)next_state <= st_stop;elsenext_state <= st_data_wr;endst_addr_rd :beginif(st_done)next_state <= st_data_rd;elsenext_state <= st_addr_rd;endst_data_rd :beginif(st_done)next_state <= st_stop;elsenext_state <= st_data_rd;endst_stop :beginif(st_done)next_state <= st_idle;elsenext_state <= st_stop;enddefault : next_state= st_idle;endcaseend//时序逻辑表示状态输出:
always@(posedge dri_clk or negedge rst_n)beginif(!rst_n)beginsda_dir <= 1'b1;sda_out <= 1'b1;scl     <= 1'b1;iic_done   <= 1'b0;iic_data_r <= 1'b0;iic_ack    <= 1'b0;st_done    <= 1'b0;cnt        <= 1'b0;addr_t     <= 1'b0;//初始化为 0,表示尚未设置目标地址。在 I2C 写操作中,目标地址会存储到 addr_t。data_r     <= 1'b0;data_wr_t  <= 1'b0;wr_flag    <= 1'b0;//read(1) write(0),读写判断endelsebegin//状态切换和计数器除了在特定状态被打断其他时刻都在切换和计数st_done <= 1'b0 ;cnt     <= cnt + 7'b1 ; case(cur_state)st_idle :beginsda_dir <= 1'b1;sda_out <= 1'b1;scl     <= 1'b1; i2c_done<= 1'b0;                     cnt     <= 7'b0;if(iic_exec)beginwr_flag   <= iic_rh_wl;addr_t    <= iic_addr;//器件内地址的寄存器data_wr_t <=iic_data_w;endendst_sladdr :begincase(cnt)7'd1 : sda_out <=1'b0;//7'd2 : sda_out <=1'b0;7'd3 : scl     <=1'b0;//scl,高时,sda,由高变低(start)7'd4 : sda_out <=SLAVE_ADDR[6]; //7'd5 : scl     <=1'b0;7'd6 : scl     <=1'b1;7'd7 : scl     <=1'b0; 7'd8 : sda_out <=SLAVE_ADDR[5];    7'd9 : scl     <=1'b1;//7'd10 : scl    <=1'b1;7'd11 : scl    <=1'b0;7'd12 : sda_out<=SLAVE_ADDR[4];                7'd13 : scl    <=1'b1;//7'd14 : scl    <=1'b1;7'd15 : scl    <=1'b0;7'd16 : sda_out<=SLAVE_ADDR[3];              7'd17 : scl    <=1'b1;//7'd18 : scl    <=1'b1; 7'd19 : scl    <=1'b0;7'd20 : sda_out<=SLAVE_ADDR[2];             7'd21 : scl    <=1'b1;//7'd22 : scl    <=1'b1;  7'd23 : scl    <=1'b0;7'd24 : sda_out<=SLAVE_ADDR[1];             7'd25 : scl    <=1'b1;s//7'd26 : scl    <=1'b1; 7'd27 : scl    <=1'b0;7'd28 : sda_out<=SLAVE_ADDR[0];               7'd29 : scl    <=1'b1;//7'd30 : scl    <=1'b1; 7'd31 : scl    <=1'b0;7'd32 : sda_out<=1'b0;  //0:写            7'd33 : scl    <=1'b1;  //此时写操作标志失效  r/w 读写控制位 //7'd34 : scl    <=1'b1; 7'd35 : scl    <=1'b0;  7'd36 : sda_dir <= 1'b0;  //将 SDA 设置为输入模式sda_out <= 1'b1;  //释放总线7'd37 : scl    <=1'b1; //此时从机可以在scl高电平发送信号7'd38 : beginst_done <= 1'b1;if(sda_in == 1'b1)  //高电平表示从机未应答iic_ack <=1'b1;end 7'd39 : beginscl  <=1'b0;cnt  <=7'd0;enddefault: ;  //无默认值,表示空操作endcaseend//sda_dir 为高电平时为输出模式,主设备控制,为低电平时为输入模式    st_addr16: begincase(cnt)7'd0 :begin                     sda_dir <= 1'b1 ;            sda_out <= addr_t[15];       //传送字地址end//在 I2C 通信中,scl 是时钟线,用于同步数据的传输。//每个数据位的传输都需要一个完整的时钟周期,//即 scl 从低电平到高电平再回到低电平的过程。7'b1 : scl <=1'b1;//7'd2 : scl <=1'b1;7'd3 : scl <=1'b0;7'd4 : sda_out <=addr_t[14];              7'd5 : scl     <=1'b1;//7'd6 : scl     <=1'b1;7'd7 : scl     <=1'b0; 7'd8 : sda_out <=addr_t[13];               7'd9 : scl     <=1'b1;//7'd10 : scl     <=1'b1;7'd11 : scl     <=1'b0;7'd12 : sda_out <=addr_t[12];7'd13 : scl     <=1'b1;//7'd14 : scl     <=1'b1;7'd15 : scl     <=1'b0;7'd16 : sda_out <=addr_t[11];7'd17 : scl     <=1'b1;7'd18 : scl     <=1'b1;7'd19 : scl     <=1'b0;7'd20 : sda_out <=addr_t[10];7'd21 : scl     <=1'b1;//7'd22 : scl     <=1'b1;7'd23 : scl     <=1'b0;7'd24 : sda_out  <=addr_t[9];7'd25 : scl     <=1'b1;//7'd26 : scl     <=1'b1;7'd27 : scl     <=1'b0;7'd28 : sda_out   <=addr_t[8];7'd29 : scl     <=1'b1;//7'd30 : scl     <=1'b1;7'd31 : scl     <=1'b0;   //在scl结束一个周期之后7'd32 : beginsda_dir <= 1'b0;  //释放总线,等待从设备应答信号sda_out <= 1'b1;  //上拉,避免主从设备通信冲突end7'd33 : scl     <=1'b1;7'd34 : beginst_done <=1'b1;if(sda_in == 1'b1)  //高电平表示从机未应答iic_ack <=1'b1;end7'd35 : beginscl <=1'b0;cnt <=1'b0;enddefault : ;endcaseendst_addr8 : begincase(cnt)7'd0 : beginsda_dir <=1'b1;//将总线设为输出模式sda_out <=addr_t[7];//保证在sdl被拉高时可以稳定传输end7'd1 :scl <= 1'b1;//7'd2 :scl <= 1'b1;7'd3 :scl <= 1'b0;7'd4 :sda_out <= addr_t[6];7'd5 :scl <= 1'b1;//7'd6 :scl <= 1'b1;7'd7 :scl <= 1'b0;7'd8 :sda_out <= addr_t[5];7'd9 :scl <= 1'b1;//7'd10 :scl <= 1'b1;7'd11 :scl <= 1'b0;7'd12 :sda_out <= addr_t[4];7'd13 :scl <= 1'b1;//7'd14 :scl <= 1'b1;7'd15 :scl <= 1'b0;7'd16 :sda_out <= addr_t[3];7'd17 :scl <= 1'b1;//7'd18 :scl <= 1'b1;7'd19 :scl <= 1'b0;7'd20 :sda_out <= addr_t[2];7'd21 :scl <= 1'b1;//7'd22 :scl <= 1'b1;7'd23 :scl <= 1'b0;7'd24 :sda_out <= addr_t[1];7'd25 :scl <= 1'b1;//7'd26 :scl <= 1'b1;7'd27 :scl <= 1'b0;7'd28 :sda_out <= addr_t[0];7'd29 :scl <= 1'b1;//7'd30 :scl <= 1'b1;7'd31 :scl <= 1'b0;//在scl结束一个周期之后7'd32 :beginsda_dir <=1'b0;sda_out <=1'b1;end7'd33 :scl <= 1'b1;7'd34 :beginst_done <=1'b1;if(sda_in == 1'b1)//从机正常应答会将sda总线拉低iic_ack <= 1'b1;//高电平表示从机未应答end7'd35 :beginscl <= 1'b0;cnt <= 1'b0;enddefault : ;endcaseend//写数据需要主设备控制sda线,也就需要设为输出模式         st_data_wr :begincase(cnt)7'd0 : beginsda_dir <=1'b1;sda_out <=data_wr_t[7];end 7'd1 : scl <=1'b1;//7'd2 : scl <=1'b1;7'd3 : scl <=1'b0;7'd4 : sda_out <=data_wr_t[6];7'd5 : scl <=1'b1;//7'd6 : scl <=1'b1;7'd7 : scl <=1'b0;7'd8 : sda_out <=data_wr_t[5];7'd9 : scl <=1'b1;//7'd10 : scl <=1'b1;7'd11 : scl <=1'b0;7'd12 : sda_out <=data_wr_t[4];7'd13 : scl <=1'b1;//7'd14 : scl <=1'b1;7'd15 : scl <=1'b0;7'd16 : sda_out <=data_wr_t[3];7'd17 : scl <=1'b1;//7'd18 : scl <=1'b1;7'd19 : scl <=1'b0;7'd20 : sda_out <=data_wr_t[2];7'd21 : scl <=1'b1;//7'd22 : scl <=1'b1;7'd23 : scl <=1'b0;7'd24 : sda_out <=data_wr_t[1];7'd25 : scl <=1'b1;//7'd26 : scl <=1'b1;7'd27 : scl <=1'b0;7'd28 : sda_out <=data_wr_t[0];7'd29 : scl <=1'b1;//7'd30 : scl <=1'b1;7'd31 : scl <=1'b0;7'd32 : beginsda_dir <= 1'b0;sda_out <= 1'b1;//释放总线,拉高sda等待从机应答end7'd33 : scl <=1'b1; //需要确定在scl高电平时采样,等待从机应答信号7'd34 : beginst_done <= 1'b1;if(sda_in == 1'b1)iic_ack <=1'b1;end7'd35 : beginscl <=1'b0;cnt <=1'b0;enddefault : ;endcaseendst_addr_rd : begincase(cnt)7'd1 : scl <=1'b1;//7'd2 : scl <=1'b1;7'd3 : scl <=1'b0;7'd4 : sda_out <=SLAVE_ADDR[6];7'd5 : scl <=1'b1;//7'd6 : scl <=1'b1;7'd7 : scl <=1'b0;7'd8 : sda_out <=SLAVE_ADDR[5];7'd9 : scl <=1'b1;//7'd10 : scl <=1'b1;7'd11 : scl <=1'b0;7'd12 : sda_out <=SLAVE_ADDR[4];7'd13 : scl <=1'b1;//7'd14 : scl <=1'b1;7'd15 : scl <=1'b0;7'd16 : sda_out <=SLAVE_ADDR[3];7'd17 : scl <=1'b1;//7'd18 : scl <=1'b1;7'd19 : scl <=1'b0;7'd20 : sda_out <=SLAVE_ADDR[2];7'd21 : scl <=1'b1;//7'd22 : scl <=1'b1;7'd23 : scl <=1'b0;7'd24 : sda_out <=SLAVE_ADDR[1];7'd25 : scl <=1'b1;//7'd26 : scl <=1'b1;7'd27 : scl <=1'b0;7'd28 : sda_out <=SLAVE_ADDR[0];7'd29 : scl <=1'b1;//7'd30 : scl <=1'b1;7'd31 : scl <=1'b0;7'd32 : sda_out <=1'b1;//主机控制,输出模式,读从机发的地址7'd33 : scl <=1'b1;//7'd34 : scl <=1'b1;7'd35 : scl <=1'b0;7'd36 : beginsda_dir <= 1'b0;            sda_out <= 1'b1;end7'd37 : scl <=1'b1;7'd38 :beginst_done <= 1'b1;if(sda_in == 1'b1)  //sda,释放总线后等待从机应答信号iic_ack <= 1'b1;end7'd39 : beginscl <= 1'b0;cnt <= 1'b0; end default : ;endcaseendst_data_rd :begincase(cnt)//data_r,用于逐位从sda线上读取数据7'd0 : sda_dir <= 1'b0; //从机控制在scl,上升沿写入数据到sda7'd1 : begindata_r[7] <=sda_in;scl <=1'b1;end7'd2 : scl <=1'b1;7'd3 : scl <=1'b0;7'd4 : sda_out <=SLAVE_ADDR[6];7'd5 : begindata_r[6] <=sda_in;scl <=1'b1;end7'd6 : scl <=1'b1;7'd7 : scl <=1'b0;7'd8 : sda_out <=SLAVE_ADDR[5];7'd9 : begindata_r[5] <=sda_in;scl <=1'b1;end7'd10 : scl <=1'b1;7'd11 : scl <=1'b0;7'd12 : sda_out <=SLAVE_ADDR[4];7'd13 : begindata_r[4] <=sda_in;scl <=1'b1;end7'd14 : scl <=1'b1;7'd15 : scl <=1'b0;7'd16 : sda_out <=SLAVE_ADDR[3];7'd17 : begindata_r[3] <=sda_in;scl <=1'b1;end7'd18 : scl <=1'b1;7'd19 : scl <=1'b0;7'd20 : sda_out <=SLAVE_ADDR[2];7'd21 : begindata_r[2] <=sda_in;scl <=1'b1;end7'd22 : scl <=1'b1;7'd23 : scl <=1'b0;7'd24 : sda_out <=SLAVE_ADDR[1];7'd25 : begindata_r[1] <=sda_in;scl <=1'b1;end7'd26 : scl <=1'b1;7'd27 : scl <=1'b0;7'd28 : sda_out <=SLAVE_ADDR[0];7'd29 : begindata_r[0] <=sda_in;scl <=1'b1;end7'd30 : scl <=1'b1;7'd31 : scl <=1'b0;7'd32 : beginsda_dir <= 1'b1;  //主机输出模式         sda_out <= 1'b1;end7'd33 : scl <=1'b1;//延后一个时刻确保从机在上升沿采样完成,避免主从机产生冲突7'd34 : st_done <=1'b1;7'd35 : beginscl <=1'b0;cnt <= 7'b0;i2c_data_r <= data_r; //将读到的数据发送给主机enddefault : ;endcaseendst_stop : begincase(cnt)7'd0 : beginscl <=1'b1;sda_out <= 1'b0;end7'd1 : scl <=1'b1;7'd2 : scl <=1'b1;7'd3 : sda_out <=1'b1; //stop标志7'd15 : st_done <= 1'b1;7'd16 :begincnt      <= 7'b0;i2c_done <= 1'b1; enddefault : ;endcaseendendcase end             end
endmodule  

        程序中对应的每个状态都有注释讲解, 但还有几个地方需要注意,sda在输入时是在scl的上升沿采样,为了保证sda在scl的每个高电平期间可以稳定的传输数据,而在给sda_out赋值的时候则是需要在scl稳定的低电平期间,也就是时序图中sda_out的上升沿和下降沿切换的时候。

 

http://www.dtcms.com/wzjs/225083.html

相关文章:

  • 重庆网站设计案例最佳搜索引擎磁力王
  • 做网站入门最新新闻摘抄
  • 绍兴中交水利水电建设有限公司网站网络推广优化培训
  • 成套小说网站模板百度账号是什么
  • 苏州前程无忧官上做网站seo搜索引擎是什么意思
  • 一个人做网站用什么技术网店推广渠道有哪些
  • 哪做网站广州番禺发布
  • 网站模板用什么做google官网登录
  • 手机网站制作价格佛山网站建设制作公司
  • 5000人朋友圈推广多少钱网站关键词排名怎么优化
  • 公司网站可以自己做百度指数查询手机版app
  • 网站运营队伍与渠道建设官方进一步优化
  • 江苏体育建设场地网站互联网营销师是干什么
  • 提供手机网站建设软件注册推广平台
  • 网站建设与维护毕业论文百度网首页官网登录
  • 深圳网站设计深圳网站建设网站排名优化技巧
  • 做网站推广那家好佛山本地网站建设
  • 济南做网站公司郑州网站技术顾问
  • 网站的优点有哪些方面百度排名优化
  • 家教补习中心网站建设百度快速收录软件
  • 项城注册公司代办公司湖南长沙seo
  • 长沙做网站最好的公司广州搜发网络科技有限公司
  • 前端兼职接单平台广告优化师怎么学
  • 南京网站群建设公司重庆森林讲了什么故事
  • 网站如何添加代码石家庄头条今日头条新闻
  • 环球资源网站网址湖南网站建设效果
  • 淘宝网站建设方案个人网站seo入门
  • 小伙做网色网站网站推广苏州
  • 个人网站制作教程视频百度竞价是什么意思?
  • 怎么样在网站上做跳转免费接单平台