FPGA模块——IIC协议(读取PCF8591)
- PCF8591/AT8591芯片
 - 对iic协议的使用
 
PCF8591/AT8591芯片
低功耗8位CMOS数据采集设备,4路模拟输入,1路模拟输出,分时多路复用,读取数据用串型iic总线接口,最大100khz。
 
控制字节(iic中写寄存器地址位8b)
 这个芯片中是有自己要求的,但是也符合iic协议的时序。
 
 stop之前最后一步:
 写的8位数据就是DAC转换得到的电压值,
 读的数据就是ADC转换得到的8位数据
对iic协议的使用
iic协议就看这个之前写的:链接: IIC协议模块
module pcf8591(//clock and resetinput                 clk        ,    // 时钟信号input                 rst_n      ,    // 复位信号//i2c interfaceoutput   reg          i2c_rh_wl  ,    // I2C读写控制信号output   reg          i2c_exec   ,    // I2C触发执行信号output   reg  [15:0]  i2c_addr   ,    // I2C器件内地址output   reg  [ 7:0]  i2c_data_w ,    // I2C要写的数据input         [ 7:0]  i2c_data_r ,    // I2C读出的数据input                 i2c_done   ,    // I2C一次操作完成//user interfaceoutput   reg  [19:0]  num             // 数码管要显示的数据
);//parameter
parameter    CONTORL_BYTE = 8'b0100_0001; // PCF8591的控制字
parameter    V_REF        = 12'd3300    ; // 3.3V放大1000倍,避免用小数//reg define
reg    [7:0]    da_data   ;               // DA数据
reg    [7:0]    ad_data   ;               // AD数据
reg    [3:0]    flow_cnt  ;               // 状态流控制
reg    [18:0]   wait_cnt  ;               // 计数等待//wire define
wire   [19:0]   num_t     ;               // 临时寄存的数据//*****************************************************
//**                    main code
//*****************************************************assign num_t = V_REF * ad_data ;//DA输出数据
always @(posedge clk or negedge rst_n) beginif(rst_n == 1'b0) beginda_data  <= 8'd0;endelse if(i2c_rh_wl == 1'b0 & i2c_done == 1'b1)beginif(da_data == 8'd255)da_data<= 8'd0;elseda_data<= da_data + 1'b1;end
end//AD输入数据处理
always @(posedge clk or negedge rst_n) beginif(rst_n == 1'b0) beginnum <= 20'd0;endelsenum <= num_t >> 4'd8;
end//AD、DA控制及采样
always @(posedge clk or negedge rst_n) beginif(rst_n == 1'b0) begini2c_exec <= 1'b0;i2c_rh_wl<= 1'b0;i2c_addr <= 8'd0;i2c_data_w <=  8'd0;flow_cnt   <=  4'd0;wait_cnt   <= 17'd0;endelse begini2c_exec <= 1'b0;case(flow_cnt)'d0: beginif(wait_cnt == 17'd100) beginwait_cnt<= 17'd0;flow_cnt<= flow_cnt + 1'b1;endelsewait_cnt<= wait_cnt + 1'b1;end//DA转换输出'd1: begini2c_exec  <= 1'b1;i2c_addr  <= CONTORL_BYTE;i2c_rh_wl <= 1'b0;i2c_data_w<= da_data;flow_cnt  <= flow_cnt + 1'b1;end'd2: beginif(i2c_done == 1'b1) beginflow_cnt<= flow_cnt + 1'b1;endend'd3: begin//每1秒变化0.1V,需33秒变化完,共256【0~255】次变化,故每次变化计数为://(33/256)*10^6 = 128906if(wait_cnt == 17'd128906) beginwait_cnt<= 17'd0;flow_cnt<= flow_cnt + 1'b1;endelsewait_cnt<= wait_cnt + 1'b1;end//AD转换输入'd4: begini2c_exec  <= 1'b1;i2c_addr  <= CONTORL_BYTE;i2c_rh_wl <= 1'b1;flow_cnt  <= flow_cnt + 1'b1;end'd5: beginif(i2c_done == 1'b1) beginad_data <= i2c_data_r;flow_cnt<= 4'd0;endenddefault: flow_cnt <= 4'd0;endcaseend
endendmodule