⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ds1631control.v

📁 一个完整的通过IIC总线控制Dallas公司的温度传感芯片DS1631采集温度数据的Verilog代码
💻 V
📖 第 1 页 / 共 2 页
字号:

module 1631Control(clk,rst,ReadT,SCL,SDA,SegEn,SegData,key_row_low);

input clk,rst;
output SCL;//I2C时钟线
inout  SDA;//I2C数据线
input ReadT;//读温度命令
output key_row_low; //输出一个低电平给矩阵键盘的某一行
output[7:0] SegEn; //数码管使能
output[7:0] SegData;//数码管数据

reg SCL;
reg[7:0] SegEn;
reg[7:0] SegData;
reg[3:0] dataout_code; //每一个数码管的显示数值,0~F

//reg[7:0] seg_data_buf;
reg[15:0] cnt_scan;
reg sda_buf;//sda输入输出数据缓存
reg link;   //sda输出标志
reg phase0,phase1,phase2,phase3;//一个scl时钟周期的四个相位阶段,将一个scl周期分为4段
//phase0对应scl的上升沿时刻,phase2对应scl的下降沿时刻,phase1对应从scl高电平的中间时刻,phase3对应从scl低电平的中间时刻,
reg[7:0] clk_div;//分频计数器
reg[1:0] main_state;
reg[2:0] i2c_state;//对i2c操作的状态
reg[3:0] inner_state;//i2c每一操作阶段内部状态
reg[19:0] cnt_delay;//按键延时计数器
reg start_delaycnt;//按键延时开始
reg[7:0] readMSData_reg;//读回高8位数据的寄存器
reg[7:0] readLSData_reg;//读回低8位数据的寄存器

/*用于显示十进制温度数据*/
reg[3:0] baiwei;  //十进制数百位
reg[3:0] shiwei;
reg[3:0] gewei;
reg[3:0] xiao1;
reg[3:0] xiao2;
reg[3:0] xiao3;
reg[3:0] xiao4;


parameter div_parameter=100;// 分频系数,AT24C02最大支持400K时钟速率

/****************SDA内部状态*******************/
parameter start=4'b0000, //开始
		  first=4'b0001, //第1位
		  second=4'b0010,//第2位
		  third=4'b0011, //第3位
		  fourth=4'b0100, //第4位
		  fifth=4'b0101, //第5位
		  sixth=4'b0110, //第6位
		  seventh=4'b0111, //第7位
		  eighth=4'b1000, //第8位
		  ack=4'b1001,   //确认位
		  stop=4'b1010; //结束位
		
		

/****************I2C总线工作状态****************/		
parameter ini=3'b000, //初始化状态
		  sendaddr=3'b001, //发送地址状态
		  write_data=3'b010, //写数据状态
		  read_ms_data=3'b011, //读高8位数据状态
		  read_ls_data=3'b100, //读低8位数据状态
		  read_ini=6'b101; //发送读信息状态

assign key_row_low=0;
assign SDA=(link)? sda_buf:1'bz;
//assign seg_data_buf = readData_reg;

