主頁 >  其他 > BH1750環境光強度傳感器FPGA驅動

BH1750環境光強度傳感器FPGA驅動

2020-12-24 11:00:17 其他

BH1750環境光強度傳感器FPGA驅動

1. BH1750介紹
BH1750是一種用于兩線式串行總線介面的數字型光強度傳感器集成電路,這種集成電路可以根據收集的光線強度資料來調整液晶或者鍵盤背景燈的亮度,利用它的高解析度可以探測較大范圍的光強度變化,(1x-65535lx)
特點:
1.支持IIC介面,
2.接近視覺靈敏度的光譜靈敏度特性(峰值靈敏度波長典型值:560nm).
3.輸出對應亮度的數字值,
4.對應廣泛的輸入光范圍(相當于1-65535lx),
5.通過降低功率功能,實作低電流化,

引腳名稱介紹
GND電源地
VCC供電電源
SCLIIC時鐘線
SDAIIC資料線,雙向IO口
ADDRIIC地址線,接GND時地址為:0100011;接VCC時地址為:1011100

2. BH1750的IIC通信


上面所示是BH1750用IIC通信協議實作測量的步驟,如果忽略第二步的等待時間,這是一個標準的IIC讀取程序,因此為了方便,可以在標準的IIC通信協議上做修改,再第二次寫入器件地址前做一個延時等待判斷,當延時時間為200ms時,開始執行第三步的操作,同時需要注意,BH1750的輸出資料為16bit,IIC讀取時要改為16位讀取,

3. 整體模塊

key_filter模塊是按鍵輸入的消抖模塊,當按下按鍵是,FPGA開始用IIC通信協議向BH1750通信,經過延時等待后得到資料,將資料利用UART串口模塊發送到上位機計算使用,

4. 代碼

按鍵消抖

module key_filter(Clk,Rst_n,key_in,key_flag,key_state);

	input Clk;
	input Rst_n;
	input key_in;
	
	output reg key_flag;
	output reg key_state;
	
	localparam
		IDEL		= 4'b0001,
		FILTER0	= 4'b0010,
		DOWN		= 4'b0100,
		FILTER1 	= 4'b1000;
		
	reg [3:0]state;
	reg [19:0]cnt;
	reg en_cnt;	//使能計數暫存器
	
//對外部輸入的異步信號進行同步處理
	reg key_in_sa,key_in_sb;
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)begin
		key_in_sa <= 1'b0;
		key_in_sb <= 1'b0;
	end
	else begin
		key_in_sa <= key_in;
		key_in_sb <= key_in_sa;	
	end
	
	reg key_tmpa,key_tmpb;
	wire pedge,nedge;
	reg cnt_full;//計數滿標志信號
	
//使用D觸發器存盤兩個相鄰時鐘上升沿時外部輸入信號(已經同步到系統時鐘域中)的電平狀態
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)begin
		key_tmpa <= 1'b0;
		key_tmpb <= 1'b0;
	end
	else begin
		key_tmpa <= key_in_sb;
		key_tmpb <= key_tmpa;	
	end

//產生跳變沿信號	
	assign nedge = !key_tmpa & key_tmpb;
	assign pedge = key_tmpa & (!key_tmpb);
	
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)begin
		en_cnt <= 1'b0;
		state <= IDEL;
		key_flag <= 1'b0;
		key_state <= 1'b1;
	end
	else begin
		case(state)
			IDEL :
				begin
					key_flag <= 1'b0;
					if(nedge)begin
						state <= FILTER0;
						en_cnt <= 1'b1;
					end
					else
						state <= IDEL;
				end
					
			FILTER0:
				if(cnt_full)begin
					key_flag <= 1'b1;
					key_state <= 1'b0;
					en_cnt <= 1'b0;
					state <= DOWN;
				end
				else if(pedge)begin
					state <= IDEL;
					en_cnt <= 1'b0;
				end
				else
					state <= FILTER0;
					
			DOWN:
				begin
					key_flag <= 1'b0;
					if(pedge)begin
						state <= FILTER1;
						en_cnt <= 1'b1;
					end
					else
						state <= DOWN;
				end
			
			FILTER1:
				if(cnt_full)begin
					key_flag <= 1'b1;
					key_state <= 1'b1;
					state <= IDEL;
				end
				else if(nedge)begin
					en_cnt <= 1'b0;
					state <= DOWN;
				end
				else
					state <= FILTER1;
			
			default:
				begin 
					state <= IDEL; 
					en_cnt <= 1'b0;		
					key_flag <= 1'b0;
					key_state <= 1'b1;
				end
				
		endcase	
	end
	
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		cnt <= 20'd0;
	else if(en_cnt)
		cnt <= cnt + 1'b1;
	else
		cnt <= 20'd0;
			
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		cnt_full <= 1'b0;
	else if(cnt == 4_999)
		cnt_full <= 1'b1;
	else
		cnt_full <= 1'b0;	

