STM32电子时钟Proteus仿真实战:LCD1602与数码管双显设计
2026/4/4 1:27:58 网站建设 项目流程

1. 项目概述与硬件选型

在嵌入式系统开发中,电子时钟是最经典的练手项目之一。这次我们要用STM32F103单片机配合Proteus仿真软件,实现一个同时驱动LCD1602液晶屏和数码管的双显电子时钟。这种设计既能锻炼GPIO和定时器的使用,又能学习不同显示设备的驱动逻辑。

硬件选择上,我推荐使用STM32F103C8T6这款性价比极高的芯片,它内置RTC实时时钟模块,72MHz主频完全够用。显示部分采用常见的LCD1602(16字符x2行)和4位共阳数码管组合。仿真环境用Proteus 8.9以上版本,实际开发可以用STM32CubeMX生成初始化代码。

注意:Proteus中的STM32模型与实际硬件存在时序差异,仿真时定时器参数需要特别调整,后文会具体说明。

2. 硬件电路设计要点

2.1 显示模块接口设计

LCD1602采用标准的4位数据线接法(DB4-DB7),节省GPIO资源。具体连接:

  • RS -> PA0
  • RW -> GND(只写模式)
  • E -> PA1
  • D4-D7 -> PA4-PA7

数码管使用动态扫描方式驱动,四个位选信号接PB8-PB11,段选信号通过74HC595串转并芯片连接,只需占用STM32的三个引脚(PB12-PB14)。这种设计在真实项目中能有效减少线材数量。

2.2 关键外围电路

  • 晶振电路:8MHz主晶振+32.768kHz RTC晶振(仿真时可省略)
  • 复位电路:10k上拉电阻+0.1uF电容
  • 按键电路:三个独立按键接PC13-PC15,用于时间设置

3. 软件架构设计

3.1 主程序流程图

int main(void) { HAL_Init(); SystemClock_Config(); LCD_Init(); DigitalTube_Init(); TIM3_Init(10, 884); // 1ms定时 RTC_Init(); while(1) { Key_Process(); // 按键扫描 Time_Update(); // 时间计算 LCD_Display(); // LCD刷新 Tube_Display(); // 数码管刷新 } }

3.2 定时器配置关键代码

使用TIM3产生1ms中断作为系统时基:

void TIM3_Init(uint16_t arr, uint16_t psc) { TIM_HandleTypeDef htim3; htim3.Instance = TIM3; htim3.Init.Prescaler = psc; htim3.Init.CounterMode = TIM_COUNTERMODE_UP; htim3.Init.Period = arr; HAL_TIM_Base_Init(&htim3); HAL_TIM_Base_Start_IT(&htim3); }

4. 双显示驱动实现

4.1 LCD1602驱动优化

采用状态机方式优化显示刷新,避免频繁操作影响实时性:

void LCD_Refresh(void) { static uint8_t state = 0; switch(state) { case 0: LCD_SetCursor(0,0); LCD_WriteString("Time:"); state++; break; case 1: LCD_SetCursor(6,0); printf("%02d:%02d:%02d", hours, mins, secs); state++; break; case 2: LCD_SetCursor(0,1); LCD_WriteString("Date:"); state++; break; case 3: LCD_SetCursor(6,1); printf("%04d-%02d-%02d", year, month, day); state = 0; break; } }

4.2 数码管动态扫描

在定时器中断中实现扫描,避免闪烁:

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { static uint8_t pos = 0; DigitalTube_Clear(); switch(pos) { case 0: Show_Hour_Tens(); break; case 1: Show_Hour_Units(); break; case 2: Show_Min_Tens(); break; case 3: Show_Min_Units(); break; } DigitalTube_Select(pos); pos = (pos+1)%4; }

5. 时间管理与设置功能

5.1 RTC初始化

使用STM32内置RTC模块,需先配置LSE时钟源:

void RTC_Init(void) { RTC_TimeTypeDef sTime = {0}; sTime.Hours = 12; sTime.Minutes = 0; sTime.Seconds = 0; HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN); }

5.2 按键时间调整

采用状态机实现多功能按键:

void Key_Process(void) { if(KEY1_Pressed()) { mode = (mode+1)%3; // 切换设置模式 } if(mode == 1) { if(KEY2_Pressed()) hours++; if(KEY3_Pressed()) hours--; } // 其他模式类似... }

6. Proteus仿真注意事项

  1. 数码管扫描频率建议设置在200-500Hz之间,过低会闪烁,过高可能导致仿真卡顿
  2. LCD1602的使能信号E脉宽需要>450ns,仿真时可适当增加延时
  3. 使用"Digital"仿真模式而非"Mixed"模式,可提高运行速度
  4. 定时器参数需要根据仿真速度调整,实际1ms定时可能对应仿真参数(10,884)

7. 常见问题排查

  1. LCD显示乱码:
  • 检查初始化时序是否严格遵循数据手册
  • 测量VO引脚电压(应为0.5Vcc左右)
  • 在第一次初始化后延迟500ms再操作
  1. 数码管显示错位:
  • 确认位选和段选信号没有接反
  • 检查动态扫描间隔时间(建议2-5ms)
  • 增加位选信号切换后的消隐时间
  1. 时间走时不准:
  • 调整RTC异步预分频器(PREDIV_A)和同步预分频器(PREDIV_S)
  • 在仿真中可以用"Debug->Set Animation Options"调整时间因子

这个项目我做过多次迭代,发现最关键的优化点是显示刷新策略。通过将LCD的刷新分散到不同周期,并合理设置数码管扫描频率,可以显著降低CPU占用率。实际测试中,这个方案即使在加入温度显示等功能后,仍然能保持流畅运行。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询