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