
最丐条形时钟
简介
用查理复用法驱动数码管,外接ds1302时钟芯片, 无源蜂鸣器播音乐,热敏电阻测量温度,中规中矩的时钟, 兼容HK32F030M,STM8S003,n76e003at20
简介:用查理复用法驱动数码管,外接ds1302时钟芯片, 无源蜂鸣器播音乐,热敏电阻测量温度,中规中矩的时钟, 兼容HK32F030M,STM8S003,n76e003at20开源协议
:GPL 3.0
描述
前言
数码管驱动电路:查理复用法
8个io驱动8位7段数码管,而且电路和最丐机械键盘的无按键冲突电路非常类似。所以取名一致。
数码管集成在PCB上,通过3D打印部件进行透光柔和,外壳显示一体化更加美观。
后期尝试做脚对脚兼容芯片的程序移植,当前先开发这次活动的金主:航顺HK32F030M。
吐槽一下烧写口位置和硬件I2C复用,不能边debug边用I2C。
电路原理说明
这是用查理复用法3个io驱动6个LED的原理图,

假设此时P1高,P3低,P2高阻,此时LED6亮,虽然LED1和LED3串联有正向电压,但由于LED6钳位,使得电压不足以同时导通。

若P1高,P2、P3都为低,此时LED1和LED6都亮,都亮度不及上面的状态,因为两个LED的电流都流过P3电阻,P3电阻分压加大。

所以每个限流电阻上并联一个二极管,利用单向导通性,使得电阻在特定电流方向下,两端分压一致,使得同时亮的LED亮度一致。

核心算法说明
不是说我代码不开源,而是代码放出来了,即使有100个人下载。然而有80个人看不懂。
那我不如只列出特别的算法,图文并茂地讲解,让更多人能看懂。
大家可以看我GD32杯的电源工程,
虽然最后功能并不成功,但经常隔三差五就被人收藏克隆慢慢吃透,但唯独没什么人点赞【PS:你们倒是把三个都点上啊。你们的支持就是我更新的动力】。
你们有什么想看的算法评论区里提。有空我会后续更新。
ADC超采样:
由技术文档可知HK32F030M的ADC有效精度是8bit,如果温度要显示到小数点后1位起码要12bit的ADC,
这怎么办呢?
这时就可以用超采样技术。
第一步,ADC设置成连续转换,EOC转换完成中断
void ADC_init()
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_ADC_PIN ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GOIO_ADC_PORT, &GPIO_InitStructure);
GPIO_PinAFConfig(GOIO_ADC_PORT,GPIO_PinSource6,GPIO_AF_7);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC ,ENABLE);
ADC_DeInit(ADC1);
ADC_StructInit(&ADC_InitStructure);
ADC_ClockModeConfig(ADC1,ADC_ClockMode_SynClkDiv4);//系统时钟4分频,8M
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;//开启连续转换
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//右对齐
ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Backward;//向后扫描
ADC_Init(ADC1,&ADC_InitStructure);
/* ADC1 regular channels configuration */
ADC_ChannelConfig(ADC1, ADC_Channel_1 , ADC_SampleTime_239_5Cycles);
/* Enable EOC interrupt */
ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE);//转换结束中断使能
/* Configure and enable ADC1 interrupt */
NVIC_InitStructure.NVIC_IRQChannel = ADC1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
ADC_GetCalibrationFactor(ADC1);//ADC校准
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADRDY));
ADC_StartOfConversion(ADC1);
}
第二步,在中断里累加ADC读回来的值(反正后面都要求平均数,不如先加起来)。
这里由于按键与热敏电阻共用同一路ADC,为了按键扫描正常,刷新率取比1000Hz稍大的数。
extern uint16_t ntc_data_13b[2];
void ADC1_COMP_IRQHandler(void)
{
static uint8_t i=0;
if(ADC_GetITStatus(ADC1, ADC_IT_EOC) != RESET)
{
ntc_data_13b[0]+=ADC_GetConversionValue(ADC1)>>4;//读取后自动清除EOC标志位
i++;
if(i>=32)//32分频,1041.6Hz
{
i=0;
ntc_data_13b[1]=ntc_data_13b[0];//存入二缓
ntc_data_13b[0]=0;//一缓清零
}
}
}
数码管上下移动动画:
动画特效一大堆,这里举一个简单一点的,用下移做例子