//按键延时处理
always@(posedge clk or negedge rst)
begin
	if(!rst)
		cnt_delay<=0;
	else begin
		if(start_delaycnt) begin
			if(cnt_delay!=20'd800000)
				cnt_delay<=cnt_delay+1;
			else
				cnt_delay<=0;
		 end
	 end
end

//scl时钟周期的四个相位生成
always@(posedge clk or negedge rst)
begin
	if(!rst) begin
		clk_div<=0;
		phase0<=0;
		phase1<=0;
		phase2<=0;
		phase3<=0;
	 end
	else begin
		if(clk_div!=div_parameter-1)
			clk_div<=clk_div+1;
		else
			clk_div<=0;
		if(phase0)
			phase0<=0;	
		else if(clk_div==99) 
			phase0<=1;
		if(phase1)
			phase1<=0;
		else if(clk_div==24)
			phase1<=1;
		if(phase2)
			phase2<=0;
		else if(clk_div==49)
			phase2<=1;
		if(phase3)
			phase3<=0;
		else if(clk_div==74)
			phase3<=1;
	 end
end


//////////////读温度I2C控制时序SDA配置/////////////
always@(posedge clk or negedge rst)
begin
	if(!rst) begin
		start_delaycnt<=0;
		main_state<=2'b00;
		i2c_state<=ini;
		inner_state<=start;
		SCL<=1;
		sda_buf<=1;
		link<=0;
		readMSData_reg<=0;
		readLSData_reg<=0;
	 end
	else begin
		case(main_state)
		    /*************等待读写要求*************/
			2'b00: begin  
				//writeData_reg<=data_in;
				SCL<=1;
				sda_buf<=1;
				link<=0;
				inner_state<=start;
				i2c_state<=ini;
						
				if(cnt_delay==0) 
						start_delaycnt<=1;
				else if(cnt_delay==20'd800000) begin
						start_delaycnt<=0;						
						main_state<=2'b01;						
				end
				
			 end
			
			/*************读Temperature的SDA配置*************/
			2'b01: begin  
				if(phase0)
					SCL<=1;
				else if(phase2)
					SCL<=0;
					
				case(i2c_state)
				/*****初始化输出*****/
				ini: begin   
					case(inner_state)
					    //配置启动,S=0
						start: begin
							if(phase1) begin
								link<=1;
								sda_buf<=0;    
							end
						//配置8位写控制字节1001xxxW(xxx为芯片地址A2A1A0)
							if(phase3&&link) begin   
								inner_state<=first;
								sda_buf<=1;   //第8位
								link<=1;
							end
						 end
						first: 
							if(phase3) begin
								sda_buf<=0;   //第7位
								link<=1;
								inner_state<=second;
							 end
						second:
							if(phase3) begin
								sda_buf<=0;   //第6位
								link<=1;
								inner_state<=third;
							 end
						third:
							if(phase3) begin
								sda_buf<=1;   //第5位
								link<=1;
								inner_state<=fourth;
							 end
						fourth:
							if(phase3) begin
								sda_buf<=0;   //A2
								link<=1;
								inner_state<=fifth;
							 end
						fifth:
							if(phase3) begin
								sda_buf<=0;   //A1
								link<=1;
								inner_state<=sixth;
							 end
						sixth:
							if(phase3) begin
								sda_buf<=0;   //A0
								link<=1;
								inner_state<=seventh;
							 end
						seventh:
							if(phase3) begin
								sda_buf<=0;   //W=0,写
								link<=1;
								inner_state<=eighth;
							 end
						//接收芯片应答,ACK
						eighth:
							if(phase3) begin
								link<=0;
								inner_state<=ack;
							 end
						ack: begin  
							if(phase0) 
								sda_buf<=SDA; //接收应答
							if(phase1) begin
								if(sda_buf==1) 
									main_state<=2'b00;
							 end
							if(phase3) begin
								link<=1;
								sda_buf<=1;  //命令字节第8位
								inner_state<=first;
								i2c_state<=sendaddr;
							end
						 end
					endcase
				end
				/*****命令字节输出*****/
				sendaddr: begin  //
					case(inner_state)
					//配置命令字节,读温度为10101010
						first: 
							if(phase3) begin
								link<=1;
								sda_buf<=0;  //第7位
								inner_state<=second;
							 end
						second:
							if(phase3) begin
								link<=1;
								sda_buf<=1;  //第6位
								inner_state<=third;
							 end
						third:
							if(phase3) begin
								link<=1;
								sda_buf<=0;  //第5位
								inner_state<=fourth;
							 end
						fourth:
							if(phase3) begin
								link<=1;
								sda_buf<=1;  //第4位
								inner_state<=fifth;
							 end
						fifth:
							if(phase3) begin
								link<=1;
								sda_buf<=0;  //第3位
								inner_state<=sixth;
							 end
						sixth:
							if(phase3) begin
								link<=1;
								sda_buf<=1;  //第2位
								inner_state<=seventh;
							 end
						seventh:
							if(phase3) begin
								link<=1;
								sda_buf<=0;  //第1位
								inner_state<=eighth;
							end
						//接收芯片应答,ACK
						eighth:
							if(phase3) begin
								link<=0;
								inner_state<=ack;
							 end
						ack: begin
							if(phase0) 
								sda_buf<=SDA;  //接收应答
							if(phase1) begin
								if(sda_buf==1) 
									main_state<=2'b00;
							 end
							if(phase3) begin
								link<=1;
								sda_buf<=1;  //为下一个S启动信号准备高电平
								inner_state<=start;
								i2c_state<=read_ini;
							 end
						 end
					 endcase
				 end
				/*****读数据请求输出*****/
				read_ini: begin 
					case(inner_state)
						//配置启动,S=0
						start: begin
							if(phase1) begin
								link<=1;
								sda_buf<=0;
							 end
						//配置8位读控制字节1001xxxR*****/
							if(phase3&&link) begin
								inner_state<=first;
								sda_buf<=1;  //第8位
								link<=1;
							 end
						 end
						first: 
							if(phase3) begin
								sda_buf<=0;  //第7位
								link<=1;
								inner_state<=second;
							 end
						second:
							if(phase3) begin
								sda_buf<=0;  //第6位
								link<=1;
								inner_state<=third;
							 end
						third:
							if(phase3) begin
								sda_buf<=1;  //第5位
								link<=1;
								inner_state<=fourth;
							 end
						fourth:
							if(phase3) begin
								sda_buf<=0;  //A2
								link<=1;
								inner_state<=fifth;
							 end
						fifth:
							if(phase3) begin
								sda_buf<=0;  //A1
								link<=1;
								inner_state<=sixth;
							 end
						sixth:
							if(phase3) begin
								sda_buf<=0;  //A0
								link<=1;
								inner_state<=seventh;
							end
						seventh:
							if(phase3) begin
								sda_buf<=1;  //R=1,读
								link<=1;
								inner_state<=eighth;
							 end
						eighth:
							if(phase3) begin
								link<=0;
								inner_state<=ack;
							 end
						//接收芯片应答,ACK
						ack: begin
							if(phase0) 
								sda_buf<=SDA;  //接收应答
							if(phase1) begin
								if(sda_buf==1) 
									main_state<=2'b00;
							 end
							if(phase3) begin
								link<=0;
								inner_state<=first;
								i2c_state<=read_ms_data;
							 end
						 end
					endcase
				end
				/*****读高8位数据输入*****/
				read_ms_data: begin  
					case(inner_state)
						//从芯片读取高8位数据
						first: begin
							if(phase0)
								sda_buf<=SDA;
							if(phase1) begin
								readMSData_reg[7:1]<=readMSData_reg[6:0];
								readMSData_reg[0]<=SDA;
							 end
							if(phase3)
								inner_state<=second;
						 end
						second: begin
							if(phase0)
								sda_buf<=SDA;
							if(phase1) begin
								readMSData_reg[7:1]<=readMSData_reg[6:0];
								readMSData_reg[0]<=SDA;
							 end
							if(phase3)
								inner_state<=third;
						 end
						third: begin
							if(phase0)
								sda_buf<=SDA;
							if(phase1) begin
								readMSData_reg[7:1]<=readMSData_reg[6:0];
								readMSData_reg[0]<=SDA;
							 end

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -