7113|14

325

帖子

0

TA的资源

裸片初长成(初级)

楼主
 

请教关于IIC接口 [复制链接]

这两天用VHDL语言编写了一个IIC控制程序,读写EEPROM AT24C02,读写时序是满足AT24C02和IIC规范的,但是始终读不出来正确的数据,下面是我的读写时序图,希望做过的朋友指点一下!
注:只有WR=1时sda<=sdat;

IIC写.jpg (38.93 KB, 下载次数: 2)

IIC写时序图

IIC写时序图

IIC读.jpg (46.56 KB, 下载次数: 0)

IIC读时序图

IIC读时序图
此帖出自FPGA/CPLD论坛

最新回复

我看你的代码,好像没有考虑I2C总线的建立时间、保持时间啊。我的邮箱  minbiao880224@126.com,可以交流! [ 本帖最后由 go_ahead001 于 2010-5-1 01:04 编辑 ]  详情 回复 发表于 2010-5-1 00:57
点赞 关注
个人签名科技应该让生活变得更简单!
 

回复
举报

50

帖子

0

TA的资源

一粒金砂(高级)

沙发
 
似乎这个时序图里面没有体现出主从的交互,就是缺少ack信号吧。

就要去判断ack才能做出相应的处理。
此帖出自FPGA/CPLD论坛
 
 

回复

325

帖子

0

TA的资源

裸片初长成(初级)

板凳
 

回复 沙发 analog010 的帖子

当wr='0'时就是判断ACK信号,此时SDAOUT是高阻态,如果有ACK才进入下一状态,否则回到IDLE。
此帖出自FPGA/CPLD论坛
个人签名科技应该让生活变得更简单!
 
 
 

回复

127

帖子

0

TA的资源

五彩晶圆(中级)

4
 
那就是有ACK信号了,嗯,不知道是什么问题啊?
此帖出自FPGA/CPLD论坛
 
 
 

回复

325

帖子

0

TA的资源

裸片初长成(初级)

5
 

回复 4楼 jyl 的帖子

恩,就是不知道问题呀,急得很
此帖出自FPGA/CPLD论坛
个人签名科技应该让生活变得更简单!
 
 
 

回复

63

帖子

0

TA的资源

纯净的硅(高级)

6
 
不熟  楼主的时序图是用什么抓出来的啊?嘿嘿!我记得IIC在释放了总线的时候两跟线都是高电平哟,
此帖出自FPGA/CPLD论坛
 
 
 

回复

130

帖子

0

TA的资源

纯净的硅(中级)

7
 
关注。。
此帖出自FPGA/CPLD论坛
个人签名就这样看着你慢慢离去.......
 
 
 

回复

325

帖子

0

TA的资源

裸片初长成(初级)

8
 

回复 6楼 59590051 的帖子

恩,是用signaltap2抓取的,测试程序写的是连续读一个地址的数取,所以没有释放总线。
此帖出自FPGA/CPLD论坛
个人签名科技应该让生活变得更简单!
 
 
 

回复

16

帖子

0

TA的资源

一粒金砂(高级)

9
 
关注。。
此帖出自FPGA/CPLD论坛
 
 
 

回复

325

帖子

0

TA的资源

裸片初长成(初级)

10
 

回复 9楼 fengxiaoyu 的帖子

今天用单片机私心数据写进去,然后用FPGA读出来,发现读出来数据是对的(也有个奇怪的现象,就是只有奇地址的才能读出数据来?),只是写不进去,现在重点关注写程序部分
此帖出自FPGA/CPLD论坛
个人签名科技应该让生活变得更简单!
 
 
 

回复

103

帖子

0

TA的资源

五彩晶圆(初级)

11
 
:D 把代码发上来吧! 单片机内部带有错误帧分析,自动锁相,所以不容易出错。写数据的时候,先找到地址,然后再发送数据,再得到ACK信号。如果两根线不满足,自己多加一个CS选通端,一起控制。
此帖出自FPGA/CPLD论坛

赞赏

1

查看全部赞赏

个人签名FPGA遥远的事情,我现在在画PCB
 
 
 

