主頁 > 移動端開發 > 基于FPGA的MCP4725驅動程式

基于FPGA的MCP4725驅動程式

2020-11-09 22:41:58 移動端開發

基于FPGA的MCP4725驅動程式

  1. 芯片資料
    MCP4725是低功耗、高精度、單通道的12位緩沖電壓輸出數模轉換器(Digital-to-Analog Convertor,DAC),具有非易失性存盤器(EEPROM),用戶可以使用I2C介面命令將DAC輸入和配置資料燒寫到非易失性存盤器(EEPROM),非易失性存盤器功能使得DAC器件在斷電期間仍能保持DAC輸入代碼,且DAC輸出在上電后立即可用,
    在這里插入圖片描述

圖1.MCP4725功能框圖
MCP4725具有外部A0地址位選擇引腳,此A0引腳可連接用戶應用電路板的VDD或VSS,MCP4725具有2線型IIC兼容串行介面,可用于標準(100 kHz)、快速(400 kHz)或高速(3.4 MHz)模式,
圖2.MCP4725封裝型別
Vout:模擬輸出電壓;
Vss:參考地;
VDD:電源電壓;3.7~5.5V
SDA:IIC串行資料;
SCL:IIC串行時鐘輸入
A0:地址位選擇引腳;該引腳可連接到VSS或VDD ,或由數字邏輯電平有效驅動,該引腳的邏輯狀態決定了I2 C地址位的A0位,
2. 輸出電壓計算
在這里插入圖片描述
例如當我們輸入0x400,即十進制數1024,電源電壓接入為5V,那么輸出電壓Vout=5*1024/4096=1.25V,
3. 作業原理
當器件連接到I2C總線時,器件作為從器件作業,使用I2C介面命令,主器件可以讀/寫DAC輸入暫存器或EEPROM,MCP4725器件地址包含4個固定位(1100 =器件代碼)和3個地址位(A2、A1和A0),A2和A1位是在出廠前硬連線的,而A0位由A0引腳的邏輯狀態決定,A0引腳可連接到VDD或VSS,或由數字邏輯電平有效驅動,寫命令用于將配置位和DAC輸入代碼裝載到DAC暫存器,或寫入器件的EEPROM,通過使用3個寫命令型別位(C2、C1和C0)定義寫命令型別,
在這里插入圖片描述
當C2=0,C1=0 時,為快速模式,此命令用于更改DAC暫存器,EEPROM不受影響;當C2=0,C1=1,C0=0 時,為寫DAC暫存器模式,即將配置位和資料代碼裝載到DAC暫存器;當C2=0,C1=1,C0=1 時,為寫DAC暫存器和更新EEPROM模式,將配置位和資料代碼裝載到DAC暫存器并且寫入EEPROM中,本次主要使用寫DAC暫存器模式和寫DAC暫存器和更新EEPROM模式,如下圖所示,
在這里插入圖片描述
第一個位元組為器件尋址,A2和A1已經被廠家設定為0,A0由自己控制(默認為0,即接地),因此第一個位元組為0x60;第二個位元組為寫資料地址,PD0和PD1都為0時為正常模式,因此第二個位元組為0x60;第三個位元組和第四個位元組的高4位組成12位資料輸入,由我們自己定義輸入,
4. IIC串行通信
MCP4725器件使用2線IIC串行介面,該介面可在標準、快速或高速模式下作業,在總線上發送資料的器件定義為發送器,而接收資料的器件定義為接收器,總線必須由主器件控制,主器件產生串行時(SCL)信號、控制總線訪問權并產生啟動條件和停止條件,MCP4725器件作為從器件作業,主器件和從器件都可以作為發送器或接收器作業,但是由主器件決定激活哪種模式,通信由主器件(單片機)發起,它發送啟動位,隨后是從地址位元組,發送的第一個位元組始終為從地址位元組,它包含器件代碼、地址位和R/W位,MCP4725器件的器件代碼為1100,當器件接收到讀命令(R/W = 1)時,發送DAC輸入暫存器和EEPROM的內容,下圖給出了IIC通信時序要求,
在這里插入圖片描述
在本次設計中,SCL時鐘輸入頻率選擇為250KHz,FPGA作業時鐘為50MHz,上電等待20ms后開始IIC資料寫入,采用模塊化設計,分為IIC驅動設計,MCP4725初始化設計,頂層模塊,
5. 代碼模塊

