这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » LM75A作业

共5条 1/1 1 跳转至

LM75A作业

助工
2014-09-01 23:24:03     打赏

自己写的LM75A作业,由于精确度为0.125,也就是1/8,就把[15:5]的低3位拿掉了,相当于右移3位,除以了8,只显示整数位温度数据,以十进制形式显示。

源代码如下:

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: Charles Wang 
// 
// Create Date:    08/21//2014 
// Design Name: 	LM75A
// Module Name:   LM75A
// Project Name: 	LM75A
// Target Devices: EP4CE6E22C8
// Tool versions: Quartus II 13.1 
// Description: 使用LM75A感应周围环境温度,并用数码管显示温度(只显示无小数位的正温度值)
//              --顶层模块
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//			
//////////////////////////////////////////////////////////////////////////////////
module LM75A(sys_clk,sys_rst_n,scl,sda,cs,disp_seg);
input sys_clk;//总线时钟 50MHz
input sys_rst_n;//异步复位,低电平有效

output scl;//SCL 时钟
inout	 sda;// SDA 数据总线
output [3:0]cs;//数码管片选
output [7:0]disp_seg;//数码管段选

wire [15:0]data;//温度数据
//////////////////////////////////////////////////////////////////////////////////
//实例化I2C 总线模块
LM75A_I2C I2C(.sys_clk(sys_clk),.sys_rst_n(sys_rst_n),.scl(scl),.sda(sda),.data(data));
//实例化LED 显示模块
LM75A_LED LED(.sys_clk(sys_clk),.sys_rst_n(sys_rst_n),.cs(cs),.disp_seg(disp_seg),
.data(data));

endmodule

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: Charles Wang 
// 
// Create Date:    08/21//2014 
// Design Name: 	LM75A
// Module Name:   LM75A_I2C
// Project Name: 	LM75A
// Target Devices: EP4CE6E22C8
// Tool versions: Quartus II 13.1 
// Description: 使用LM75A感应周围环境温度,并用数码管显示温度(只显示无小数位的正温度值)
//              --I2C 总线模块
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//			
//////////////////////////////////////////////////////////////////////////////////
module LM75A_I2C(sys_clk,sys_rst_n,scl,sda,data);

input sys_clk;//总线时钟 50MHz
input sys_rst_n;//异步复位,低电平有效

output scl;//SCL 时钟
inout  sda;// SDA 数据总线
output [15:0] data;//温度数据