endmodule

IIC驅動

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

          //i2c interface
          input                i2c_exec   ,      // I2C觸發執行信號
          input                bit_ctrl   ,      // 字地址位控制(16b/8b)
          input                i2c_rh_wl  ,      // I2C讀寫控制信號
          input        [ 7:0]  i2c_addr   ,      // I2C器件內地址
          input        [ 7:0]  i2c_data_w ,      // I2C要寫的資料
          output  reg  [ 15: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    [15:0]  data_r      ;                     // 讀取的資料
reg    [ 7:0]  data_wr_t   ;                     // I2C需寫的資料的臨時寄存
reg    [ 9:0]  clk_cnt     ;                     // 分頻時鐘計數

reg    [15:0]  delay_cnt   ;                     // 延時200ms時鐘計數
reg            delay_done  ;                     // 延時結束

//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

//延時200ms等待BH1750采樣轉換結束
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        delay_cnt <= 16'd0;
    end
    else if((cur_state ==st_addr_rd) && (delay_cnt < 16'd50_000)) 
       delay_cnt <= delay_cnt + 1'b1;
    else
        delay_cnt <= 16'd0;
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        delay_done <= 1'b0;
    end
    else if(delay_cnt == 16'd49_999) 
       delay_done <= ~delay_done;

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
    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                          // 寫資料(8 bit)
                case(cnt)
                    7'd0: begin
                        sda_out <= data_wr_t[7];       // I2C寫8位資料
                        sda_dir <= 1'b1;
                    end
                    7'd1 : scl <= 1'b1;
                    7'd3 : scl <= 1'b0;
                    7'd4 : sda_out <= data_wr_t[6];
                    7'd5 : scl <= 1'b1;
                    7'd7 : scl <= 1'b0;
                    7'd8 : sda_out <= data_wr_t[5];
                    7'd9 : scl <= 1'b1;
                    7'd11: scl <= 1'b0;
                    7'd12: sda_out <= data_wr_t[4];
                    7'd13: scl <= 1'b1;
                    7'd15: scl <= 1'b0;
                    7'd16: sda_out <= data_wr_t[3];
                    7'd17: scl <= 1'b1;
                    7'd19: scl <= 1'b0;
                    7'd20: sda_out <= data_wr_t[2];
                    7'd21: scl <= 1'b1;
                    7'd23: scl <= 1'b0;
                    7'd24: sda_out <= data_wr_t[1];
                    7'd25: scl <= 1'b1;
                    7'd27: scl <= 1'b0;
                    7'd28: sda_out <= data_wr_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_addr_rd: begin                          // 寫地址以進行讀資料
               if(delay_done) 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
            end
            st_data_rd: begin                          // 讀取資料(16 bit)
                case(cnt)
                    7'd0: sda_dir <= 1'b0;
                    7'd1: begin
                        data_r[15] <= sda_in;
                        scl       <= 1'b1;
                    end
                    7'd3: scl  <= 1'b0;
                    7'd5: begin
                        data_r[14] <= sda_in ;
                        scl       <= 1'b1   ;
                    end
                    7'd7: scl  <= 1'b0;
                    7'd9: begin
                        data_r[13] <= sda_in;
                        scl       <= 1'b1  ;
                    end
                    7'd11: scl  <= 1'b0;
                    7'd13: begin
                        data_r[12] <= sda_in;
                        scl       <= 1'b1  ;
                    end
                    7'd15: scl  <= 1'b0;
                    7'd17: begin
                        data_r[11] <= sda_in;
                        scl       <= 1'b1  ;
                    end
                    7'd19: scl  <= 1'b0;
                    7'd21: begin
                        data_r[10] <= sda_in;
                        scl       <= 1'b1  ;
                    end
                    7'd23: scl  <= 1'b0;
                    7'd25: begin
                        data_r[9] <= sda_in;
                        scl       <= 1'b1  ;
                    end
                    7'd27: scl  <= 1'b0;
                    7'd29: begin
                        data_r[8] <= sda_in;
                        scl       <= 1'b1  ;
                    end
						  7'd31: begin
                        data_r[7] <= sda_in;
                        scl       <= 1'b1;
                    end
                    7'd33: scl  <= 1'b0;
                    7'd35: begin
                        data_r[6] <= sda_in ;
                        scl       <= 1'b1   ;
                    end
                    7'd37: scl  <= 1'b0;
                    7'd39: begin
                        data_r[5] <= sda_in;
                        scl       <= 1'b1  ;
                    end
                    7'd41: scl  <= 1'b0;
                    7'd43: begin
                        data_r[4] <= sda_in;
                        scl       <= 1'b1  ;
                    end
                    7'd45: scl  <= 1'b0;
                    7'd47: begin
                        data_r[3] <= sda_in;
                        scl       <= 1'b1  ;
                    end
                    7'd49: scl  <= 1'b0;
                    7'd51: begin
                        data_r[2] <= sda_in;
                        scl       <= 1'b1  ;
                    end
                    7'd53: scl  <= 1'b0;
                    7'd55: begin
                        data_r[1] <= sda_in;
                        scl       <= 1'b1  ;
                    end
                    7'd57: scl  <= 1'b0;
                    7'd59: begin
                        data_r[0] <= sda_in;
                        scl       <= 1'b1  ;
                    end
						 
                    7'd61: scl  <= 1'b0;
                    7'd62: begin
                        sda_dir <= 1'b1;              // 非應答
                        sda_out <= 1'b1;
                    end
                    7'd63: scl     <= 1'b1;
                    7'd64: st_done <= 1'b1;
                    7'd65: 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

串口模塊

module uart_byte_tx(
   Clk,
	Rst,
	data_byte,
	send_en,
	baud_set,
	
	Rs232_Tx,
	Tx_Done,
	uart_state

  );
  
   input Clk;
	input Rst;
	input [15:0]data_byte;
	input send_en;
	input [2:0]baud_set;
	
	output reg Rs232_Tx;
	output reg Tx_Done;
	output reg uart_state;
	
	reg [15:0]div_cnt;//分頻計數器
	reg bps_clk;//波特率時鐘
	reg [15:0]bps_DR;//分頻計數最大值
	reg [4:0]bps_cnt;//波特率時鐘計數器
	
	
	reg [15:0]r_data_byte;
	
	localparam start_bit = 1'b0;
	localparam stop_bit = 1'b1;

	
	always@(posedge Clk or negedge Rst)
	if(!Rst)
	   uart_state <= 1'b0;
	else if(send_en )
	   uart_state <= 1'b1;
	else if(Tx_Done)
	   uart_state <= 1'b0;
	else
	   uart_state <= uart_state;
	
	
	always@(posedge Clk or negedge Rst)
	if(!Rst)
	   r_data_byte <= 8'd0;
	else if(send_en)
	   r_data_byte <= data_byte;
	else
	   r_data_byte <= r_data_byte;
		
	
	always@(posedge Clk or negedge Rst)
	if(!Rst)
	   bps_DR <= 16'd5207;
	else begin
	   case(baud_set)
		  0:bps_DR <= 16'd5207;
		  1:bps_DR <= 16'D2603;
		  2:bps_DR <= 16'd1301;
		  3:bps_DR <= 16'd867;
		  4:bps_DR <= 16'd433;
		  default:bps_DR <= 16'd5207;
		endcase
	 end
		  
	
	
//counter
	always@(posedge Clk or negedge Rst)
	if(!Rst)
	   div_cnt <= 16'd0;
	else if(uart_state)begin
	     if(div_cnt == bps_DR)
		     div_cnt <= 16'd0;
		  else
		     div_cnt <=div_cnt + 1'b1;
		  end
	else
		div_cnt <= 16'd0;
	
//bps_clk	
	always@(posedge Clk or negedge Rst)
	if(!Rst)
	   bps_clk <= 1'b0;
	else if(div_cnt == 1'b1)
	   bps_clk <=1'b1;
	else
	   bps_clk <= 1'b0;
		
	 
   always@(posedge Clk or negedge Rst)
	if(!Rst)
      bps_cnt <= 5'd0;
	else if(Tx_Done)
      bps_cnt <= 5'd0;
	else if(bps_clk)
      bps_cnt <= bps_cnt + 1'b1;
	else
      bps_cnt <= bps_cnt;
		

   always@(posedge Clk or negedge Rst)
	if(!Rst)
	   Tx_Done <= 1'b0;
	else if(bps_cnt == 5'd21)
	   Tx_Done <= 1'b1;
	else
	   Tx_Done <= 1'b0;
		
		
	always@(posedge Clk or negedge Rst)
	if(!Rst)
	   Rs232_Tx <= 1'b1;
	else begin
	   case(bps_cnt)
		   0:Rs232_Tx <= 1'b1;
			1:Rs232_Tx <= start_bit;
			2:Rs232_Tx <= r_data_byte[8];
			3:Rs232_Tx <= r_data_byte[9];
			4:Rs232_Tx <= r_data_byte[10];
			5:Rs232_Tx <= r_data_byte[11];
			6:Rs232_Tx <= r_data_byte[12];
			7:Rs232_Tx <= r_data_byte[13];
			8:Rs232_Tx <= r_data_byte[14];
			9:Rs232_Tx <= r_data_byte[15];
			10:Rs232_Tx <= stop_bit;
			11:Rs232_Tx <= 1'b1;
			12:Rs232_Tx <= start_bit;
			13:Rs232_Tx <= r_data_byte[0];
			14:Rs232_Tx <= r_data_byte[1];
			15:Rs232_Tx <= r_data_byte[2];
			16:Rs232_Tx <= r_data_byte[3];
			17:Rs232_Tx <= r_data_byte[4];
			18:Rs232_Tx <= r_data_byte[5];
			19:Rs232_Tx <= r_data_byte[6];
			20:Rs232_Tx <= r_data_byte[7];
			21:Rs232_Tx <= stop_bit;
			default:Rs232_Tx <= 1'b1;
		endcase
	 end
endmodule 

頂層模塊

module BH1750_CTRL(

  input clk,
  input rst_n,
  input key3,
  
  output rx232_tx,
  
  output scl,
  inout sda

);

  wire                  key_flag        ;
  wire                  key_state       ;  
  wire                  start_en        ;   //按鍵啟動信號

  wire                  en              ;  //定時1秒啟動
  wire                  i2c_exec        ;  //I2C觸發執行信號        
  wire                  i2c_done        ;  //I2C暫存器配置完成信號
  wire                  i2c_dri_clk     ;  //I2C操作時鐘
  wire   [15:0]         i2c_data_r      ;  //I2C讀出資料
  
  parameter  SLAVE_ADDR = 7'h23        ;  //BH1750的器件地址7'h3c
  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

  assign start_en = key_flag && !key_state ;
 
 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           (start_en  ),   
    .bit_ctrl           (BIT_CTRL  ),   
    .i2c_rh_wl          (1'b1),             //固定為讀操作              
    .i2c_addr           (8'h10),   
    .i2c_data_w         (0),   
    .i2c_data_r         (i2c_data_r),   
    .i2c_done           (i2c_done  ),   
    .scl                (scl   ),   
    .sda                (sda   ),   
        
    .dri_clk            (i2c_dri_clk)       //I2C操作時鐘
); 

uart_byte_tx u_uart_byte_tx(
	.Clk       (clk),
	.Rst       (rst_n),
	.data_byte (i2c_data_r),
	.send_en   (i2c_done),
	.baud_set  (3'd0),
	.Rs232_Tx  (rx232_tx),
	.Tx_Done   (),
	.uart_state()
);

key_filter u_key_filter(
   .Clk      (i2c_dri_clk),
	.Rst_n    (rst_n),
	.key_in   (key3),
	.key_flag (key_flag),
	.key_state(key_state)

);

endmodule 

注意:按鍵消抖模塊的驅動時鐘使用IIC驅動模塊的輸出時鐘1MHz,如果使用50MHz的輸入時鐘,則按鍵啟動信號的高電平持續周期時間太短,可能不會被IIC模塊啟動信號捕捉到,從而導致按鍵按下,但IIC通信并未開始,

5. 驗證
將程式下載至開發板,將芯片模塊引腳連接好,打開串口除錯助手,波特率選擇9600,無檢驗位,資料位8位,1位停止位,按下按鍵,得到16位環境光強度資料,用光照射芯片,再按下按鍵,可以看到資料變大,多次測驗無誤,證明驗證成功,PS:得到的161位資料還需要轉換成十進制資料進行計算才可以得到光強資料,單位lx,請自行查閱手冊得到計算公式和引數,

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

標籤:其他

上一篇:js獲取本地天氣引數(免費實況天氣介面)

下一篇:施耐德開放自動化平臺初體驗(3)

標籤雲
其他(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)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more