回复

325

帖子

0

TA的资源

裸片初长成(初级)

12
 

回复 11楼 sadlife1000 的帖子

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity iic is
port(
     reset:in std_logic;         --system reset
     clk  :in std_logic;         
    datain:in std_logic_vector(7 downto 0);  --data or control datain;
   bit_cmd:in std_logic;                     --work begin or go on command ;
    rd_wr: in std_logic;                     --rd or wr ;
   
   dataout:out std_logic_vector(7 downto 0); --receive data;
  cmd_done:out std_logic;                    --datatransfer done;
      nop :out std_logic;                    --current state is nop;
       sda:inout std_logic;                  --data wire
       scl:out std_logic);                   --clock wire;
  end entity iic;
  
  architecture rtl of iic is

  signal in_reg:std_logic_vector(7 downto 0);  --dataout tmp;
  signal out_reg:std_logic_vector(7 downto 0); --datain  tmp;
  signal sdat:std_logic;
  signal wr    :std_logic;
  signal r_w   :std_logic;
  signal rd    :integer range 0 to 2;
  signal clkcnt:std_logic_vector(1 downto 0);  
  signal clkdiv:std_logic:='1';

  
  type state is(idle,start,wr_ad,wr_dd,rd_dd,stop);
  signal now_state,next_state:state;
  signal datacnt:integer range 1 to 9;
  begin
  
  process(clk,reset)
     begin
       if reset='0' then
              clkcnt<="00";
              clkdiv<='1';
        elsif clk'event and clk='1' then
                 if clkcnt="11" then
                    clkcnt<="00";
                  else
                    clkcnt<=clkcnt+1;
                   end if;
                   if clkcnt="01" or clkcnt="11" then
                    clkdiv<=not clkdiv;
                    end if;
          end if;
    end process;
  process(clk,reset)  --this process deals with state transfer;
      begin
         if reset='0' then
               next_state<=idle;
              
         elsif clk'event and clk='1' then
                case now_state is
                       when idle=> if clkcnt="01" then
                                      if bit_cmd='1' then
                                        next_state<=start;
                                        r_w<=rd_wr;
                                        end if;
                                     end if;
                                     rd<=0;
                                    
                       when start=> if clkcnt="01" then
                                       next_state<=wr_ad;
                                       end if;
                                       datacnt<=1;
                       when wr_ad=>  
                                     if datacnt=9 then
                                         if clkcnt="01" then
                                          if sda='1' then
                                              next_state<=idle;
                                            elsif r_w='0' then
                                              next_state<=wr_dd;
                                            elsif rd=2 then  next_state<=rd_dd;
                                             elsif rd=1 then next_state<=start;
                                                  rd<=rd+1;
                                            else rd<=rd+1;      
                                              end if;
                                              datacnt<=1;
                                          end if;
                                      elsif clkcnt="01" then
                                           datacnt<=datacnt+1;
                                      end if;
                         when wr_dd=>
                                      if datacnt=9 then
                                              if clkcnt="01" then
                                                if sda='1' then
                                                  next_state<=idle;
                                                 elsif bit_cmd='0' then
                                                  next_state<=stop;
                                                 end if;
                                                datacnt<=1;
                                               end if;
                                             
                                        elsif clkcnt="01" then
                                         datacnt<=datacnt+1;
                                       end if;
                                       
                         when rd_dd=>  if clkcnt="01" then
                                        if datacnt=9 then
                                             datacnt<=1;
                                             next_state<=stop;
                                        else datacnt<=datacnt+1;
                                        end if;
                                        end if;
                         when stop=>   if clkcnt="01" then
                                              next_state<=idle;
                                              else
                                                datacnt<=1;
                                                end if;
                                                rd<=0;
                           end case;
                  end if;
                  end process;
                  
          process(clk,reset)      -- this process deals with data transfer or receive;
                begin
                  if reset='0' then
                       sdat<='1';
                       wr<='1';
                  elsif clk'event and clk='1' then
                          case now_state is
                                     when idle=> wr<='0';
                                                 sdat<='1';
                                     when start=>if clkcnt="00" then
                                                   
                                                   if rd=0 then
                                                   cmd_done<='1';
                                                   in_reg<=datain;
                                                   end if;
                                                  elsif clkcnt="01" then
                                                    cmd_done<='0';
                                                    sdat<='0';
                                                   
                                                 end if;
                                                 wr<='1';
                                     when wr_ad=>if clkcnt="11" then
                                                    if datacnt<9 then
                                                    sdat<=in_reg(8-datacnt);
                                                    wr<='1';
                                                    else
                                                    in_reg<=datain;
                                                    cmd_done<='1';
                                                    wr<='0';
                                                    end if;
                                                  elsif clkcnt="01" then
                                                     if datacnt=9 then
                                                     end if;
                                                  else cmd_done<='0';
                                                  
                                                 end if;
                                                 out_reg<=(others=>'1');
                          
                                      when wr_dd=>
                                                     if clkcnt="11" then
                                                          if datacnt<9 then
                                                            sdat<=in_reg(8-datacnt);
                                                            wr<='1';
                                                          else
                                                           in_reg<=datain;
                                                           cmd_done<='1';
                                                           wr<='0';
                                                           end if;
                                                     elsif clkcnt="01" then
                                                          if datacnt=9 then
                                                          sdat<='0';
                                                          end if;
                                                     else cmd_done<='0';
                                                         
                                                     end if;
                                            
                                    when rd_dd=>    if clkcnt="01" then
                                                         if datacnt<9 then
                                                           out_reg(8-datacnt)<=sda;      
                                                         else
                                                           dataout<=out_reg;
                                                           cmd_done<='1';
                                                         end if;
                                                    else cmd_done<='0';
                                                    wr<='0';
                                                    end if;
                                                    sdat<='1';
                                                   
                                    when stop=>      cmd_done<='0';
                                                   
                                                     wr<='1';
                                                     if clkcnt="01" then
                                                           sdat<='1';
                                                            
                                                     end if;  
                                    end case;   
                  end if;
                  end process;
              process(clk,reset)      --this process deals with now_state<=next_state;
                    begin
                if reset='0' then
                   now_state<=idle;
                  elsif clk'event and clk='1' then
                     now_state<=next_state;
                   end if;
              end process;
              
           sda<=sdat when wr='1' else 'Z';   --this control the tri_state inout data wire;
           
              process(clk,sda)
                    begin
                    if clk'event and clk='1' then
                          if now_state=idle then
                                 scl<='1';
                          else scl<=clkdiv;
                          end if;
                     end if;
                end process;                  -- this control the scl;
              process(clk,reset)              --this process show the isbusy?
                    begin
                     if reset='0' then
                        nop<='1';
                     elsif clk'event and clk='1' then
                           if now_state=idle then
                               nop<='1';
                           else nop<='0';
                           end if;
                     end if;
                end process;
           end rtl;   
                                                      
         我把代码发上来,呵呵,现在经测试可以实现读写EEPROM了,支持多种连续读和单地址读等多种模式,希望大家指正。
     另外这个程序只是IIC主设备的程序,现在正在写从设备程序,发现从设备程序比主设备程序要麻烦,如果遇到问题,还会继续请教大家的!
此帖出自FPGA/CPLD论坛
个人签名科技应该让生活变得更简单!
 
 
 

回复

103

帖子

0

TA的资源

五彩晶圆(初级)

13
 
:D 不错哦的!
此帖出自FPGA/CPLD论坛
个人签名FPGA遥远的事情,我现在在画PCB
 
 
 

回复

10

帖子

0

TA的资源

一粒金砂(初级)

14
 
关注~~
此帖出自FPGA/CPLD论坛
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

15
 

确定时需满足要求吗?

我看你的代码,好像没有考虑I2C总线的建立时间、保持时间啊。我的邮箱  minbiao880224@126.com,可以交流!

[ 本帖最后由 go_ahead001 于 2010-5-1 01:04 编辑 ]
此帖出自FPGA/CPLD论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/6 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表