# 电子时钟demo **Repository Path**: djjcdjb66/clock-demo ## Basic Information - **Project Name**: 电子时钟demo - **Description**: No description available - **Primary Language**: Unknown - **License**: MulanPSL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 1 - **Created**: 2025-12-27 - **Last Updated**: 2026-01-10 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ![image-20251230204242140](media/image-20251230204242140.png) # 需求 利用6818开发板绘制电子时钟 简易: 简单实现时钟功能 升级: 加刻度和数字 进阶: 获取日期,天气 # 功能实现 1.画圆,定中心点和半径 2.时针和分针秒针的长度不一样且随着时间变化另一个点规律变化 2.1规律变化:开始的时候获取一次时间然后sleep()来规律变化 还是 循环获取时间,每一秒都记录? 3.难点:程序运行获取当前时间并对应时针和分针秒针指向的位置 ## 遇到的困难 ### 1.开发板中默认时间 ![image-20251225194902789](media/image-20251225194902789.png) 解决: ![image-20251225195303808](media/image-20251225195303808.png) 修正后默认时间 ![image-20251225195511101](media/image-20251225195511101.png) ```bash 在 ARM 开发板或 Ubuntu 上校准时间: 1. **设置系统时间**: date -s "2023-06-02 15:46:00" 2. **写入硬件时钟 (RTC)** (确保断电不丢失): hwclock -w 3. **重启验证**:`reboot` ``` 完美解决 ### 2.画秒针 原理: 通过**极坐标到直角坐标的转换**绘制秒针: 1. **角度计算** `sec * 6.0 * PI/180.0` 将秒数转换为弧度(一圈 60 秒,每秒 6 度,再转为弧度)。 2. **坐标计算** - `SEC_LEN * sin(angle)` 得到秒针末端相对于圆心的水平偏移。 - `SEC_LEN * cos(angle)` 得到垂直偏移(因为屏幕坐标系 Y 轴向下,所以用 `-cos` 使角度从 12 点方向顺时针增长)。 3. **实际坐标** 将圆心坐标 `(DIAL_CENTER_X, DIAL_CENTER_Y)` 加上偏移,得到秒针末端坐标 `(end_x, end_y)`。 4. **绘制** 调用 `lcd_draw_line` 从圆心到末端画红色线段,形成秒针。 **核心**:利用三角函数,根据秒数实时计算秒针末端位置,每秒更新一次绘制。 第一次画秒针出现一直显示的情况于是设计了空白秒针在后面追 ![image-20251227145205147](media/image-20251227145205147.png) ![image-20251227144352165](media/image-20251227144352165.png) ### 3.画刻度 思路: 12个大刻度:每个刻度之间夹角为30度,可以找离圆心近的点near和远的点far,然后连线 每2个大刻度之间有4个小刻度,每个小刻度之间夹角为6度,和秒针对应,所以可以先画小刻度再画大刻度覆盖对应的位置 核心流程: ```c //near点 int near_x1 = DIAL_CENTER_X + (int)((DIAL_RADIUS-SMALL_MARK_LEN) * sin(angle));//半径-刻度长度=near刻度到圆心的距离 int near_y1 = DIAL_CENTER_Y - (int)((DIAL_RADIUS-SMALL_MARK_LEN) * cos(angle)); //far点 int far_x1 = DIAL_CENTER_X + (int)(DIAL_RADIUS * sin(angle));//far刻度点到圆心的距离就是半径 int far_y1 = DIAL_CENTER_Y - (int)(DIAL_RADIUS * cos(angle)); //连接near和far点 lcd_draw_line(lcd,near_x1,near_y1,far_x1,far_y1,BLACK); ``` 后续大刻度还要描粗,画2根线即可(亲测跨度0.2最合适,1太大了) ### 4.画时针 24小时制的时间--->12小时制的圆盘时间 hour%12,时针刻度之间差了30° ```c int clock_hour=hour%12; double angle=clock_hour*30*PI/180; int end_x=DIAL_CENTER_X+(int)(HOUR_LEN*sin(angle)); int end_y=DIAL_CENTER_Y-(int)(HOUR_LEN*cos(angle)); //划线,从圆点到终点 lcd_draw_line(lcd,DIAL_CENTER_X,DIAL_CENTER_Y,end_x,end_y,BLACK); ``` 怎么设计时针一直在动? 时针60*60s动30度,1s动多少度? 30/3600 上面做法不能对应时针平滑的运动 改进:引入分针和秒针的偏移 ```c //时针 void clock_drawhour(LCDP lcd,int hour,int min,int sec) { //1.时间角度 double angel_h=(hour%12)*30.0; //2.分钟的角度,60分钟走30度,每分钟走0.5度 double angel_m=(30.0/60.0)*min; //3.秒针的角度,1s走30.0 / 3600.0 double angle_s=sec * (30.0 / 3600.0); //总角度 double total_angle=angel_h+angel_m+angle_s; //画时针 //计算弧度角 double rad_angle=(total_angle)*PI/180.0; int end_x=DIAL_CENTER_X+(int)(HOUR_LEN*sin(rad_angle)); int end_y=DIAL_CENTER_Y-(int)(HOUR_LEN*cos(rad_angle)); //划线,从圆点到终点 lcd_draw_line(lcd,DIAL_CENTER_X,DIAL_CENTER_Y,end_x,end_y,BLACK); } ``` ### 5.画分钟 同上时针,分针60分钟走360度,一分钟走6度, 60*60s走360度,每秒走360.0/3600.0度 ```c //分针 void clock_drawmin(LCDP lcd,int min,int sec) { //分钟的角度 double angle_m=min*6.0; //秒针的角度 double angle_s=sec*(360.0/3600.0); //总角度 double total_angle=angle_m+angle_s; //画分针 //计算弧度角 double rad_angle=total_angle*PI/180.0; int end_x=DIAL_CENTER_X+(int)(MINUTE_LEN*sin(rad_angle)); int end_y=DIAL_CENTER_Y-(int)(MINUTE_LEN*cos(rad_angle)); //划线,从圆点到终点 lcd_draw_line(lcd,DIAL_CENTER_X,DIAL_CENTER_Y,end_x,end_y,BLACK); } ``` ### 6.针转动的时候上一秒的时候的遗留难清除问题 前面画秒针的时候我们利用了画一个前一秒的空白秒针来追来解决这个问题,但是到后面发现当时针分针这种每秒钟转动角度小的时候,上一秒的空白针会覆盖原来的,所以我们需要想一个其它的方法来解决这个问题,此时我想到了整个绘制过程都放在while循环里,每秒钟都绘制一次,循环中最后的时候清屏。 ### 7.移植lvgl