<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > 基于STEP FPGA的PCF8591的DAC(I2C)功能驅動(dòng)

基于STEP FPGA的PCF8591的DAC(I2C)功能驅動(dòng)

作者: 時(shí)間:2023-12-01 來(lái)源:電子森林 收藏

硬件說(shuō)明

PCF8591是集成了4路ADC和1路DAC的芯片,使用I2C總線(xiàn)通信。
I2C總線(xiàn)是由Philips公司開(kāi)發(fā)的一種簡(jiǎn)單、雙向二線(xiàn)制同步串行總線(xiàn)。它只需要兩根線(xiàn)即可在連接于總線(xiàn)上的器件之間傳送信息。主器件用于啟動(dòng)總線(xiàn)傳送數據,并產(chǎn)生時(shí)鐘以開(kāi)放傳送的器件,此時(shí)任何被尋址的器件均被認為是從器件。如果主機要發(fā)送數據給從器件,則主機首先尋址從器件,然后主動(dòng)發(fā)送數據至從器件,最后由主機終止數據傳送;如果主機要接收從器件的數據,首先由主器件尋址從器件,然后主機接收從器件發(fā)送的數據,最后由主機終止接收過(guò)程。這里不做過(guò)多的講解,硬件連接如下:

本文引用地址:http://dyxdggzs.com/article/202312/453482.htm

本設計的硬件連接如下

本設計中FPGA作為I2C主設備,PCF8591作為I2C從設備,從設備的地址由固定地址和可編程地址組成,我們的外設底板已將可編程地址A0、A1、A2接地,所以7位地址為7'h48,加上最低位的讀寫(xiě)控制,所以給PCF8591寫(xiě)數據時(shí)的尋址地址為8'h90,對PCF8591讀數據時(shí)的尋址地址為8'h91。如下

PCF8591集成了很多功能,當需要不同的功能時(shí)要對PCF8591做相應的配置,配置數據存儲在名為CONTROL BYTE的寄存器中,下圖展示了寄存器中部分bit的功能,詳細請參考PCF8591的datasheet,本設計中我們只使用DAC功能,配置數據為8'h40。

本設計中我們需要的通信過(guò)程具體為:開(kāi)始–寫(xiě)尋址–讀響應–寫(xiě)配置數據–讀響應–[寫(xiě)DAC數據–讀響應]循環(huán)–結束

通過(guò)上面的介紹大家應該對如何驅動(dòng)PCF8591進(jìn)行DAC采樣有了整體的概念,還有一些細節就是I2C通信的時(shí)序明細,如下圖


Verilog代碼

// --------------------------------------------------------------------
// >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
// --------------------------------------------------------------------
// Module: DAC_I2C
// 
// Author: Step
// 
// Description: DAC_I2C
// --------------------------------------------------------------------
// Code Revision History :
// --------------------------------------------------------------------
// Version: |Mod. Date:   |Changes Made:
// V1.1     |2016/10/30   |Initial ver
// --------------------------------------------------------------------
module DAC_I2C(
	input				clk_in,		//系統時(shí)鐘
	input				rst_n_in,	//系統復位,低有效 	
	output	reg			dac_done,	//DAC采樣完成標志
	input		[7:0]	dac_data,	//DAC采樣數據 	
	output				scl_out,	//I2C總線(xiàn)SCL
	inout				sda_out		//I2C總線(xiàn)SDA
	); 	
	parameter	CNT_NUM	=	15; 	
	localparam	IDLE	=	3'd0;
	localparam	MAIN	=	3'd1;
	localparam	START	=	3'd2;
	localparam	WRITE	=	3'd3;
	localparam	STOP	=	3'd4; 	//根據PCF8591的datasheet,I2C的頻率最高為100KHz,
	//我們準備使用4個(gè)節拍完成1bit數據的傳輸,所以需要400KHz的時(shí)鐘觸發(fā)完成該設計
	//使用計數器分頻產(chǎn)生400KHz時(shí)鐘信號clk_400khz
	reg					clk_400khz;
	reg		[9:0]		cnt_400khz;
	always@(posedge clk_in or negedge rst_n_in) begin
		if(!rst_n_in) begin
			cnt_400khz <= 10'd0;
			clk_400khz <= 1'b0;
		end else if(cnt_400khz >= CNT_NUM-1) begin
			cnt_400khz <= 10'd0;
			clk_400khz <= ~clk_400khz;
		end else begin
			cnt_400khz <= cnt_400khz + 1'b1;
		end
	end 	reg		[7:0]		adc_data_r;
	reg					scl_out_r;
	reg					sda_out_r;
	reg		[2:0]		cnt;
	reg		[2:0]		cnt_main;
	reg		[7:0]		data_wr;
	reg		[2:0]		cnt_start;
	reg		[2:0]		cnt_write;
	reg		[2:0]		cnt_stop;
	reg		[2:0] 		state; 	
	always@(posedge clk_400khz or negedge rst_n_in) begin
		if(!rst_n_in) begin	//如果按鍵復位,將相關(guān)數據初始化
			scl_out_r <= 1'd1;
			sda_out_r <= 1'd1;
			cnt <= 1'b0;
			cnt_main <= 1'b0;
			cnt_start <= 1'b0;
			cnt_write <= 3'd0;
			cnt_stop <= 1'd0;
			dac_done <= 1'b1;
			state <= IDLE;
		end else begin
			case(state)
				IDLE:begin	//軟件自復位,主要用于程序跑飛后的處理
						scl_out_r <= 1'd1;
						sda_out_r <= 1'd1;
						cnt <= 1'b0;
						cnt_main <= 1'b0;
						cnt_start <= 1'b0;
						cnt_write <= 3'd0;
						cnt_stop <= 1'd0;
						dac_done <= 1'b1;
						state <= MAIN;
					end
				MAIN:begin
						if(cnt_main >= 3'd3) cnt_main <= 3'd3;  //對MAIN中的子狀態(tài)執行控制cnt_main
						else cnt_main <= cnt_main + 1'b1;
						case(cnt_main)
							3'd0:	begin state <= START; 
							end	//I2C通信時(shí)序中的START
							3'd1:	begin data_wr <= 8'h90; 
							state <= WRITE; end	
							//A0,A1,A2都接了GND,寫(xiě)地址為8'h90
							3'd2:	begin data_wr <= 8'h40; 
							state <= WRITE; 
							end	
							//control byte為8'h40,打開(kāi)DAC功能
							3'd3:	begin data_wr <= dac_data; 
							state <= WRITE; 
							dac_done <= 1'b0; 
							end	//需要進(jìn)行DAC轉換的數據
							3'd4:	begin state <= STOP; 
							end	
							//I2C通信時(shí)序中的結束STOP
							default: state <= IDLE;	//如果程序失控,進(jìn)入IDLE自復位狀態(tài)
						endcase
					end
				START:begin	//I2C通信時(shí)序中的起始START
						if(cnt_start >= 3'd5) cnt_start <= 1'b0;	
						//對START中的子狀態(tài)執行控制cnt_start
						else cnt_start <= cnt_start + 1'b1;
						case(cnt_start)
							3'd0:	begin sda_out_r <= 1'b1; 
							scl_out_r <= 1'b1; end	//將SCL和SDA拉高,保持4.7us以上
							3'd1:	begin sda_out_r <= 1'b1; 
							scl_out_r <= 1'b1; end	//clk_400khz每個(gè)周期2.5us,需要兩個(gè)周期
							3'd2:	begin sda_out_r <= 1'b0; 
							end	//SDA拉低到SCL拉低,保持4.0us以上
							3'd3:	begin sda_out_r <= 1'b0; 
							end	//clk_400khz每個(gè)周期2.5us,需要兩個(gè)周期
							3'd4:	begin scl_out_r <= 1'b0; 
							end	//SCL拉低,保持4.7us以上
							3'd5:	begin scl_out_r <= 1'b0; 
							state <= MAIN; 
							end	//clk_400khz每個(gè)周期2.5us,需要兩個(gè)周期,返回MAIN
							default: state <= IDLE;	//如果程序失控,進(jìn)入IDLE自復位狀態(tài)
						endcase
					end
				WRITE:begin	//I2C通信時(shí)序中的寫(xiě)操作WRITE和相應判斷操作ACK
						if(cnt <= 3'd6) begin	//共需要發(fā)送8bit的數據,這里控制循環(huán)的次數
							if(cnt_write >= 3'd3) begin cnt_write <= 1'b0; 
							cnt <= cnt + 1'b1; 
							end
							else begin cnt_write <= cnt_write + 1'b1; 
							cnt <= cnt; 
							end
						end else begin
							if(cnt_write >= 3'd7) begin cnt_write <= 1'b0; 
							cnt <= 1'b0; 
							end	//兩個(gè)變量都恢復初值
							else begin cnt_write <= cnt_write + 1'b1; 
							cnt <= cnt; 
							end
						end
						case(cnt_write)
							//按照I2C的時(shí)序傳輸數據
							3'd0:	begin scl_out_r <= 1'b0; 
							sda_out_r <= data_wr[7-cnt]; 
							end	//SCL拉低,并控制SDA輸出對應的位
							3'd1:	begin scl_out_r <= 1'b1; 
							end	//SCL拉高,保持4.0us以上
							3'd2:	begin scl_out_r <= 1'b1; 
							end	//clk_400khz每個(gè)周期2.5us,需要兩個(gè)周期
							3'd3:	begin scl_out_r <= 1'b0; 
							end	//SCL拉低,準備發(fā)送下1bit的數據
							//獲取從設備的響應信號并判斷
							3'd4:	begin sda_out_r <= 1'bz; dac_done <= 1'b1; 
							end	//釋放SDA線(xiàn),準備接收從設備的響應信號
							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'd7:	begin scl_out_r <= 1'b0; 
							state <= MAIN; 
							end	//SCL拉低,返回MAIN狀態(tài)
							default: state <= IDLE;	//如果程序失控,進(jìn)入IDLE自復位狀態(tài)
						endcase
					end
				STOP:begin	//I2C通信時(shí)序中的結束STOP
						if(cnt_stop >= 3'd5) cnt_stop <= 1'b0;	//對STOP中的子狀態(tài)執行控制cnt_stop
						else cnt_stop <= cnt_stop + 1'b1;
						case(cnt_stop)
							3'd0:	begin sda_out_r <= 1'b0; 
							end	//SDA拉低,準備STOP
							3'd1:	begin sda_out_r <= 1'b0; 
							end	//SDA拉低,準備STOP
							3'd2:	begin scl_out_r <= 1'b1; 
							end	//SCL提前SDA拉高4.0us
							3'd3:	begin scl_out_r <= 1'b1; 
							end	//SCL提前SDA拉高4.0us
							3'd4:	begin sda_out_r <= 1'b1; 
							end	//SDA拉高
							3'd5:	begin sda_out_r <= 1'b1; 
							state <= MAIN; 
							end	//完成STOP操作,返回MAIN狀態(tài)
							default: state <= IDLE;	//如果程序失控,進(jìn)入IDLE自復位狀態(tài)
						endcase
					end
				default:;
			endcase
		end
	end 	assign	scl_out = scl_out_r;	//對SCL端口賦值
	assign	sda_out = sda_out_r;	//對SDA端口賦值 endmodule

小結

本節主要為大家講解了使用I2C驅動(dòng)PCF8591的DAC功能的原理及軟件設計,需要大家掌握的同時(shí)自己創(chuàng )建工程,通過(guò)整個(gè)設計流程,生成FPGA配置文件加載測試。



評論


相關(guān)推薦

技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>