上图展示的是下移的过程,提取重复的部分,只有一个步骤(上移同理)
#define digital_a 0x01
#define digital_b 0x02
#define digital_c 0x04
#define digital_d 0x08
#define digital_e 0x10
#define digital_f 0x20
#define digital_g 0x40
uint8_t digital_putdown(uint8_t dat)
{
uint8_t temp=0;
temp|=(dat&digital_g)?digital_d:0;//G赋值到D
temp|=(dat&digital_a)?digital_g:0;//A赋值到G
temp|=(dat&digital_b)?digital_c:0;//B赋值到C
temp|=(dat&digital_f)?digital_e:0;//F赋值到E
return temp;//其余没赋值的数据丢弃
}
走时误差校准:
首先这个DS1302很多人都反馈不准,其实是有诀窍的:
这个网址可以参考下:http://www.51hei.com/bbs/dpj-177015-1.html
下面的代码调时间的。
//输入最小数值-86400
void time_adjust(int32_t sec)
{
uint8_t time_temp[7];
uint8_t i;
for(i=0;i<7;i++)
time_temp[i]=bcd2hex(*((uint8_t *)&time_data+i));
if(sec<0)//直接借一天做减法
{
sec+=86400;
time_temp[5]--;//星期是从1到7,不担心溢出
}
time_temp[0]+=sec%60;
if(time_temp[0]>=60)
{
time_temp[1]+=time_temp[0]/60;
time_temp[0]%=60;
}
time_temp[1]+=sec%3600/60;
if(time_temp[1]>=60)
{
time_temp[2]+=time_temp[1]/60;
time_temp[1]%=60;
}
time_temp[2]+=sec/3600;
if(time_temp[2]>=24)
{
time_temp[5]+=time_temp[2]/24;
time_temp[2]%=24;
time_temp[5]%=7;
time_temp[5]=time_temp[5]?time_temp[5]:7;//将零偏移到7
}
for(i=0;i<7;i++)
*((uint8_t *)&time_data+i)=hex2bcd(time_temp[i]);
}
由于我这里没有年月日,只有星期,所以轻松一点。不用考虑更多的进制。
和上面网址里的一样,挑一个夜深人静的时候校准。当然校准时有概率会跳过闹钟。但谁会设置午夜凶铃呢?🤣
加一点补充,怕有人不理解自动校准。
比如你的手表一天快了1分钟。当我只观察这个手表时,这个手表走了1天多1分钟时,调慢1分钟,就能和标准时间对上。
当然在校准前一刻快了的59秒。但每天的累计误差被压缩了。
现在经过我这套算法。设置好后,一个星期最大相差1秒以内。一年下来,误差也就一分钟。
时间校准方法:
每天在同一个固定的时间段来调整时间,先根据第一天的观察来决定要每天偏移多少秒。
输入到AC_DAY的设置里。然后再重新设置时间。
同理,一个星期后再调节AC_WEEK。这样就完成了。
由于校准数据是存在DS1302的内存里的。如果电池没电数据就清空的,建议在PCB上写上校准参数。
PCB成品展示


组装成品展示