reg [15:0]data_r;//温度数据寄存器
reg scl;//SCL 总线寄存器
reg sda_r;//SDA 总线寄存器
reg sda_link;//SDA 总线数据方向标志
reg [7:0]scl_cnt;//SCL 时钟产生计数器
reg [2:0]cnt;//用来标记SCL时钟计数器
reg [25:0]timer_cnt;//定时器,每隔2s 读取一次温度数据
reg [3:0]data_cnt;//数据串并转换寄存器
reg [7:0]address_reg;//器件地址寄存器
reg [8:0]state;//状态寄存器
//////////////////////////////////////////////////////////////////////////////////
//进程1、2、3:产生SCL 总线时钟
always@(posedge sys_clk or negedge sys_rst_n)
	begin
		if(!sys_rst_n)
			scl_cnt <= 8'd0;
		else if(scl_cnt == 8'd199)
			scl_cnt <= 8'd0;
		else
			scl_cnt <= scl_cnt + 1'b1;
	end
always@(posedge sys_clk or negedge sys_rst_n)
	begin
		if(!sys_rst_n)
			cnt <= 3'd5;
		else 
			case(scl_cnt)
				8'd49: cnt <= 3'd1;//高电平中间
				8'd99: cnt <= 3'd2;//下降沿
				8'd149:cnt <= 3'd3;//低电平中间
				8'd199:cnt <= 3'd0;//上升沿
			   default: cnt <= 3'd5;
			endcase
	end
`define SCL_HIG (cnt == 3'd1)
`define SCL_NEG (cnt == 3'd2)
`define SCL_LOW (cnt == 3'd3)
`define SCL_POS (cnt == 3'd0)
always@(posedge sys_clk or negedge sys_rst_n)
	begin
		if(!sys_rst_n)
			scl <= 1'b0;
		else if(`SCL_POS)
			scl <= 1'b1;
		else if(`SCL_NEG)
			scl <= 1'b0;
	end
//////////////////////////////////////////////////////////////////////////////////
//进程4:定时器,每隔1s 读取一次温度数据
always@(posedge sys_clk or negedge sys_rst_n)
	begin
		if(!sys_rst_n)
			timer_cnt <= 26'd0;
		else if(timer_cnt == 26'd49999999)
			timer_cnt <= 26'd0;
		else 
			timer_cnt <= timer_cnt + 1'b1;
	end
//////////////////////////////////////////////////////////////////////////////////
//状态机定义
parameter IDLE 	= 9'b0_0000_0000,
			 START	= 9'b0_0000_0010,
			 ADDRESS	= 9'b0_0000_0100,
			 ACK1		= 9'b0_0000_1000,
			 READ1	= 9'b0_0001_0000,
			 ACK2		= 9'b0_0010_0000,
			 READ2	= 9'b0_0100_0000,
			 NACK		= 9'b0_1000_0000,
			 STOP		= 9'b1_0000_0000;
`define DEVICE_ADDRESS 8'b1001_0001//器件地址,读操作
//////////////////////////////////////////////////////////////////////////////////
//进程5:状态机描述
always@(posedge sys_clk or negedge sys_rst_n)
	begin
		if(!sys_rst_n)
			begin
				data_r 	<= 16'd0;
				sda_r	 	<= 1'b1;
				sda_link	<= 1'b1;
				state		<= IDLE;
				address_reg <= 15'd0;
				data_cnt 	<= 4'd0;
			end
		else 
			case(state)
				IDLE:
					begin
						sda_r 	<= 1'b1;
						sda_link <= 1'b1;
						if(timer_cnt == 26'd49999999)
							state <= START;
						else
							state <= IDLE;
					end
				START://产生起始信号
					begin
						if(`SCL_HIG)
							begin
								sda_r 		<= 1'b0;
								sda_link 	<= 1'b1;
								address_reg <= `DEVICE_ADDRESS;
								state			<= ADDRESS;
								data_cnt		<= 4'd0;
							end
						else
							state <= START;
					end
				ADDRESS://主机对器件进行寻址
					begin
						if(`SCL_LOW)
							begin
								if(data_cnt == 4'd8)//寻址完成,SDA改变方向,器件准备输出应答讯号
									begin
										state 	<= ACK1;
										data_cnt <=	4'd0;
										sda_r		<= 1'b1;
										sda_link	<= 1'b0;
									end
								else//寻址过程中,SDA对器件作为输入
									begin
										state 	<= ADDRESS;
										data_cnt <= data_cnt + 1'b1;
										case(data_cnt)
											4'd0: sda_r <= address_reg[7];
											4'd0: sda_r <= address_reg[7];
											4'd1: sda_r <= address_reg[6];
											4'd2: sda_r <= address_reg[5];
											4'd3: sda_r <= address_reg[4];
											4'd4: sda_r <= address_reg[3];
											4'd5: sda_r <= address_reg[2];
											4'd6: sda_r <= address_reg[1];
											4'd7: sda_r <= address_reg[0];
											default: ;
										endcase
									end
							end
						else
							state <= ADDRESS;
					end
				ACK1://器件输出应答信号
					begin
						if(!sda && (`SCL_HIG))
							state <= READ1;
						else if(`SCL_NEG)
							state <= READ1;
						else
							state <= ACK1;
					end
				READ1://读器件数据,高字节
					begin
						if((`SCL_LOW) && (data_cnt == 4'd8))//读高字节数据完成,SDA改变方向,主机准备输出应答讯号
							begin
								state 	<= ACK2;
								data_cnt <= 4'd0;
								sda_r		<= 1'b1;
								sda_link	<= 1'b1;
							end
						else if(`SCL_HIG)//读数据过程中,器件作为输出
							begin
								data_cnt <= data_cnt + 1'b1;
								case(data_cnt)
									4'd0: data_r[15] <= sda;
									4'd1: data_r[14] <= sda;
									4'd2: data_r[13] <= sda;
									4'd3: data_r[12] <= sda;
									4'd4: data_r[11] <= sda;
									4'd5: data_r[10] <= sda;
									4'd6: data_r[9]  <= sda;
									4'd7: data_r[8]  <= sda;
									default: ;
								endcase
							end
						else
							state <= READ1;
					end
				ACK2://主机输出应答讯号
					begin	
						if(`SCL_LOW)
							sda_r <= 1'b0;
						else if(`SCL_NEG)
							begin
								sda_r 	<= 1'b1;
								sda_link	<= 1'b0;
								state		<= READ2;
							end
						else
							state <= ACK2;
					end
				READ2://读低字节数据
					begin
						if((`SCL_LOW) && (data_cnt == 4'd8))
							begin
								state 	<= NACK;
								data_cnt <= 4'd0;
								sda_r		<= 1'b1;
								sda_link	<= 1'b1;
							end
						else if(`SCL_HIG)
							begin
								data_cnt <= data_cnt + 1'b1;
								case(data_cnt)
									4'd0: data_r[7] <= sda;
									4'd1: data_r[6] <= sda;
									4'd2: data_r[5] <= sda;
									4'd3: data_r[4] <= sda;
									4'd4: data_r[3] <= sda;
									4'd5: data_r[2] <= sda;
									4'd6: data_r[1]  <= sda;
									4'd7: data_r[0]  <= sda;
									default: ;
								endcase
							end
						else
							state <= READ2;
					end
				NACK://主机非应答
					begin
						if(`SCL_LOW)
							begin
								state <= STOP;
								sda_r	<= 1'b0;
							end
						else
							state <= NACK;
					end
				STOP:
					begin
						if(`SCL_HIG)
							begin
								state <= IDLE;
								sda_r <= 1'b1;
							end
						else
							state <= STOP;
					end
				default: state <= IDLE;
			endcase
	end
assign sda	 = sda_link ? sda_r: 1'bz;
assign data	 = data_r;
endmodule

 


`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: Charles Wang 
// 
// Create Date:    08/21//2014 
// Design Name: 	LM75A
// Module Name:   LM75A_LED
// Project Name: 	LM75A
// Target Devices: EP4CE6E22C8
// Tool versions: Quartus II 13.1 
// Description: 使用LM75A感应周围环境温度,并用数码管显示温度(只显示无小数位的正温度值)
//              --数码管显示模块
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//			
//////////////////////////////////////////////////////////////////////////////////
module LM75A_LED(sys_clk,sys_rst_n,data,cs,disp_seg);

input sys_clk;//总线时钟,50MHz
input sys_rst_n;//异步复位,低电平有效

input [15:0]data;//温度数据
output[3:0]cs;//数码管片选
output[7:0]disp_seg;//数码管段选

reg [1:0]cnt_clk;
reg [3:0]cs;
reg [12:0] cnt;
reg [3:0]data_buff;//温度数据寄存器
reg [3:0]data_buffa;//温度数据寄存器,个位
reg [3:0]data_buffb;//温度数据寄存器,十位
//////////////////////////////////////////////////////////////////////////////////
//进程1、2:数码管片选扫描信号,10KHz 
always @ (posedge sys_clk or negedge sys_rst_n)
	begin
		if(!sys_rst_n) 
			cnt <= 13'd0;
		else if (cnt==13'd4999)
			cnt <= 13'd0;
		else 
			cnt <= cnt+1'b1;
	end
always@(posedge sys_clk or negedge sys_rst_n)
	begin	
		if(!sys_rst_n)
			cnt_clk <= 2'd0;
		else if((cnt == 13'd4999) && (cnt_clk == 2'd2))
			cnt_clk <= 2'd0;
		else if(cnt == 13'd4999)
			cnt_clk <= cnt_clk + 1'b1;
		else
			cnt_clk <= cnt_clk;
	end
reg[7:0] sm_seg;		//7段数码管
//////////////////////////////////////////////////////////////////////////////////
//进程3、4:数码管显示	
always @ (posedge sys_clk or negedge sys_rst_n)
	begin
		if(!sys_rst_n)
			begin 
			  data_buffa <=4'hf;
			  data_buffb <=4'hf;
			end
		else if(data_buffa > 4'd9)
			begin
				data_buffa <= data_buffa - 4'd10;
				data_buffb <= data_buffb + 1'b1;
			end
		else
			begin
				data_buffa <= {data[11:8]};
				data_buffb <= {data[15:12]};
			end
	end	
always @ (posedge sys_clk or negedge sys_rst_n)
	begin
		if(!sys_rst_n)
			begin
				data_buff <= 4'hf;
				cs <= 4'b1111;
			end
		else
			case(cnt_clk)
				 2'd1: 
					begin 
						cs  		 <=4'b1110;
						data_buff <=data_buffa;
					end
				 2'd2: 
					begin
						cs  		 <=4'b1101;
						data_buff <=data_buffb;
					end
				default: ;
			endcase
	end
always @ (posedge sys_clk or negedge sys_rst_n)
	begin
		if(!sys_rst_n) 
			sm_seg<=8'hff;
		else 
			begin
				case (data_buff)	//温度值值显示在2个数码管上,共阳极数码管
					4'h0 : sm_seg = 8'hc0;   // "0"
					4'h1 : sm_seg = 8'hf9;   // "1"
					4'h2 : sm_seg = 8'ha4;   // "2"
					4'h3 : sm_seg = 8'hb0;   // "3"
					4'h4 : sm_seg = 8'h99;   // "4"
					4'h5 : sm_seg = 8'h92;   // "5"
					4'h6 : sm_seg = 8'h82;   // "6"
					4'h7 : sm_seg = 8'hf8;   // "7"
					4'h8 : sm_seg = 8'h80;   // "8"
					4'h9 : sm_seg = 8'h90;   // "9"
					default: ;
				endcase
			end
	end
assign disp_seg = sm_seg;
endmodule			  

 


 




关键词: LM75A     温度     显示    

助工
2014-09-01 23:27:46     打赏
2楼

显示图片是今天刚拍下来的,如下:

我现在在重庆,今天的气温如下:

    


助工
2014-09-02 00:03:24     打赏
3楼

从8月21号一直到现在,一边看I2C总线协议一边看培训视频,自己慢慢写了一个多礼拜,今天算是把结果调出来了,只是有个问题就是如上图所示,“23”中“2”的右下角有一个竖着的段是亮着的,实际比较暗,可能是由于手机拍摄的原因,拍下来很亮,还没有再仔细看。

如果有哪位大神已经看出来问题了,请先赐教。


论坛里大牛很多,不敢太放肆,就关公面前耍一回小刀,说一下这段时间以来的学习心得:

    1. 记得在线培训刚开始的第一堂课的时候,自己在在线问答的时候,问了51大神一个自己现在想起来都想笑的问题,就是UART 和 I2C 有什么区别,现在来看,自己觉得最简单的区别其实就是:UART 不需要时钟信号,只有波特率之说,而I2C 则需要时钟信号,也就是说几乎完全不同的两个总线

    2. 忘了是在哪一节培训时,51说过大致这么一句话:“试着脱离别人的代码,看数据手册,自己写源代码,等到自己调试出问题,没有头绪时,再回头看别人的代码”,之后自己从红外篇吧应该是,慢慢尝试脱离51的源代码,试着自己写,到VGA,在直到现在的I2C,当然,不敢全部把功劳邀在自己的身上,因为自己还没有完完全全脱离51的教程。不过,通过自己看手册,写代码,能学到的不止一星半点,的确可以学到很多培训以外的东西。也多亏51的耐心,每次烦他的时候,他都会及时的帮我解决一些燃眉之急,不会像现在的一些所谓的“砖家””叫兽“,摆架子(我是不是扯远了?)。

    3. 分享真的是个好东西,你能在别人的身上学到很多,比如论坛里面很多人的技术疑问,其他人的作业本,每日一题等等。现在几乎每天都会来论坛看一下每日一题啊,一天一个电路分析啊什么的。也有很多次拿论坛里别人的源代码看几遍,学了很多自己需要弥补的东西。


    罗里吧嗦那么多,该休息了。。。。

    


专家
2014-09-02 08:41:53     打赏
4楼
虽然不知道是什么作业,楼主精神可嘉,鼓励原创,期待更多作业

院士
2014-09-02 09:22:54     打赏
5楼

共5条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]