原创 fpga学习日记24,代码阅读之实现IIC

2013-9-5 08:09 2758 17 19 分类: FPGA/CPLD 文集: 数电,FPGA学习

(注:如果本文有代码 则均搜索于网络或本人编写仅供学习交流之用)

本文主要学习iic读写24cxx的编程方法和思想

本文建立在前面五篇日记的基础上

fpga学习日记14,实现UART发送

fpga学习日记15,实现IIC通信

fpga学习日记20,状态机 任务和并行设计思想

fpga学习日记22,代码阅读之实现UART

fpga学习日记23,代码阅读之UART时序分析

 

因为iic在通信程序设计上和uart有很大程度的类似

在日记15中已经详细描述了IIC的通信规范和协议以及24CXX的操作知识

这里再回顾下像这种串行通信的设计思路

  1. 首先还是时钟问题  通信时钟和数据收发辅助时钟
  2. 程序结构问题       状态机,并行执行和任务
  3. 收发器状态位的问题   忙检测 出错标志 收发标志位等

 

下面依次分析以上三个部分

1首先还是时钟问题

为了在SCL低电平的中点改变SDA上的数据 我们需要将IIC的时钟2倍或4倍频下以获取辅助时钟来监测SCL的中点

同时辅助时钟还可以在接受中判断scl高电平中点时刻来获取sda线上的数据 这点和uart的思想是一样的

先看下2倍频的例子

always @ (posedge clk or negedge rst_n)
   if(!rst_n) cnt_delay <= 9'd0;
   else if(cnt_delay == 9'd499) cnt_delay <= 9'd0;    //计数到10us为scl的周期,即100KHz
   else cnt_delay <= cnt_delay+1'b1;    //时钟计数

   always @ (posedge clk or negedge rst_n) begin      //将IIC时钟分成四份-2倍频以产生辅助时钟
   if(!rst_n) cnt <= 3'd5;
   else begin
       case (cnt_delay)
           9'd124:    cnt <= 3'd1;    //cnt=1:scl高电平中间,用于数据采样
           9'd249:    cnt <= 3'd2;    //cnt=2:scl下降沿
           9'd374:    cnt <= 3'd3;    //cnt=3:scl低电平中间,用于数据变化
           9'd499:    cnt <= 3'd0;    //cnt=0:scl上升沿
           default: cnt <= 3'd5;
           endcase
       end
end

 

下面是4倍频的例子

always @(posedge sys_clk or negedge sys_rst_n) begin
       if (sys_rst_n ==1'b0)  
           clk_50k <= 10'b0;
       else  if ((counter_div >= 375) && (counter_div < 875))    
           clk_50k <= 10'b1;
       else
           clk_50k <= 10'b0;
end
// gen a 200K CLK for work counter count
always @(posedge sys_clk or negedge sys_rst_n) begin
       if (sys_rst_n ==1'b0)  
           clk_200k <= 10'b0;
       else  if ((counter_div >= 0  ) && (counter_div < 125))
           clk_200k <= 10'b0;
       else  if ((counter_div >= 125) && (counter_div < 250))
           clk_200k <= 10'b1;  
       else  if ((counter_div >= 250) && (counter_div < 375))
           clk_200k <= 10'b0;                        
       else  if ((counter_div >= 375) && (counter_div < 500))
           clk_200k <= 10'b1;
       else  if ((counter_div >= 500) && (counter_div < 625))
           clk_200k <= 10'b0;
       else  if ((counter_div >= 625) && (counter_div < 750))
           clk_200k <= 10'b1;  
       else  if ((counter_div >= 750) && (counter_div < 875))
           clk_200k <= 10'b0;                        
       else  if ((counter_div >= 875) && (counter_div < 1000))
           clk_200k <= 10'b1;    
       else ;
end

 

2程序结构问题(在此基础上在状态机中添加读数据即可)

 

Module  eeprom_w

//输入输出定义

//变量定义

//参数定义

 

Assign SDA=(out_***==1)? Sda_buf[7]  :1’bz;        //控制IIC数据线接收发送

 

Initial

Begin

    //参数初始化

End

 

Always @(negedge sys_clk) //iic产生时钟

If(复位)

    Scl<=0;

Else

    Scl=~scl;

 

Always @scl下降沿)

     如果复位 初始化某些参数

否则begin

    Casex(main_state)  //状态机

      状态1      空闲 准备跳入下一个状态

      状态2      发开始信号  (调用任务)  准备跳入下一个状态 

      状态3     发设备地址(调用任务)   准备跳入下一个状态

      状态4     发数据地址(调用任务)   准备跳入下一个状态

      状态5    发数据(调用任务)       准备跳入下一个状态

      状态6     发停止信号  (调用任务)  准备跳入下一个状态

      状态7     ACK应答信号(调用任务)准备跳入下一个状态

Default

Endcase

End

 

 

   任务1 发送IIC起始信号(代码实现)

   任务2 8位数据发到IIC总线(代码实现)

   任务3 IIC总线上读取8位数据 (代码实现)

   任务4 发送IIC结束信号(代码实现)

   任务5 发送IIC ack应答信号(代码实现)

 

Endmodule 

 

 也可以直接把任务写在状态机中

3收发器状态位的问题

有时我们还需设计一些状态标志位来表示iic的通信状态

状态标志:
─  发送器/ 接收器模式标志
─  字节发送结束标志
─  IiC 总线忙标志

 错误标志
─   主模式时的仲裁丢失
─   地址/ 数据传输后的应答(ACK) 错误
─   检测到错位的起始或停止条件
─   禁止拉长时钟功能时的上溢或下溢
中断
─  1个中断用于地址/ 数据通讯成功
─  1个中断用于错误

最后附上两个读写eeprom的源代码供讨论学习

 

 

PARTNER CONTENT

文章评论2条评论)

登录后参与讨论

用户1418083 2016-3-23 09:57

不错,支持

用户442006 2015-5-6 16:46

很不错的例子
相关推荐阅读
liang890319_284707880 2016-03-22 11:41
[博客大赛]我在搞嵌入式 我有罪
  我在搞嵌入式 我有罪 做嵌入式也有几年了 刚学习的时候书上说嵌入式的定义是以应用为中心,以计算机技术为基础,软硬件可裁剪,适应应用系统对功能、可靠性、成本、体积、功耗等严格要求的专用计...
liang890319_284707880 2015-10-22 11:57
帕萨特迈腾蒙迪欧哪个好
氵灬清风灬说:太小了,没法穿了,懒得换了 junyao00022说:............................... jd272475byp说:宝贝收到啦,衣服质量非常不错,...
liang890319_284707880 2015-10-22 11:56
二手荣威550和二手起亚k2哪个好
二手荣威550和二手起亚k2哪个好   风之乞说:衣服挺好的,就是偏小,已经更换了 梦里水乡0609说:不错 很好  不了不错  赞 四灵之首说:衣服质量不错,韵达快递不行~ ...
liang890319_284707880 2015-10-22 11:55
澳大利亚深海鱼油哪个牌子好
hgjfhgj说:不错  价格便宜  款式不错  开始买中码小了一点  免费给换的  好店家 小杰c子说:非常合适。也很有气质 天佑945说:还可以,性价比高。。。。。。。。。。 Ab...
liang890319_284707880 2015-10-19 11:03
常用DDR sdram和Flash型号
  以下是代码片段: http://blog.csdn.net/myarrow/article/details/7854863   主要是三星 现代 ...
liang890319_284707880 2013-09-29 17:00
ROM FLASH RAM
EPROM、EEPROM、FLASH的总结性区别   http://xdc0363.blog.163.com/blog/static/11546200220...
EE直播间
更多
我要评论
2
17
关闭 站长推荐上一条 /1 下一条