时钟动画演示
时钟下都带错位延迟更新效果。
凑巧格式转换成GIF后,速度变慢了,拿来展示效果刚刚好。
无过渡动画:
![1.无动画 00_00_00-00_00_30 [640i].gif](http://image.lceda.cn/pullimage/qibbLzvG5EH7UmFnYn97ADrf8Z72Lr7YcT2PR2U1.gif)
切换后闪烁:
![2.闪烁 00_00_00-00_00_30 [640i].gif](http://image.lceda.cn/pullimage/U1J3Y9pct65AsZJclWH36x3Vcv2NBkl7iBbitHOr.gif)
上移出上移入:
![3.上移移出移入 00_00_00-00_00_30 [640i].gif](http://image.lceda.cn/pullimage/PXr5FYoPKUkCt7kkA0z8YR1UIZrRQ8yWdffcoRG8.gif)
亮度渐变:
![4.渐变 00_00_00-00_00_30 [640i].gif](http://image.lceda.cn/pullimage/5xNfoFGIUYRbsdqvaBUoaE6JI4QCHmnxLTr56z2m.gif)
笔划移位:
![5.笔划移位 00_00_00-00_00_30 [640i].gif](http://image.lceda.cn/pullimage/dZ1Gk81PgyzSFGeA8zoVHFmKfS4JV7Jt5jVK0hue.gif)
逐位更新:
![6.逐位更新 00_00_00-00_00_30 [640i].gif](http://image.lceda.cn/pullimage/Q43kraLoyCyTMyuIQQIdMREUyLPwac7euBafeBTy.gif)
操作逻辑及流程图
按键逻辑:
| 动作时间 | 提示音 | 功能 |
|---|---|---|
| 0.5s内松开 | 松开后有动作提示音 | 加数值或者切换界面 |
| 0.5s~1s松开 | 提示音滴一声后 | 确认或进入 |
| 1s~1.5s松开 | 提示音滴两声后 | 重新设置该数值 |
| 1.5s以上松开 | 提示音滴三声后 | 放弃设置并返回 |
菜单设置流程:


外壳说明
不得不夸赞下立创的光敏打印,价格没比PLA贵,关键是壁厚能做到1mm。
但是最后做出来的均匀光效果不理想,颜色发散,导致晚上看的时候有点糊。
能在里面塞入亚克力导光就可以改善。
下面放3d模型渲染图
前面板
正方字体:

VFD字体

福禄克字体

后面板

打印文件后续我重新设计一些加强结构并且验证过后会再上传到附件,

来自工具人的外壳制作过程
通过数字的槽内壁喷上一层黑漆,再倒入不同颜色的树脂的方法:
黑漆防止泛光,
白色树脂将led的光线匀开,
透明树脂将光投射到上层。

遮盖

喷漆+倒胶+擦拭油漆
喷漆前一天熬夜上头忘记拍喷漆和倒胶了,就只留个倒胶图吧。加上滴胶凝固大约1天
关于滴胶之前尝试过按1/3比例配置但比例没控制好,重新试了下发现树脂混合时比较稀的时候效果最好。

成品
滴胶挺硬的,两侧泛光的现象几乎没有,但led的光晕开效果不明显,而且正面效果确实不咋地,
数字面板几乎是全黑的,等想做2.0看先灌白色树脂再喷漆效果如何吧。


程序细节
音乐清单:
开机音乐:《全家开门铃声》
下面音乐可设置为闹钟铃声:
- 《天空之城》
- 《永远同在》
- 《华为主题曲》
- 《电磁炮》op1
- 《紫色激情》开头循环
- 《克罗地亚狂想曲》
- 《this game》
- 《next to you》
- 《柯南主题曲》
- 《青鸟》
V05的歌曲数组已经占用了6k的ROM,总共16K的ROM空间已经吃干抹净了,
后续可能会用MIDI乐谱来转换,可能歌曲数量就更少了。看情况,咕咕咕。
程序更新日志:
V00
- 时钟+温度功能,暂时没有闹钟功能
- 设置界面下,短按松开是加,滴一声后松开确认
- 运行界面下,短按换界面,滴一声后松开进入设置
- 星期温度界面下,等待10秒后自动返回时间界面,短按松开切换时钟特效并返回走时界面
- 上电自检DS1302内存,若数据丢失,则进入星期时间设置,并关闭充电模式
V01
- 完善闹钟功能,闹钟时间保存在DS1302内,电池没电后一起复位
- 显示时间时按住1.5秒后松开切换数码管过渡动画
- 温度显示精确到小数点后一位
- 加入移位刷新与移位移出移入动画
- 闹钟音乐加入《电磁炮》op1
- 杂项设置菜单未完成,无法进入选项
V02
- 音乐添加《紫色激情》,《克罗地亚》,《this game》,《next to you》,《柯南主题曲》,《青鸟》
- 开机音乐替换为《头文字D》开头
- 音调输出改为pwm模式,减少中断次数
V03
- 开机音乐替换为《帝国进行曲》开头
- 音乐完善《紫色激情》,《头文字D》,添加《学猫叫》,《记忆》,《愤怒的小鸟》
- 占空比下调到25%,以降低音质来换功耗
V04
- 音乐添加《命运石之门》,并无损压缩部分音乐
- 部分GPIO配置改为操作寄存器
- 修复闹钟设置的回退层级问题
V05
- 每日/每周走秒误差补偿
- 若在一周内重新上电,校正这一周的累计误差
- 音量/音色,过渡动画可调,且掉电保存
- 存储格式改为结构体,提高代码阅读性
- 若开机发现为掉电状态,闹钟,设置,重置为默认值
- 更换音乐《紫色激情》来换取代码空间
已知硬件问题:
- 上电冲击可能导致DS1302时间复位,可能是个别芯片现象,更换DS1302或者加大滤波电容或者将DS1302供电改3.3V可解决
- 蜂鸣器长时间运行导致电路板升温会影响温度检测
- 3.3V单片机因为导通压降的原因,只能用红黄橙的LED,更换宽电压单片机和去掉稳压块可解决,等待后续其他单片机支持。
感谢引用:
原理说明图片来源:https://blog.csdn.net/m0_38106923/article/details/83242204
流程图绘制工具:腾讯文档
设计图
未生成预览图,请在编辑器重新保存一次BOM
暂无BOM
克隆工程知识产权声明&复刻说明
本项目为开源硬件项目,其相关的知识产权归创作者所有。创作者在本平台上传该硬件项目仅供平台用户用于学习交流及研究,不包括任何商业性使用,请勿用于商业售卖或其他盈利性的用途;如您认为本项目涉嫌侵犯了您的相关权益,请点击上方“侵权投诉”按钮,我们将按照嘉立创《侵权投诉与申诉规则》进行处理。
请在进行项目复刻时自行验证电路的可行性,并自行辨别该项目是否对您适用。您对复刻项目的任何后果负责,无论何种情况,本平台将不对您在复刻项目时,遇到的任何因开源项目电路设计问题所导致的直接、间接等损害负责。









