跳到主要内容

12.4 实验原理

12.4.1 AT24C02芯片介绍

AT24C02是一种带电可擦除可编程只读存储器,采用8-pin DIP和8-pin SOP封装,有2线串行接口,完全兼容I2C总线,管脚功能描述如下。

alt text
管脚功能描述

AT24C02芯片典型电路连接如下:

alt text
典型电路连接

12.4.2 AT24C02芯片连接

STEP BaseBoard V4.0底板上的AT24C02模块电路图如下

alt text
AT24C02芯片电路

上图为数据存储芯片AT24C02模块电路,与FPGA硬件接口有I2C总线(SCL、SDA),AT24C02是美国ATmel公司的低功耗CMOS型E2PROM,内含256*8位存储空间,具有工作电压宽(2.5V~5.5V),擦写次数多(大于10000次),写入速度快(小于10ms),抗干扰能力强,数据不易丢失,体积小等特点。并且它是采用I2C总线式进行数据读写的串行操作,只占用很少的资源和I/O线。AT24C02有一个16字节页写缓冲器,该器件通过I2C总线接口进行操作,还有一个专门的写保护功能。

alt text
AT24C02内部框图

12.4.3 AT24C02驱动设计

通过前面的了解,我们对于整个I2C总线的驱动原理有了一定的了解,接下来我们根据AT24C02的芯片手册了解其驱动方法及参数要点。

alt text
AT24C02时序图
alt text
AT24C02时序参数

通过AT24C02时序参数了解,AT24C02支持I2C通信400KHz快速模式的同时兼容100KHz的标准模式,还有两种模式下时序中的各种时间参数,所以通信速度不需要调整。

  • 分频得到400KHz的时钟,程序实现同智能接近系统设计实验。

I2C时序基本单元(启动、停止、发送、接收、发应答、读应答)协议里统一的,所以所以基本单元状态的设计也是不需要调整的。

-启动时序状态设计程序实现同智能接近系统设计实验。 -发送单元和读应答单元合并,时序状态设计程序实现同智能接近系统设计实验。 -接收单元和写应答单元合并,时序状态设计程序实现同智能接近系统设计实验。 -停止时序状态设计程序实现同智能接近系统设计实验。

各型号芯片器件地址如下,最后一位用于区分读写

alt text
器件地址

对于写操作而言,分为两种,字节写和页写,本实验采用了字节写;对于读操作而言,则有当前地址读,随机读,顺序读三种,本实验采用了随机读方式完成。

字节写操作时序流程如下:

alt text
字节写

我们将这种操作设计成一个一个状态,程序实现如下:

MODE1:begin //单次写操作 
      if(cnt_mode1 >= 3'd5) 
      cnt_mode1 <= 1'b0; //对START中的子状态执行控制cnt_start
      else cnt_mode1 <= cnt_mode1 + 1'b1;
      state_back <= MODE1;
      case(cnt_mode1)
       3'd0: begin state <= START; end //I2C通信时序中的START
       3'd1: begin data_wr <= dev_addr; state <= WRITE; end //设备地址
       3'd2: begin data_wr <= reg_addr; state <= WRITE; end //寄存器地址
       3'd3: begin data_wr <= `WRITE_DATA; state <= WRITE; end //写入数据
       3'd4: begin state <= STOP; end //I2C通信时序中的STOP
       3'd5: begin state <= MAIN; end //返回MAIN
       default: state <= IDLE; //如果程序失控,进入IDLE自复位状态
endcase

随机读操作时序流程如下:

alt text
随机读

同理,程序实现如下

MODE2:begin //随机读操作
if(cnt_mode2 >= 4'd8)
cnt_mode2 <= 1'b0; //对START中的子状态执行控制cnt_start
else
cnt_mode2 <= cnt_mode2 + 1'b1;
state_back <= MODE2;
case(cnt_mode2)
4'd0: begin state <= START; end //I2C通信时序中的START
4'd1: begin data_wr <= dev_addr; state <= WRITE; end //设备地址
4'd2: begin data_wr <= reg_addr; state <= WRITE; end //寄存器地址
4'd3: begin state <= START; end //I2C通信时序中的START
4'd4: begin data_wr <= dev_addr_r; state <= WRITE; end //设备地址
4'd5: begin ack <= ACK; state <= READ; end //读寄存器数据
4'd6: begin seg_data <= data_r; end
4'd7: begin ack <= NACK; state <= STOP; end //I2C通信时序中的STOP
4'd8: begin state <= MAIN; end //返回MAIN
default: state <= IDLE; //如果程序失控,进入IDLE自复位状态
endcase
end

最后我们编程控制状态机按照驱动例程代码中流程运行,程序实现如下:

MAIN:begin
  if(cnt_main >= 2'd2) 
  cnt_main <= 2'd0;   //写完控制指令后循环读数据
  else 
  cnt_main <= cnt_main + 1'b1; 
  case(cnt_main)
   2'd0: begin dev_addr <= 8'ha0; reg_addr <= 8'h80; state <= MODE1; end //写入数据
   2'd1: begin num_delay <= 24'd2000; state <= DELAY; end //5ms延时
   2'd2: begin dev_addr <= 8'ha0; dev_addr_r <= 8'ha1; reg_addr <= 8'h80; state <= MODE2; end //读取数据
   default: state <= IDLE; //如果程序失控,进入IDLE自复位状态
  endcase
 end

12.4.4 系统总体实现

本实验例程往EEPROM写0~255的递增数,同时读取出来显示在数码管上:

at24_driver u1(
        .clk            (clk            ),  //系统时钟
        .rst_n      (rst_n      ),  //系统复位,低有效
       
        .i2c_scl        (i2c_scl        ),  //I2C总线SCL
        .i2c_sda        (i2c_sda        ),  //I2C总线SDA
       
        .data_valid (),
        .data_out   (data_out)
    );


wire [19:0] data_bcd;
bin_to_bcd u2
(
.rst_n              (rst_n      ),  //系统复位,低有效
.bin_code           (data_out   ),  //需要进行BCD转码的二进制数据
.bcd_code           (data_bcd   )   //转码后的BCD码型数据输出
);

segment_scan u3(
        .clk            (clk            ),  //系统时钟
        .rst_n      (rst_n          ),  //系统复位,低有效
        .dat_1      (   ),  //SEG1
        .dat_2      (   ),  //SEG2
        .dat_3      (   ),  //SEG3
        .dat_4      (data_bcd[19:16]    ),  //SEG4
        .dat_5      (data_bcd[15:12]),  //SEG5
        .dat_6      (data_bcd[11: 8]),  //SEG6
        .dat_7      (data_bcd[ 7: 4]),  //SEG7
        .dat_8      (data_bcd[ 3: 0]),  //SEG8
        .dat_en     (8'b0001_1111   ),  //各位数码管数据显示使能,[MSB~LSB]=[SEG1~SEG8]
        .dot_en     (8'b0000_0000   ),  //各位数码管小数点显示使能,[MSB~LSB]=[SEG1~SEG8]
        .seg_rck        (seg_rck        ),  //74HC595的RCK管脚
        .seg_sck        (seg_sck        ),  //74HC595的SCK管脚
        .seg_din        (seg_din        )   //74HC595的SER管脚
    );

综合后的设计框图如下:

alt text