# 设计文档
## 项目信息
**名称:** 数字万年历温湿度计 Verilog QuartusII
**软件:** QuartusII
**语言:** Verilog
## 代码功能
本项目实现了一个基于FPGA的多功能数字万年历系统,集成了时间显示、日期显示和环境监测功能。系统具备以下核心功能:
- **实时时钟功能**:通过DS1340Z时钟芯片实现精确的时、分、秒显示,采用24小时制
- **万年历功能**:显示年、月、日、星期信息,支持用户手动校准
- **温湿度监测**:集成SHT20传感器,实时测量并显示环境温度和湿度
- **双模式显示**:支持时间日期模式和温湿度模式的切换显示
- **多种输入方式**:支持4×4矩阵键盘和旋转编码器两种输入方式
- **数码管显示**:采用8位七段数码管动态扫描显示,支持小数点控制
系统通过I2C总线与外部传感器通信,采用模块化设计确保各功能模块独立工作且协调配合。
本代码已在小脚丫开发板验证
编辑
## 代码实现思路
### 整体架构
系统采用分层模块化设计,主要分为以下几个层次:
1. **硬件接口层**:包括I2C通信、数码管驱动、按键检测等底层硬件控制
2. **数据处理层**:负责温湿度数据转换、BCD码转换、时间数据处理
3. **控制逻辑层**:实现模式切换、显示控制、用户交互逻辑
4. **显示驱动层**:控制8位数码管的动态扫描显示
### 核心算法
- **I2C通信协议**:实现与DS1340Z时钟芯片和SHT20温湿度传感器的标准I2C通信
- **温度计算**:T = -46.85 + 175.72 × T_code / 2^16,通过定点运算实现浮点计算
- **湿度计算**:RH = -6 + 125 × H_code / 2^16,采用类似的定点运算方法
- **BCD转换**:将二进制数据转换为BCD码,便于数码管显示
- **按键消抖**:采用计数器方式实现按键信号的消抖处理
### 状态机设计
系统采用多个状态机协同工作:
- **主控状态机**:控制系统整体运行流程和模式切换
- **I2C状态机**:管理I2C通信的START、WRITE、READ、STOP等状态
- **显示状态机**:控制数码管的扫描显示时序
## 代码结构
### 主要模块说明
**`Digtal_Calender` 模块**
- 系统顶层模块,集成所有子模块并实现顶层控制逻辑
**`DS1340Z_driver` 模块**
- DS1340Z实时时钟芯片驱动,实现时间的读取和设置功能
**`SHT20_Driver` 模块**
- SHT20温湿度传感器驱动,负责温湿度数据的采集
**`Calculate` 模块**
- 温湿度数据计算模块,将传感器原始数据转换为实际温湿度值
**`mode_ctrl` 模块**
- 模式控制模块,处理用户输入并控制系统运行状态
**`Array_KeyBoard` 模块**
- 4×4矩阵键盘扫描模块,实现按键检测和编码
**`Encoder` 模块**
- 旋转编码器处理模块,检测旋转方向和脉冲信号
**`Debounce` 模块**
- 按键消抖模块,消除按键机械抖动产生的干扰
**`Decoder` 模块**
- 显示模式切换控制模块,处理时间和温湿度显示的切换
**`Segment_scan` 模块**
- 数码管扫描显示模块,实现8位数码管的动态显示控制
**`bin_to_bcd` 模块**
- 二进制到BCD码转换模块,为数码管显示提供数据格式转换
部分代码展示:
//1. 时间显示功能:包括小时、分钟、秒,采用24小时显示方式?//2. 日期显示功能:包括年、月、日、星期?//3. 实际温度和湿度显示功能?//4. 使用键盘或旋转编码器作为输入,进行日期和时间的校准和日期时间温湿度的显示切换。// --------------------------------------------------------------------module?Digtal_Calender(input clk, //系统时钟input rst_n, //系统复位,低有效//矩阵键盘input [3:0] col,output [3:0] row,//旋转编码器input key_a, //旋转编码器A管脚input key_b, //旋转编码器B管脚input key_o, //旋转编码器D管脚//时钟芯片output reg i2c_scl, //I2C总线SCLinout reg i2c_sda, //I2C总线SDA//数码管控制output seg_rck, //74HC595的RCK管脚output seg_sck, //74HC595的SCK管脚output seg_din //74HC595的SER管脚);wire [15:0] key_out;wire [15:0] key_pulse;reg [3:0] dat_1; //SEG1 显示的数据输入reg [3:0] dat_2; //SEG2 显示的数据输入reg [3:0] dat_3; //SEG3 显示的数据输入reg [3:0] dat_4; //SEG4 显示的数据输入reg [3:0] dat_5; //SEG5 显示的数据输入reg [3:0] dat_6; //SEG6 显示的数据输入reg [3:0] dat_7; //SEG7 显示的数据输入reg [3:0] dat_8; //SEG8 显示的数据输入reg [7:0] dat_en_dis; //数码管数据位显示使能,[MSB~LSB]=[SEG1~SEG8]reg [7:0] dot_en_dis; //数码管小数点位显示使能,[MSB~LSB]=[SEG1~SEG8]wire ? ? select_display;wire ? ? shift_p;wire ? ? shift_n;wire shift_rst_n;assign shift_rst_n=~(shift_p | shift_n);//温湿度芯片wire i2c_scl_THM; //I2C时钟总线wire i2c_sda_THM; //I2C数据总线//时钟芯片wire ? ? ? ?i2c_scl_TM;wire ? ? ? ?i2c_sda_TM;//矩阵键盘控制Array_KeyBoard?u0(.clk (clk ),.rst_n (rst_n ),.col (col ),.row (row ),.key_out (key_out ),.key_pulse (key_pulse ));wire L_pulse,R_pulse;Encoder?u1(.clk (clk ), //系统时钟 12MHz.rst_n (rst_n ), //系统复位 低有效.key_a (key_a ), //旋转编码器EC11的A脚.key_b (key_b ), //旋转编码器EC11的B脚.L_pulse (L_pulse ), //左旋脉冲输出.R_pulse (R_pulse ) //右旋脉冲输出);wire O_jit,O_pulse,O_state;//key debounce moduleDebounce?u2(.clk (clk ), //系统时钟 12MHz.rst_n (rst_n ), //系统复位 低有效.key_n (key_o ), //按键信号输入.key_jit (O_jit ), //延时消抖输出.key_pulse (O_pulse ), //消抖脉冲输出.key_state (O_state ) //消抖翻转输出);
294