5.1 IIC驅動模塊

module i2c_dri
    #(// slave address(器件地址)
      parameter   SLAVE_ADDR =  7'b1100000  ,
      parameter   CLK_FREQ   = 26'd50_000_000,   //  時鐘頻率(CLK_FREQ)
      parameter   I2C_FREQ   = 18'd250_000       // I2C的SCL時鐘頻率
     )(
          //global clock
          input                clk        ,      // 時鐘
          input                rst_n      ,      // 復位信號

          //i2c interface
          input                i2c_exec   ,      // I2C觸發執行信號
          input                bit_ctrl   ,      // 字地址位控制(16b/8b)
          input                i2c_rh_wl  ,      // I2C讀寫控制信號
          input        [15:0]  i2c_addr   ,      // I2C器件內地址
          input        [15:0]  i2c_data_w ,      // I2C要寫的資料
          output  reg  [ 7:0]  i2c_data_r ,      // I2C讀出的資料
          output  reg          i2c_done   ,      // I2C一次操作完成
          output  reg          scl        ,      // I2C的SCL時鐘信號
          inout                sda        ,      // I2C的SDA信號

          //user interface
          output  reg          dri_clk           // 驅動I2C操作的驅動時鐘
     );

//localparam define
localparam  st_idle     = 8'b0000_0001;          // 空閑狀態
localparam  st_sladdr   = 8'b0000_0010;          // 發送器件地址(slave address)
localparam  st_addr16   = 8'b0000_0100;          // 發送16位字地址
localparam  st_addr8    = 8'b0000_1000;          // 發送8位字地址
localparam  st_data_wr  = 8'b0001_0000;          // 寫資料(8 bit)
localparam  st_addr_rd  = 8'b0010_0000;          // 發送器件地址讀
localparam  st_data_rd  = 8'b0100_0000;          // 讀資料(8 bit)
localparam  st_stop     = 8'b1000_0000;          // 結束I2C操作

//reg define
reg            sda_dir     ;                     // I2C資料(SDA)方向控制
reg            sda_out     ;                     // SDA輸出信號
reg            st_done     ;                     // 狀態結束
reg            wr_flag     ;                     // 寫標志
reg    [ 6:0]  cnt         ;                     // 計數
reg    [ 7:0]  cur_state   ;                     // 狀態機當前狀態
reg    [ 7:0]  next_state  ;                     // 狀態機下一狀態
reg    [15:0]  addr_t      ;                     // 地址
reg    [ 7:0]  data_r      ;                     // 讀取的資料
reg    [15:0]  data_wr_t   ;                     // I2C需寫的資料的臨時寄存
reg    [ 9:0]  clk_cnt     ;                     // 分頻時鐘計數

//wire define
wire          sda_in      ;                      // SDA輸入信號
wire   [8:0]  clk_divide  ;                      // 模塊驅動時鐘的分頻系數



//SDA控制
assign  sda     = sda_dir ?  sda_out : 1'bz;     // SDA資料輸出或高阻
assign  sda_in  = sda ;                          // SDA資料輸入
assign  clk_divide = (CLK_FREQ/I2C_FREQ) >> 3;   // 模塊驅動時鐘的分頻系數

