寒假一起练(4)温度、计时、报警、音乐、串口显示
温度、计时、报警、音乐、串口显示。 上位机用于初始化屏幕和温度显示
标签
FPGA
显示
velyaten
更新2021-02-21
1136

项目描述及要实现的功能:

  1. 实现一个可定时时钟的功能,用小脚丫FPGA核心模块的4个按键设置当前的时间,OLED显示数字钟的当前时间,精确到分钟即可,到整点的时候比如8:00,蜂鸣器报警,播放音频信号,最长可持续30秒;

  2. 实现温度计的功能,小脚丫通过板上的温度传感器实时测量环境温度,并同时间一起显示在OLED的屏幕上;

  3. 定时时钟整点报警的同时,将温度信息通过UART传递到电脑上,电脑上能够显示当前板子上的温度信息(任何显示形式都可以),要与OLED显示的温度值一致;

  4. PC收到报警的温度信号以后,将一段音频文件(自己制作,持续10秒钟左右)通过UART发送给小脚丫FPGA,蜂鸣器播放收到的这段音频文件,OLED屏幕上显示的时间信息和温度信息都停住不再更新;

  5. 音频文件播放完毕,OLED开始更新时间信息和当前的温度信息

完成的功能:(视频的演示部分已更新)

1、精确到分钟微秒的定时时钟、oled显示(RAM字库)、整点报警

2、温度采集、oled显示(RAM字库)

3、音乐播放(RAM读取)

4、串口接收温度数据、报警信号,发送oled初始化命令、字库信息

使用的资源:

这里将可以共用的寄存器全部合并了,并删除了微秒和秒的显示,暂且提高了资源利用率,后续还得多参考大佬们的代码,学习verilog的硬件编程的思路路漫漫其修远兮

1、一个pll:c0=1.8432mhz

                  c1=1mhz

                  c2=880khz

                  c3=115.2khz

2、RAM: 32768bit 

3、LCS: 1591

4、寄存器使用:658

详细使用情况:

FimNV7J27Q8FjGkTmW46o3YNW8qU

 

接下来是实现的思路

实现思路:

根据要求分析出需要的功能:

1、定时时钟

2、温度采集 + bcd转码

3、显示

4、uart接收、发送

5、上位机接收、发送

 

整体框架

整个任务是围绕地三个功能来进行的,以第三个功能搭建框架:

FlEyj1wVwqs_6cCOLSeevfQcOIKL

上电后还要初始化显示屏:

FpvhjqozrkOCh2kkfFYY_NTC4B0d

 

接下来是细的步骤

初始化显示屏:

FlbMHO65-titulXTP1G0ix0Kf_1K

 

oled显示的细分步骤:

这里将要显示的数据放在专用寄存器内,然后通过地址加法将对应的字库地址换算出来:

对应字库地址 = (寄存器数据 <<  4) + 12'd537    12'd537是‘0’字符的首地址

FoyCNUFnQM9_0sxeKZ5k36FoyS5-

接下来直接上代码:

主循环 + 小任务

					  		case (state)
					  			UART_RECV:begin 
					  					ram_sw <= '1;
					  					mode <=1'b0 ;
					  					case (ck)
					  					 0:if(!rdy_r) begin  EN <= '1;  ck <= ck; end 
					  					 					else begin wren <= '1; ck <= ck + 1'b1; end
					  					 1:begin if(rdy_r) begin ck <= ck; end
					  									    else begin  wren <= '0; ck <= ck + 1'b1; end
					  					 end
					  					 2:if(address == address_end)begin state_next <= state_back[state_pointer - 1'b1] ; state_pointer <= state_pointer - 1'd1; ck <= '0; EN <= '0; end
					  					   else begin address <= address + 1'b1 ; ck <= '0;end
					  					endcase
					  			end //UART_RECV
					  			OLED_INIT:begin 
					  					 case (ck)
					  					 0:begin oled_res_n <= '0;
					  					 		 delay_us <= 10'd1023 ; state_next <= DELAY ; state_back[state_pointer] <= state ; state_pointer <= state_pointer + 1'd1;
					  					 		 ck <= ck + 1'b1;
					  					 end
					  					 1:begin 
					  					 		 oled_res_n <= '1;
					  					 		 delay_us <= 10'd1023 ; state_next <= DELAY ; state_back[state_pointer] <= state ; state_pointer <= state_pointer + 1'd1; //100ms
					  							 ck <= ck + 1'b1;
					  					  end
					  					 2:begin 
					  					 		 oled_dc_n <= '0;
					  					 		 state_next <= SPI_SEND_RAM ; state_back[state_pointer] <= state ; state_pointer <= state_pointer + 1'd1; ck <= ck + 1'b1;
					  					 		 send_cnt <= 16'd25 ; address <= '0 ;
					  					  end
					  					 3:begin R0<='0;R1<='0;R2<=8'd127;R3<=8'd3; spi_send(CMD , CMD_SET_X); ck <= ck + 1'b1; end 
					  					 4:begin spi_send( CMD , R0 ) ; ck <= ck + 1'b1 ; end 
					  					 5:begin spi_send( CMD , R2 ) ; ck <= ck + 1'b1 ; end 
					  					 6:begin spi_send( CMD , CMD_SET_Y ) ; ck <= ck + 1'b1 ; end 
					  					 7:begin spi_send( CMD , R1 ) ; ck <= ck + 1'b1 ; end 
					  					 8:begin spi_send( CMD , R3 ) ; ck <= ck + 1'b1 ; end 
					  					 9:begin spi_send_ram(DATA , 12'd25 , 512) ;ck <= ck + 1'b1;end 
					  					 10:begin state_next <= state_back [ state_pointer - 1'b1 ] ; state_pointer <= state_pointer - 1'b1 ; ck <= '0;end 
					  					 endcase 
					  			end 
					  			MAIN:begin
					  				case (ck0)
					  				  0:begin address <= '0; address_end <= 12'd1122; state_next <= UART_RECV; state_back[state_pointer] <= state ; state_pointer <= state_pointer + 1'b1 ; ck0 <= ck0 + 1'b1; end
					  				  1:begin state_next <= UART_SEND; send_cnt <= 16'd1123; address <= '0; state_back[state_pointer] <= state ; state_pointer <= state_pointer + 1'b1 ; ck0 <= ck0 + 1'b1; end
					  				  2:begin state_next <= OLED_INIT; state_back[state_pointer] <= state ; state_pointer <= state_pointer + 1'b1 ; ck0 <= ck0 + 1'b1; end
					  				  3:begin gen_xy(R4 , 0 , SIZE8); spi_send(CMD , CMD_SET_X) ; R4 <= R4 + 8'd8 ; ck0 <= ck0 + 1'b1 ;end
									  4:begin spi_send(CMD , R0 ) ; 							  ck0 <= ck0 + 1'b1 ; end
									  5:begin spi_send(CMD , R2 ) ; 							  ck0 <= ck0 + 1'b1 ; end
									  6:begin spi_send(CMD , CMD_SET_Y) ; 						  ck0 <= ck0 + 1'b1 ; end
									  7:begin spi_send(CMD , R1 ) ; 							  ck0 <= ck0 + 1'b1 ; end
									  8:begin spi_send(CMD , R3 ) ; 							  ck0 <= ck0 + 1'b1 ; end
									  9:begin spi_send_ram(DATA , clock[clock_ck], SIZE8_16) ; clock_ck <= clock_ck - 1'b1 ; ck0 <= ck0 + 1'b1 ; end
									 10:begin if(timer_alarm) begin state_next <= UART_SEND ; address <= 1093; send_cnt <= 16'd30; state_back[state_pointer] <= state ; state_pointer <= state_pointer + 1'b1 ; ck0 <= ck0 + 1'b1 ; ck <= '0; end else begin ck0 <= 5'd13; end end
									 11:begin state_next <= UART_RECV; state_back[state_pointer] <= state ; state_pointer <= state_pointer + 1'b1 ; address <= 12'd889; address_end <= 12'd1060; ck0 <= ck0 + 1'b1; end
									 //12:begin state_next <= UART_SEND; send_cnt <= 16'd172; address <= 12'd889; state_back[state_pointer] <= state ; state_pointer <= state_pointer + 1'b1 ; ck0 <= ck0 + 1'b1; end
									 12:begin state_next <= MUSIC; address <= 12'd889; state_back[state_pointer] <= state ; state_pointer <= state_pointer + 1'b1 ; ck0 <= ck0 + 1'b1; end 
									 13:begin gen_xy(R6 , 2 , SIZE8); spi_send(CMD , CMD_SET_X);   R6 <= R6 + 8'd8; ck0 <= ck0 + 1'b1; end
									 14:begin spi_send(CMD , R0 ) ; 							   ck0 <= ck0 + 1'b1 ; end
									 15:begin spi_send(CMD , R2 ) ; 							   ck0 <= ck0 + 1'b1 ; end
									 16:begin spi_send(CMD , CMD_SET_Y) ; 						   ck0 <= ck0 + 1'b1 ; end
									 17:begin spi_send(CMD , R1 ) ; 							   ck0 <= ck0 + 1'b1 ; end
									 18:begin spi_send(CMD , R3 ) ; 							   ck0 <= ck0 + 1'b1 ; end
									 19:begin ram_write(12'd1093 , 2'd0) ; R0 <= ds18b20_out[15:8] ; t_ad <= bcd_buff[bcd_ad]; ck0 <= ck0 + 1'b1 ; end
									 20:begin ram_write(12'd1094 , 2'd0) ; R0 <= ds18b20_out[7:0]  ; t_ad <= t_ad<<4; 		  ck0 <= ck0 + 1'b1 ; end
									 21:begin address <= 12'd1092; send_cnt <= 16'd3; state_next <= UART_SEND; state_back[state_pointer] <= state ; state_pointer <= state_pointer + 1'b1 ; t_ad <= t_ad + 12'd537; ck0 <= ck0 + 1'b1 ; end
									 22:begin spi_send_ram(DATA , t_ad , SIZE8_16); bcd_ad <= bcd_ad - 1'd1; ck0 <= ck0 + 1'b1 ; end
									 23:begin if(bcd_ad == 2'd3) begin R6 <= '0;				   ck0 <= ck0 + 1'b1 ; end else begin ck0 <= 5'd13; end end
									 24:begin gen_xy(32 , 2 , SIZE16); spi_send(CMD , CMD_SET_X);  ck0 <= ck0 + 1'b1 ; end
									 25:begin spi_send(CMD , R0 ) ; 							   ck0 <= ck0 + 1'b1 ; end
									 26:begin spi_send(CMD , R2 ) ; 							   ck0 <= ck0 + 1'b1 ; end
									 27:begin spi_send(CMD , CMD_SET_Y) ; 						   ck0 <= ck0 + 1'b1 ; end
									 28:begin spi_send(CMD , R1 ) ; 							   ck0 <= ck0 + 1'b1 ; end
									 29:begin spi_send(CMD , R3 ) ; 							   ck0 <= ck0 + 1'b1 ; end
									 30:begin spi_send_ram(DATA , 12'd1061 , SIZE16_16); ck0 <= 5'd3; end
									 default:R4 = '0;
					  				endcase
					  			end 
					  			MUSIC:begin 
					  				 if(address != 12'd1061)
					  				  case (ck) 
					  				  0:begin ram_read(0) ;  ck <= ck + 1'b1 ; music_ld <= '1; end 
					  				  1:begin ram_read(1) ;  address <= address + 1'b1; ck <= ck + 1'b1 ; end 
					  				  2:begin time_fpn <= { R0 , R1 } ; ck <= ck + 1'b1 ; end 
					  				  3:begin music_ld <= '0 ; ck <= ck + 1'b1 ; end 
					  				 //5:begin if( address == MUSIC_LEN ) begin music_en <= '0 ; state_next <= state_back [ state_pointer - 1'b1 ] ; state_pointer <= state_pointer - 1'b1 ; ck <= 3'd0 ; end
					  				 //		  else begin ck <= 3'd6 ; end end
					  				  4:begin if(!upd ) begin music_ld <= '1 ; ck <= ck + 1'b1;  end else begin ck <= ck; end end
					  				  5:begin if( upd ) begin music_ld <= '1 ; ck <= ck + 1'b1;  end 
					  				  			  else  begin music_ld <= '1 ; ck <= ck ; address <= address;  end end
					  				  6:begin address <= address + 1'd1 ; music_ld <= '1; ck <= '0; end
					  				  endcase 
					  				  else begin state_next <= state_back [ state_pointer - 1'b1 ] ; state_pointer <= state_pointer - 1'b1 ; music_ld <= '0; ck <= '0; end
					  			end 
								UART_SEND:begin 
										  mode <= 1'd1 ;
										  case (ck)
										  0:begin rden  <=  1'b1 ; ck <= ck + 1'b1 ; end
										  1:begin if(!rdy) begin EN <= 1'b1 ;  end
										  			  else begin address <= address + 1'b1 ; ck <= ck + 1'b1 ; end
										  end                    
										  2:begin if( rdy) begin ck <= ck ; end
										  			  else begin send_cnt <= send_cnt - 1'b1 ; ck <= ck + 1'b1 ; end
										  end
										  3:begin if(send_cnt != 16'd0) begin ck <= '0; end
										  						   else begin 
										  						  	    state_next <= state_back [ state_pointer - 1'b1 ] ; state_pointer <= state_pointer - 1'b1 ; ck <= '0 ;
										  						  	    EN    <= 1'b0 ;
										  						  	    wren  <= 1'b0 ; rden <= 1'b0 ; address <= 12'h000 ; end
										  end 
										  endcase
								end//MAIN 
								SPI_SEND_RAM:begin 
											 case (ck_spi_send)
											 0:begin oled_cs_n <= '0 ; rden   <=  1'b1 ; ck_spi_send <= ck_spi_send + 1'b1 ; end 
											 1:begin if(!rdy_spi_tx) begin en <=  1'b1 ; end 
											 			else begin address  <=  address + 1'b1 ; ck_spi_send <= ck_spi_send + 1'b1 ; end 
											 end 
											 2:begin if( rdy_spi_tx) begin oled_cs_n <= '1 ; ck_spi_send <= ck_spi_send; end 
											 		    else begin send_cnt <=  send_cnt - 1'b1 ; ck_spi_send <= ck_spi_send + 1'b1 ; end 
											 end 
											 3:begin if(send_cnt == 16'd0) begin 
											 						state_next <= state_back[ state_pointer - 1'b1 ] ; state_pointer <= state_pointer - 1'b1 ; rden <= 1'b0 ; address <= 12'h000 ;
											 						send_cnt   <= 16'd0 ; 
											 						en         <= 1'b0  ; 
											 						ck_spi_send         <= '0 ; 
											 						wren       <= 1'b0  ; end
											 				   else begin ck_spi_send <= '0; end
											 end
											 endcase 
											end 
								SPI_SEND:begin 
										 case (ck_spi_send)
										  0:if( ~rdy_spi_tx ) begin oled_cs_n <= '0 ; spi_sw <= '0; en <= '1 ; end 
										  				else  begin ck_spi_send <= ck_spi_send + 1'b1 ; end
										  1:begin if( rdy_spi_tx ) begin oled_cs_n <= '1 ; ck_spi_send <= ck_spi_send ; end
										 					 else  begin en <= '0 ; state_next <= state_back[ state_pointer - 1'b1 ] ; state_pointer <= state_pointer - 1'b1 ; ck_spi_send <= '0 ; end
										  end
										 endcase
								end 
								DELAY:begin 
									  case ( ck1 )
									  0:begin timer_us_en <= '1 ; ck1 <= ck1 + 1'b1 ; end
									  1:if( timer_us < delay_us ) begin ck1 <= ck1 ; end
									    else begin timer_us_en <= '0 ; state_next <= state_back [ state_pointer - 1'b1 ] ; state_pointer <= state_pointer - 1'b1 ; ck1 <= '0; end
									  endcase
								end 
								RAM_READ:begin 
										case ( ck2 )
											0:begin rden <= '1 ; ck2 <= ck2+1'b1 ; end
											1:begin 
												state_next <= state_back [ state_pointer - 1'b1 ] ; state_pointer <= state_pointer - 1'b1 ; ck2 <= '0;
												rden <= '0 ; 
												case(R_) 
												0: R0 <= q ; 
												1: R1 <= q ; 
												2: R2 <= q ; 
												3: R3 <= q ; 
												default : ;
												endcase 
											 end 
											 default : ;
										endcase 
								end 
								RAM_WRITE:begin 
								 		  	case (ck2) 
								 		  		0:begin ram_sw <= '0 ; wren <= '1 ; ck2  <=  ck2 + 1'b1 ; 
								 		  				case(R_) 
														0: ram_in <= R0 ; 
														1: ram_in <= R1 ; 
														2: ram_in <= R2 ; 
														3: ram_in <= R3 ; 
														default : ;
													endcase 
								 		 		 	end 
												1:begin 
													state_next <= state_back[state_pointer - 1'b1] ; state_pointer <= state_pointer - 1'b1 ; ck2  <=  '0;
													wren <= '0 ; 
												 end 
								 		  endcase 
								end 
								default : begin ; end
							endcase//STATE 
				end//end else 
		end//always 

计时时钟、spi驱动、uart驱动、温度采集的代码见附件

 

 

遇到的困难:

1、还未领略硬件编程的精髓

2、起初蜂鸣器发烫,后来把输出寄存器的空闲状态调整为1‘b0,就能正常测到室温了

2、由于RAM读取的时序不清楚,导致前期,无法读出数据

 

改进计划:

1、下步计划重新优化结构,提升系统稳定性

2、优化状态机,减少多余状态,提高资源利用率

 

将来的打算与目前正在做的东西:

1、加入ps2接口,以便键盘输入命令(已实现)

2、设计基于spi协议的lcd驱动

3、基于lcd实现俄罗斯方块

 

对板卡的一点小建议:

1、加入外部ROM

2、丰富各种接口

3、加入LCD接口

附件下载
ctaus_max10.qar
工程文件
团队介绍
陕西科技大学
团队成员
王峄铭
陕科大的某某某
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号