差别
这里会显示出您选择的修订版和当前版本之间的差别。
两侧同时换到之前的修订记录 前一修订版 后一修订版 | 前一修订版 | ||
dac数模转换模块 [2017/06/30 15:46] anran [硬件说明] |
dac数模转换模块 [2020/01/18 21:41] (当前版本) gongyu |
||
---|---|---|---|
行 1: | 行 1: | ||
- | ======基于STEP FPGA的PCF8591的DAC(I2C)功能驱动====== | + | ### 基于STEP FPGA的PCF8591的DAC(I2C)功能驱动 |
本节将和大家一起使用FPGA驱动底板上的PCF8591的DAC转换(I2C)功能。 | 本节将和大家一起使用FPGA驱动底板上的PCF8591的DAC转换(I2C)功能。 | ||
+ | --- | ||
+ | #### 硬件说明 | ||
- | ====硬件说明==== | ||
- | ------- | ||
PCF8591是集成了4路ADC和1路DAC的芯片,使用I2C总线通信。 | PCF8591是集成了4路ADC和1路DAC的芯片,使用I2C总线通信。 | ||
\\ | \\ | ||
行 27: | 行 27: | ||
{{ :pcf8591_时序控制2.jpg?800 |}} | {{ :pcf8591_时序控制2.jpg?800 |}} | ||
- | ====Verilog代码==== | + | --- |
- | ------ | + | #### Verilog代码 |
<code verilog> | <code verilog> | ||
// -------------------------------------------------------------------- | // -------------------------------------------------------------------- | ||
// >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<< | // >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<< | ||
// -------------------------------------------------------------------- | // -------------------------------------------------------------------- | ||
- | // Module: ADC_I2C | + | // Module: DAC_I2C |
// | // | ||
// Author: Step | // Author: Step | ||
// | // | ||
- | // Description: ADC_I2C | + | // Description: DAC_I2C |
// | // | ||
// Web: www.stepfpga.com | // Web: www.stepfpga.com | ||
行 47: | 行 47: | ||
// V1.1 |2016/10/30 |Initial ver | // V1.1 |2016/10/30 |Initial ver | ||
// -------------------------------------------------------------------- | // -------------------------------------------------------------------- | ||
- | module ADC_I2C | + | module DAC_I2C |
( | ( | ||
input clk_in, //系统时钟 | input clk_in, //系统时钟 | ||
input rst_n_in, //系统复位,低有效 | input rst_n_in, //系统复位,低有效 | ||
+ | |||
+ | output reg dac_done, //DAC采样完成标志 | ||
+ | input [7:0] dac_data, //DAC采样数据 | ||
+ | |||
output scl_out, //I2C总线SCL | output scl_out, //I2C总线SCL | ||
- | inout sda_out, //I2C总线SDA | + | inout sda_out //I2C总线SDA |
- | output reg adc_done, //ADC采样完成标志 | + | |
- | output reg [7:0] adc_data //ADC采样数据 | + | |
); | ); | ||
行 63: | 行 65: | ||
localparam START = 3'd2; | localparam START = 3'd2; | ||
localparam WRITE = 3'd3; | localparam WRITE = 3'd3; | ||
- | localparam READ = 3'd4; | + | localparam STOP = 3'd4; |
- | localparam STOP = 3'd5; | + | |
//根据PCF8591的datasheet,I2C的频率最高为100KHz, | //根据PCF8591的datasheet,I2C的频率最高为100KHz, | ||
行 87: | 行 88: | ||
reg sda_out_r; | reg sda_out_r; | ||
reg [2:0] cnt; | reg [2:0] cnt; | ||
- | reg [3:0] cnt_main; | + | reg [2:0] cnt_main; |
reg [7:0] data_wr; | reg [7:0] data_wr; | ||
reg [2:0] cnt_start; | reg [2:0] cnt_start; | ||
reg [2:0] cnt_write; | reg [2:0] cnt_write; | ||
- | reg [4:0] cnt_read; | ||
reg [2:0] cnt_stop; | reg [2:0] cnt_stop; | ||
reg [2:0] state; | reg [2:0] state; | ||
行 100: | 行 100: | ||
sda_out_r <= 1'd1; | sda_out_r <= 1'd1; | ||
cnt <= 1'b0; | cnt <= 1'b0; | ||
- | cnt_main <= 4'd0; | + | cnt_main <= 1'b0; |
- | cnt_start <= 3'd0; | + | cnt_start <= 1'b0; |
cnt_write <= 3'd0; | cnt_write <= 3'd0; | ||
- | cnt_read <= 5'd0; | ||
cnt_stop <= 1'd0; | cnt_stop <= 1'd0; | ||
- | adc_done <= 1'b0; | + | dac_done <= 1'b1; |
- | adc_data <= 1'b0; | + | |
state <= IDLE; | state <= IDLE; | ||
end else begin | end else begin | ||
行 114: | 行 112: | ||
sda_out_r <= 1'd1; | sda_out_r <= 1'd1; | ||
cnt <= 1'b0; | cnt <= 1'b0; | ||
- | cnt_main <= 4'd0; | + | cnt_main <= 1'b0; |
- | cnt_start <= 3'd0; | + | cnt_start <= 1'b0; |
cnt_write <= 3'd0; | cnt_write <= 3'd0; | ||
- | cnt_read <= 5'd0; | ||
cnt_stop <= 1'd0; | cnt_stop <= 1'd0; | ||
- | adc_done <= 1'b0; | + | dac_done <= 1'b1; |
state <= MAIN; | state <= MAIN; | ||
end | end | ||
MAIN:begin | MAIN:begin | ||
- | if(cnt_main >= 4'd6) cnt_main <= 4'd6; //对MAIN中的子状态执行控制cnt_main | + | if(cnt_main >= 3'd3) cnt_main <= 3'd3; //对MAIN中的子状态执行控制cnt_main |
else cnt_main <= cnt_main + 1'b1; | else cnt_main <= cnt_main + 1'b1; | ||
case(cnt_main) | case(cnt_main) | ||
- | 4'd0: begin state <= START; end //I2C通信时序中的START | + | 3'd0: begin state <= START; end //I2C通信时序中的START |
- | 4'd1: begin data_wr <= 8'h90; state <= WRITE; end //A0,A1,A2都接了GND,写地址为8'h90 | + | 3'd1: begin data_wr <= 8'h90; state <= WRITE; end //A0,A1,A2都接了GND,写地址为8'h90 |
- | 4'd2: begin data_wr <= 8'h00; state <= WRITE; end //control byte为8'h00,采用4通道ADC中的通道0 | + | 3'd2: begin data_wr <= 8'h40; state <= WRITE; end //control byte为8'h40,打开DAC功能 |
- | 4'd3: begin state <= STOP; end //I2C通信时序中的START | + | 3'd3: begin data_wr <= dac_data; state <= WRITE; dac_done <= 1'b0; end //需要进行DAC转换的数据 |
- | 4'd4: begin state <= START; end //I2C通信时序中的STOP | + | 3'd4: begin state <= STOP; end //I2C通信时序中的结束STOP |
- | 4'd5: begin data_wr <= 8'h91; state <= WRITE; end //A0 A1 A2都接了GND,读地址为8'h91 | + | |
- | 4'd6: begin state <= READ; adc_done <= 1'b0; end //读取ADC的采样数据 | + | |
- | 4'd7: begin state <= STOP; adc_done <= 1'b1; end //I2C通信时序中的STOP,读取完成标志 | + | |
- | 4'd8: begin state <= MAIN; end //预留状态,不执行 | + | |
default: state <= IDLE; //如果程序失控,进入IDLE自复位状态 | default: state <= IDLE; //如果程序失控,进入IDLE自复位状态 | ||
endcase | endcase | ||
行 166: | 行 159: | ||
3'd3: begin scl_out_r <= 1'b0; end //SCL拉低,准备发送下1bit的数据 | 3'd3: begin scl_out_r <= 1'b0; end //SCL拉低,准备发送下1bit的数据 | ||
//获取从设备的响应信号并判断 | //获取从设备的响应信号并判断 | ||
- | 3'd4: begin sda_out_r <= 1'bz; end //释放SDA线,准备接收从设备的响应信号 | + | 3'd4: begin sda_out_r <= 1'bz; dac_done <= 1'b1; end //释放SDA线,准备接收从设备的响应信号 |
3'd5: begin scl_out_r <= 1'b1; end //SCL拉高,保持4.0us以上 | 3'd5: begin scl_out_r <= 1'b1; end //SCL拉高,保持4.0us以上 | ||
3'd6: begin if(sda_out) state <= IDLE; else state <= state; end //获取从设备的响应信号并判断 | 3'd6: begin if(sda_out) state <= IDLE; else state <= state; end //获取从设备的响应信号并判断 | ||
- | 3'd7: begin scl_out_r <= 1'b0; state <= MAIN; end //SCL拉低,返回MAIN状态 | ||
- | default: state <= IDLE; //如果程序失控,进入IDLE自复位状态 | ||
- | endcase | ||
- | end | ||
- | READ:begin //I2C通信时序中的读操作READ和返回ACK的操作 | ||
- | if(cnt <= 3'd6) begin //共需要接收8bit的数据,这里控制循环的次数 | ||
- | if(cnt_read >= 3'd3) begin cnt_read <= 1'b0; cnt <= cnt + 1'b1; end | ||
- | else begin cnt_read <= cnt_read + 1'b1; cnt <= cnt; end | ||
- | end else begin | ||
- | if(cnt_read >= 3'd7) begin cnt_read <= 1'b0; cnt <= 1'b0; end //两个变量都恢复初值 | ||
- | else begin cnt_read <= cnt_read + 1'b1; cnt <= cnt; end | ||
- | end | ||
- | case(cnt_read) | ||
- | //按照I2C的时序接收数据 | ||
- | 3'd0: begin scl_out_r <= 1'b0; sda_out_r <= 1'bz; end //SCL拉低,释放SDA线,准备接收从设备数据 | ||
- | 3'd1: begin scl_out_r <= 1'b1; end //SCL拉高,保持4.0us以上 | ||
- | 3'd2: begin adc_data_r[7-cnt] <= sda_out; end //读取从设备返回的数据 | ||
- | 3'd3: begin scl_out_r <= 1'b0; end //SCL拉低,准备接收下1bit的数据 | ||
- | //向从设备发送响应信号 | ||
- | 3'd4: begin sda_out_r <= 1'b0; adc_done <= 1'b1; adc_data <= adc_data_r; end //发送响应信号,将前面接收的数据锁存 | ||
- | 3'd5: begin scl_out_r <= 1'b1; end //SCL拉高,保持4.0us以上 | ||
- | 3'd6: begin scl_out_r <= 1'b1; adc_done <= 1'b0; end //SCL拉高,保持4.0us以上 | ||
3'd7: begin scl_out_r <= 1'b0; state <= MAIN; end //SCL拉低,返回MAIN状态 | 3'd7: begin scl_out_r <= 1'b0; state <= MAIN; end //SCL拉低,返回MAIN状态 | ||
default: state <= IDLE; //如果程序失控,进入IDLE自复位状态 | default: state <= IDLE; //如果程序失控,进入IDLE自复位状态 | ||
行 219: | 行 190: | ||
</code> | </code> | ||
+ | --- | ||
+ | #### 小结 | ||
- | ====小结==== | + | 本节主要为大家讲解了使用I2C驱动PCF8591的DAC功能的原理及软件设计,需要大家掌握的同时自己创建工程,通过整个设计流程,生成FPGA配置文件加载测试。 |
- | ------ | + | |
- | 本节主要为大家讲解了使用I2C驱动PCF8591的ADC功能的原理及软件设计,需要大家掌握的同时自己创建工程,通过整个设计流程,生成FPGA配置文件加载测试。 | + | |
\\ | \\ | ||
如果你对Diamond软件的使用不了解,请参考这里:[[lattice_diamond的使用|Diamond的使用]]。 | 如果你对Diamond软件的使用不了解,请参考这里:[[lattice_diamond的使用|Diamond的使用]]。 | ||
- | ====相关资料==== | + | --- |
- | ------ | + | #### 相关资料 |
\\ | \\ | ||
- | 使用[[STEP-MXO2第二代]]的PCF8591的ADC驱动程序: 后续会有下载连接 待更新 | + | 使用[[STEP-MXO2第二代]]的PCF8591的DAC驱动程序: 后续会有下载连接 待更新 |
\\ | \\ | ||
- | 使用[[STEP-MAX10]]的PCF8591的ADC驱动程序: 后续会有下载连接 待更新 | + | 使用[[STEP-MAX10]]的PCF8591的DAC驱动程序: 后续会有下载连接 待更新 |
\\ | \\ |