//生成I2C的SCL的四倍頻率的驅動時鐘用于驅動i2c的操作
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        dri_clk <=  1'b1;
        clk_cnt <= 10'd0;
    end
    else if(clk_cnt == clk_divide - 1'd1) begin
        clk_cnt <= 10'd0;
        dri_clk <= ~dri_clk;
    end
    else
        clk_cnt <= clk_cnt + 1'b1;
end

//(三段式狀態機)同步時序描述狀態轉移
always @(posedge dri_clk or negedge rst_n) begin
    if(!rst_n)
        cur_state <= st_idle;
    else
        cur_state <= next_state;
end

//組合邏輯判斷狀態轉移條件
always @( * ) begin
//    next_state = st_idle;
    case(cur_state)
        st_idle: begin                           // 空閑狀態
           if(i2c_exec) begin
               next_state = st_sladdr;
           end
           else
               next_state = st_idle;
        end
        st_sladdr: begin
            if(st_done) begin
                if(bit_ctrl)                     // 判斷是16位還是8位字地址
                   next_state = st_addr16;
                else
                   next_state = st_addr8 ;
            end
            else
                next_state = st_sladdr;
        end
        st_addr16: begin                         // 寫16位字地址
            if(st_done) begin
                next_state = st_addr8;
            end
            else begin
                next_state = st_addr16;
            end
        end
        st_addr8: begin                          // 8位字地址
            if(st_done) begin
                if(wr_flag==1'b0)                // 讀寫判斷
                    next_state = st_data_wr;
                else
                    next_state = st_addr_rd;
            end
            else begin
                next_state = st_addr8;
            end
        end
        st_data_wr: begin                        // 寫資料(8 bit)
            if(st_done)
                next_state = st_stop;
            else
                next_state = st_data_wr;
        end
        st_addr_rd: begin                        // 寫地址以進行讀資料
            if(st_done) begin
                next_state = st_data_rd;
            end
            else begin
                next_state = st_addr_rd;
            end
        end
        st_data_rd: begin                        // 讀取資料(8 bit)
            if(st_done)
                next_state = st_stop;
            else
                next_state = st_data_rd;
        end
        st_stop: begin                           // 結束I2C操作
            if(st_done)
                next_state = st_idle;
            else
                next_state = st_stop ;
        end
        default: next_state= st_idle;
    endcase
end

//時序電路描述狀態輸出
always @(posedge dri_clk or negedge rst_n) begin
    //復位初始化
    if(!rst_n) begin
        scl        <= 1'b1;
        sda_out    <= 1'b1;
        sda_dir    <= 1'b1;
        i2c_done   <= 1'b0;
        cnt        <= 1'b0;
        st_done    <= 1'b0;
        data_r     <= 1'b0;
        i2c_data_r <= 1'b0;
        wr_flag    <= 1'b0;
        addr_t     <= 1'b0;
        data_wr_t  <= 1'b0;
    end
    else begin
        st_done <= 1'b0 ;
        cnt     <= cnt +1'b1 ;
        case(cur_state)
             st_idle: begin                            // 空閑狀態
                scl     <= 1'b1;
                sda_out <= 1'b1;
                sda_dir <= 1'b1;
                i2c_done<= 1'b0;
                cnt     <= 7'b0;
                if(i2c_exec) begin
                    wr_flag   <= i2c_rh_wl ;
                    addr_t    <= i2c_addr  ;
                    data_wr_t <= i2c_data_w;
                end
            end
            st_sladdr: begin                           // 寫地址(器件地址和字地址)
                case(cnt)
                    7'd1 : sda_out <= 1'b0;            // 開始I2C
                    7'd3 : scl <= 1'b0;
                    7'd4 : sda_out <= SLAVE_ADDR[6];   // 傳送器件地址
                    7'd5 : scl <= 1'b1;
                    7'd7 : scl <= 1'b0;
                    7'd8 : sda_out <= SLAVE_ADDR[5];
                    7'd9 : scl <= 1'b1;
                    7'd11: scl <= 1'b0;
                    7'd12: sda_out <= SLAVE_ADDR[4];
                    7'd13: scl <= 1'b1;
                    7'd15: scl <= 1'b0;
                    7'd16: sda_out <= SLAVE_ADDR[3];
                    7'd17: scl <= 1'b1;
                    7'd19: scl <= 1'b0;
                    7'd20: sda_out <= SLAVE_ADDR[2];
                    7'd21: scl <= 1'b1;
                    7'd23: scl <= 1'b0;
                    7'd24: sda_out <= SLAVE_ADDR[1];
                    7'd25: scl <= 1'b1;
                    7'd27: scl <= 1'b0;
                    7'd28: sda_out <= SLAVE_ADDR[0];
                    7'd29: scl <= 1'b1;
                    7'd31: scl <= 1'b0;
                    7'd32: sda_out <= 1'b0;            // 0:寫
                    7'd33: scl <= 1'b1;
                    7'd35: scl <= 1'b0;
                    7'd36: begin
                        sda_dir <= 1'b0;               // 從機應答
                        sda_out <= 1'b1;
                    end
                    7'd37: scl     <= 1'b1;
                    7'd38: st_done <= 1'b1;
                    7'd39: begin
                        scl <= 1'b0;
                        cnt <= 1'b0;
                    end
                    default :  ;
                endcase
            end
            st_addr16: begin
                case(cnt)
                    7'd0 : begin
                        sda_dir <= 1'b1 ;
                        sda_out <= addr_t[15];         // 傳送字地址
                    end
                    7'd1 : scl <= 1'b1;
                    7'd3 : scl <= 1'b0;
                    7'd4 : sda_out <= addr_t[14];
                    7'd5 : scl <= 1'b1;
                    7'd7 : scl <= 1'b0;
                    7'd8 : sda_out <= addr_t[13];
                    7'd9 : scl <= 1'b1;
                    7'd11: scl <= 1'b0;
                    7'd12: sda_out <= addr_t[12];
                    7'd13: scl <= 1'b1;
                    7'd15: scl <= 1'b0;
                    7'd16: sda_out <= addr_t[11];
                    7'd17: scl <= 1'b1;
                    7'd19: scl <= 1'b0;
                    7'd20: sda_out <= addr_t[10];
                    7'd21: scl <= 1'b1;
                    7'd23: scl <= 1'b0;
                    7'd24: sda_out <= addr_t[9];
                    7'd25: scl <= 1'b1;
                    7'd27: scl <= 1'b0;
                    7'd28: sda_out <= addr_t[8];
                    7'd29: scl <= 1'b1;
                    7'd31: scl <= 1'b0;
                    7'd32: begin
                        sda_dir <= 1'b0;               // 從機應答
                        sda_out <= 1'b1;
                    end
                    7'd33: scl     <= 1'b1;
                    7'd34: st_done <= 1'b1;
                    7'd35: begin
                        scl <= 1'b0;
                        cnt <= 1'b0;
                    end
                    default :  ;
                endcase
            end
            st_addr8: begin
                case(cnt)
                    7'd0: begin
                       sda_dir <= 1'b1 ;
                       sda_out <= addr_t[7];           // 字地址
                    end
                    7'd1 : scl <= 1'b1;
                    7'd3 : scl <= 1'b0;
                    7'd4 : sda_out <= addr_t[6];
                    7'd5 : scl <= 1'b1;
                    7'd7 : scl <= 1'b0;
                    7'd8 : sda_out <= addr_t[5];
                    7'd9 : scl <= 1'b1;
                    7'd11: scl <= 1'b0;
                    7'd12: sda_out <= addr_t[4];
                    7'd13: scl <= 1'b1;
                    7'd15: scl <= 1'b0;
                    7'd16: sda_out <= addr_t[3];
                    7'd17: scl <= 1'b1;
                    7'd19: scl <= 1'b0;
                    7'd20: sda_out <= addr_t[2];
                    7'd21: scl <= 1'b1;
                    7'd23: scl <= 1'b0;
                    7'd24: sda_out <= addr_t[1];
                    7'd25: scl <= 1'b1;
                    7'd27: scl <= 1'b0;
                    7'd28: sda_out <= addr_t[0];
                    7'd29: scl <= 1'b1;
                    7'd31: scl <= 1'b0;
                    7'd32: begin
                        sda_dir <= 1'b0;               // 從機應答
                        sda_out <= 1'b1;
                    end
                    7'd33: scl     <= 1'b1;
                    7'd34: st_done <= 1'b1;
                    7'd35: begin
                        scl <= 1'b0;
                        cnt <= 1'b0;
                    end
                    default :  ;
                endcase
            end
            st_data_wr: begin                          // 寫資料(12 bit)
                case(cnt)
                    7'd0: begin
                        sda_out <= data_wr_t[15];       // I2C寫2次8位資料
                        sda_dir <= 1'b1;
                    end
                    7'd1 : scl <= 1'b1;
                    7'd3 : scl <= 1'b0;
                    7'd4 : sda_out <= data_wr_t[14];
                    7'd5 : scl <= 1'b1;
                    7'd7 : scl <= 1'b0;
                    7'd8 : sda_out <= data_wr_t[13];
                    7'd9 : scl <= 1'b1;
                    7'd11: scl <= 1'b0;
                    7'd12: sda_out <= data_wr_t[12];
                    7'd13: scl <= 1'b1;
                    7'd15: scl <= 1'b0;
                    7'd16: sda_out <= data_wr_t[11];
                    7'd17: scl <= 1'b1;
                    7'd19: scl <= 1'b0;
                    7'd20: sda_out <= data_wr_t[10];
                    7'd21: scl <= 1'b1;
                    7'd23: scl <= 1'b0;
                    7'd24: sda_out <= data_wr_t[9];
                    7'd25: scl <= 1'b1;
                    7'd27: scl <= 1'b0;
                    7'd28: sda_out <= data_wr_t[8];
                    7'd29: scl <= 1'b1;
                    7'd31: scl <= 1'b0;
                    7'd32: begin
                        sda_dir <= 1'b0;               // 從機應答
                        sda_out <= 1'b1;
                    end
                    7'd33: scl <= 1'b1;
              
                    7'd35: scl  <= 1'b0;
                    7'd36: sda_out <= data_wr_t[7];
					     7'd37: scl <= 1'b1;
					     
					     7'd39: scl  <= 1'b0;
					     7'd40: sda_out <= data_wr_t[6];
					     7'd41: scl <= 1'b1;
		              
						  7'd43: scl  <= 1'b0;
					     7'd44: sda_out <= data_wr_t[5];
					     7'd45: scl <= 1'b1;
						
				        7'd47: scl  <= 1'b0;
					     7'd48: sda_out <= data_wr_t[4];
					     7'd49: scl <= 1'b1;
						  
						  7'd51: scl  <= 1'b0;
					     7'd52: sda_out <= data_wr_t[3];
					     7'd53: scl <= 1'b1;
						  
						  7'd55: scl  <= 1'b0;
					     7'd56: sda_out <= data_wr_t[2];
					     7'd57: scl <= 1'b1;
						  
						  7'd59: scl  <= 1'b0;
					     7'd60: sda_out <= data_wr_t[1];
					     7'd61: scl <= 1'b1;
						  
						  7'd63: scl  <= 1'b0;
					     7'd64: sda_out <= data_wr_t[0];
					     7'd65: scl <= 1'b1;
						  
						  7'd67: scl <= 1'b0;
                    7'd68: begin
                        sda_dir <= 1'b0;               // 從機應答
                        sda_out <= 1'b1;
                    end
                    7'd69: scl <= 1'b1;
                    7'd70: st_done <= 1'b1;
                    7'd71: begin
                        scl  <= 1'b0;
                        cnt  <= 1'b0;
                    end
				 		                                
                    default  :  ;
                endcase
            end
            st_addr_rd: begin                          // 寫地址以進行讀資料
                case(cnt)
                    7'd0 : begin
                        sda_dir <= 1'b1;
                        sda_out <= 1'b1;
                    end
                    7'd1 : scl <= 1'b1;
                    7'd2 : sda_out <= 1'b0;            // 重新開始
                    7'd3 : scl <= 1'b0;
                    7'd4 : sda_out <= SLAVE_ADDR[6];   // 傳送器件地址
                    7'd5 : scl <= 1'b1;
                    7'd7 : scl <= 1'b0;
                    7'd8 : sda_out <= SLAVE_ADDR[5];
                    7'd9 : scl <= 1'b1;
                    7'd11: scl <= 1'b0;
                    7'd12: sda_out <= SLAVE_ADDR[4];
                    7'd13: scl <= 1'b1;
                    7'd15: scl <= 1'b0;
                    7'd16: sda_out <= SLAVE_ADDR[3];
                    7'd17: scl <= 1'b1;
                    7'd19: scl <= 1'b0;
                    7'd20: sda_out <= SLAVE_ADDR[2];
                    7'd21: scl <= 1'b1;
                    7'd23: scl <= 1'b0;
                    7'd24: sda_out <= SLAVE_ADDR[1];
                    7'd25: scl <= 1'b1;
                    7'd27: scl <= 1'b0;
                    7'd28: sda_out <= SLAVE_ADDR[0];
                    7'd29: scl <= 1'b1;
                    7'd31: scl <= 1'b0;
                    7'd32: sda_out <= 1'b1;            // 1:讀
                    7'd33: scl <= 1'b1;
                    7'd35: scl <= 1'b0;
                    7'd36: begin
                        sda_dir <= 1'b0;               // 從機應答
                        sda_out <= 1'b1;
                    end
                    7'd37: scl     <= 1'b1;
                    7'd38: st_done <= 1'b1;
                    7'd39: begin
                        scl <= 1'b0;
                        cnt <= 1'b0;
                    end
                    default : ;
                endcase
            end
            st_data_rd: begin                          // 讀取資料(8 bit)
                case(cnt)
                    7'd0: sda_dir <= 1'b0;
                    7'd1: begin
                        data_r[7] <= sda_in;
                        scl       <= 1'b1;
                    end
                    7'd3: scl  <= 1'b0;
                    7'd5: begin
                        data_r[6] <= sda_in ;
                        scl       <= 1'b1   ;
                    end
                    7'd7: scl  <= 1'b0;
                    7'd9: begin
                        data_r[5] <= sda_in;
                        scl       <= 1'b1  ;
                    end
                    7'd11: scl  <= 1'b0;
                    7'd13: begin
                        data_r[4] <= sda_in;
                        scl       <= 1'b1  ;
                    end
                    7'd15: scl  <= 1'b0;
                    7'd17: begin
                        data_r[3] <= sda_in;
                        scl       <= 1'b1  ;
                    end
                    7'd19: scl  <= 1'b0;
                    7'd21: begin
                        data_r[2] <= sda_in;
                        scl       <= 1'b1  ;
                    end
                    7'd23: scl  <= 1'b0;
                    7'd25: begin
                        data_r[1] <= sda_in;
                        scl       <= 1'b1  ;
                    end
                    7'd27: scl  <= 1'b0;
                    7'd29: begin
                        data_r[0] <= sda_in;
                        scl       <= 1'b1  ;
                    end
                    7'd31: scl  <= 1'b0;
                    7'd32: begin
                        sda_dir <= 1'b1;              // 非應答
                        sda_out <= 1'b1;
                    end
                    7'd33: scl     <= 1'b1;
                    7'd34: st_done <= 1'b1;
                    7'd35: begin
                        scl <= 1'b0;
                        cnt <= 1'b0;
                        i2c_data_r <= data_r;
                    end
                    default  :  ;
                endcase
            end
            st_stop: begin                            // 結束I2C操作
                case(cnt)
                    7'd0: begin
                        sda_dir <= 1'b1;              // 結束I2C
                        sda_out <= 1'b0;
                    end
                    7'd1 : scl     <= 1'b1;
                    7'd3 : sda_out <= 1'b1;
                    7'd15: st_done <= 1'b1;
                    7'd16: begin
                        cnt      <= 1'b0;
                        i2c_done <= 1'b1;             // 向上層模塊傳遞I2C結束信號
                    end
                    default  : ;
                endcase
            end
        endcase
    end
end

endmodule

5.2 MCP4725初始化模塊

module MCP4725_init( 
 
    input                clk      ,   //時鐘信號
    input                rst_n    ,   //復位信號,低電平有效
    
    input                i2c_done ,   //I2C暫存器配置完成信號
    output  reg          i2c_exec ,   //I2C觸發執行信號   
    output  reg  [23:0]  i2c_data    //I2C要配置的地址與資料(高16位地址,低8位資料)
);




//reg define
reg   [14:0]   start_init_cnt;        //等待延時計數器



//scl配置成250khz,輸入的clk為1Mhz,周期為1us,20000*1us = 20ms
//上電到開始配置IIC至少等待20ms
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        start_init_cnt <= 15'd0;
    else if(start_init_cnt < 15'd20000)
        start_init_cnt <= start_init_cnt + 1'b1;                    
end



//i2c觸發執行信號   
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        i2c_exec <= 1'b0;
    else if(start_init_cnt == 15'd19999)
        i2c_exec <= 1'b1;

    else
        i2c_exec <= 1'b0;
end 



//配置暫存器地址與資料
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        i2c_data <= 16'd0;
	 else 
	     i2c_data <= {8'h60,8'h40,8'h00} ;//第一個位元組為模式控制(60:同步更新到EEPROM;40:只更新DAC暫存器),后面兩個位元組為輸入資料,取高12位
	 
	 end
endmodule

5.3 頂層模塊

module MCP4725_CTRL(

  input clk,
  input rst_n,
  
  output scl,
  inout sda

);

  wire                  i2c_exec        ;  //I2C觸發執行信號
  wire   [23:0]         i2c_data        ;  //I2C要配置的地址與資料(高8位地址,低16位資料)          
  wire                  i2c_done        ;  //I2C暫存器配置完成信號
  wire                  i2c_dri_clk     ;  //I2C操作時鐘
  
  parameter  SLAVE_ADDR = 7'h60         ;  //MCP4725的器件地址7'h60
  parameter  BIT_CTRL   = 1'b0          ;  //位元組地址為8位  0:8位 1:16位
  parameter  CLK_FREQ   = 26'd50_000_000;  //時鐘頻率 50MHz
  parameter  I2C_FREQ   = 18'd250_000   ;  //I2C的SCL時鐘頻率,250KHz

  
 i2c_dri 
   #(
    .SLAVE_ADDR         (SLAVE_ADDR),       //引數傳遞
    .CLK_FREQ           (CLK_FREQ  ),              
    .I2C_FREQ           (I2C_FREQ  )                
    )   
   u_i2c_dri(   
    .clk                (clk       ),
    .rst_n              (rst_n     ),   
        
    .i2c_exec           (i2c_exec  ),   
    .bit_ctrl           (BIT_CTRL  ),   
    .i2c_rh_wl          (1'b0),             //固定為0,只用到了IIC驅動的寫操作   
    .i2c_addr           (i2c_data[23:16]),   
    .i2c_data_w         (i2c_data[15:0]),   
    .i2c_data_r         (),   
    .i2c_done           (i2c_done  ),   
    .scl                (scl   ),   
    .sda                (sda   ),   
        
    .dri_clk            (i2c_dri_clk)       //I2C操作時鐘
); 
  
MCP4725_init u_MCP4725_init( 
 
   .clk     (i2c_dri_clk),   //時鐘信號
   .rst_n   (rst_n),   //復位信號,低電平有效
   .i2c_done(i2c_done),   //I2C暫存器配置完成信號
   .i2c_exec(i2c_exec),   //I2C觸發執行信號   
   .i2c_data(i2c_data)   //I2C要配置的地址與資料(高8位地址,低16位資料)
);
  
  
  
endmodule 

PS:IIC驅動程式是我在以前寫的IIC單位元組讀寫程式的基礎上修改而來,從而實作兩個位元組的寫入(這里可以再增加實作多個位元組的寫入,但要注意cnt的位寬),MCP4725初始化程式中最后的 i2c_data <= {8’h60,8’h40,8’h00} ; 這一行大家可以根據自己的實際需求做更改,詳細更改的內容自行參考芯片的資料手冊,

6.驗證
將工程編譯好后的sof檔案下載到EP4CE6F17C8器件中,連接好MCP4725各個引腳,電源接5V,輸入的資料為1024,為4096的四分之一,因此輸出電壓應該為1.25V,利用萬用表測量資料為1.25V,將模塊斷電再重新上電,再次測量也為1.25V,證明資料成功寫入EEPROM中,驗證成功,

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/208454.html

標籤:其他

上一篇:Spring之默認標簽的決議(一) 總覽

下一篇:還在一行行敲代碼嗎?一起自定義vscode快捷輸入吧!

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【從零開始擼一個App】Dagger2

    Dagger2是一個IOC框架,一般用于Android平臺,第一次接觸的朋友,一定會被搞得暈頭轉向。它延續了Java平臺Spring框架代碼碎片化,注解滿天飛的傳統。嘗試將各處代碼片段串聯起來,理清思緒,真不是件容易的事。更不用說還有各版本細微的差別。 與Spring不同的是,Spring是通過反射 ......

    uj5u.com 2020-09-10 06:57:59 more
  • Flutter Weekly Issue 66

    新聞 Flutter 季度調研結果分享 教程 Flutter+FaaS一體化任務編排的思考與設計 詳解Dart中如何通過注解生成代碼 GitHub 用對了嗎?Flutter 團隊分享如何管理大型開源專案 插件 flutter-bubble-tab-indicator A Flutter librar ......

    uj5u.com 2020-09-10 06:58:52 more
  • Proguard 常用規則

    介紹 Proguard 入口,如何查看輸出,如何使用 keep 設定入口以及使用實體,如何配置壓縮,混淆,校驗等規則。

    ......

    uj5u.com 2020-09-10 06:59:00 more
  • Android 開發技術周報 Issue#292

    新聞 Android即將獲得類AirDrop功能:可向附近設備快速分享檔案 谷歌為安卓檔案管理應用引入可安全隱藏資料的Safe Folder功能 Android TV新主界面將顯示電影、電視節目和應用推薦內容 泄露的Android檔案暗示了傳說中的谷歌Pixel 5a與折疊屏新機 谷歌發布Andro ......

    uj5u.com 2020-09-10 07:00:37 more
  • AutoFitTextureView Error inflating class

    報錯: Binary XML file line #0: Binary XML file line #0: Error inflating class xxx.AutoFitTextureView 解決: <com.example.testy2.AutoFitTextureView android: ......

    uj5u.com 2020-09-10 07:00:41 more
  • 根據Uri,Cursor沒有獲取到對應的屬性

    Android: 背景:呼叫攝像頭,拍攝視頻,指定保存的地址,但是回傳的Cursor檔案,只有名稱和大小的屬性,沒有其他諸如時長,連ID屬性都沒有 使用 cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATIO ......

    uj5u.com 2020-09-10 07:00:44 more
  • Android連載29-持久化技術

    一、持久化技術 我們平時所使用的APP產生的資料,在記憶體中都是瞬時的,會隨著斷電、關機等丟失資料,因此android系統采用了持久化技術,用于存盤這些“瞬時”資料 持久化技術包括:檔案存盤、SharedPreference存盤以及資料庫存盤,還有更復雜的SD卡記憶體儲。 二、檔案存盤 最基本存盤方式, ......

    uj5u.com 2020-09-10 07:00:47 more
  • Android Camera2Video整合到自己專案里

    背景: Android專案里呼叫攝像頭拍攝視頻,原本使用的 MediaStore.ACTION_VIDEO_CAPTURE, 后來因專案需要,改成了camera2 1.Camera2Video 官方demo有點問題,下載后,不能直接整合到專案 問題1.多次拍攝視頻崩潰 問題2.雙擊record按鈕, ......

    uj5u.com 2020-09-10 07:00:50 more
  • Android 開發技術周報 Issue#293

    新聞 谷歌為Android TV開發者提供多種新功能 Android 11將自動填表功能整合到鍵盤輸入建議中 谷歌宣布Android Auto即將支持更多的導航和數字停車應用 谷歌Pixel 5只有XL版本 搭載驍龍765G且將比Pixel 4更便宜 [圖]Wear OS將迎來重磅更新:應用啟動時間 ......

    uj5u.com 2020-09-10 07:01:38 more
  • 海豚星空掃碼投屏 Android 接收端 SDK 集成 六步驟

    掃碼投屏,開放網路,獨占設備,不需要額外下載軟體,微信掃碼,發現設備。支持標準DLNA協議,支持倍速播放。視頻,音頻,圖片投屏。好點意思。還支持自定義基于 DLNA 擴展的操作動作。好像要收費,沒體驗。 這里簡單記錄一下集成程序。 一 跟目錄的build.gradle添加私有mevan倉庫 mave ......

    uj5u.com 2020-09-10 07:01:43 more
最新发布
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:40:31 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:40:11 more
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:39:36 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:39:13 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:16:23 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:16:15 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:15:46 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:14:53 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:14:08 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:08:34 more