找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 9004|回复: 21
收起左侧

STC8单片机+DS3231+WS2812做的全彩RGB挂钟程序原理图资料

  [复制链接]
ID:390416 发表于 2021-1-3 20:43 | 显示全部楼层 |阅读模式
A、红色常亮表示时针,绿色慢呼吸灯表示分针、蓝色每秒走一灯。
B、长按Set键开始调时,短按Set选择时、分、秒,再长按Set退出。红色快闪是调时针、绿色快闪是调分针、蓝色快闪是调秒针
C、短按+键 时间增进、短按-键 时间减回。
D、短按LED键,调整背景色 红、绿、蓝、黄、青、紫
F、可以自己编写其他WS2812相关程序,如流水灯、流星灯效果
源代码的文件太多了 所以用压缩包形式提供
制作出来的实物图如下:
WS2812全彩挂钟 背景紫色.jpg WS2812全彩挂钟 背景灭灯.jpg

电路原理图如下:
51hei.png

单片机源程序如下:
  1. //时钟程序,2020年9月,汪祁绪原创。
  2. //店铺:祁绪电子
  3. #include "all.h"
  4. u8 xdata Set_Mode=Set_Timer_OFF;                                        //设置时间状态变量
  5. u8 xdata LED_Mode=Set_Back_OFF;                                                //设置背景状态变量
  6. u8 xdata LD_hour=LED_LD;                                                        //默认最大128亮度
  7. u8 xdata LD_min=LED_LD;                                                                //默认最大128亮度
  8. u8 xdata LD_sec=LED_LD;                                                                //默认最大128亮度
  9. u8 xdata Back_R=0;                                                                        //背景亮度R
  10. u8 xdata Back_G=0;                                                                        //背景亮度G
  11. u8 xdata Back_B=0;                                                                        //背景亮度B

  12. //根据调整的时针、分针、秒针 分别让R\G\B快速闪烁显示(快速呼吸)
  13. void LED_PWM_Allot()
  14. {
  15.         static u8 xdata sec_count;
  16.         static bit PWM_Flag;
  17.         switch(Set_Mode)
  18.         {
  19.                 case Set_Timer_OFF         :                                                //默认状态,直接显示时间,分针是呼吸灯效果
  20.                 {
  21.                         sec_count++;
  22.                         if(sec_count==255)
  23.                         {
  24.                                 if(PWM_Flag==0)                                                //PWM增加
  25.                                 {
  26.                                         LD_min++;
  27.                                         if(LD_min>=LED_LD)                                //默认最大128亮度
  28.                                         {
  29.                                                 PWM_Flag=1;
  30.                                         }
  31.                                 }
  32.                                 if(PWM_Flag==1)                                                //PWM减少
  33.                                 {
  34.                                         LD_min--;
  35.                                         if(LD_min==0)
  36.                                         {
  37.                                                 PWM_Flag=0;
  38.                                         }
  39.                                 }
  40.                         }
  41.                         LD_hour=LED_LD;                                                        //时针保持最大亮度128
  42.                         LD_sec=LED_LD;                                                        //秒针保持最大亮度128
  43.                 }break;
  44.                
  45.                 case Set_Timer_hour :                                                //时针调整模式,时针快速闪烁
  46.                 {
  47.                         sec_count++;
  48.                         if(sec_count==255)
  49.                         {
  50.                                 if(PWM_Flag==0)                                                //PWM增加
  51.                                 {
  52.                                         LD_hour+=10;
  53.                                         if(LD_hour>=LED_LD)                                //默认最大128亮度
  54.                                         {
  55.                                                 PWM_Flag=1;
  56.                                         }
  57.                                 }
  58.                                 if(PWM_Flag==1)                                         //PWM减少
  59.                                 {
  60.                                         LD_hour-=10;
  61.                                         if(LD_hour<=10)
  62.                                         {
  63.                                                 PWM_Flag=0;
  64.                                         }
  65.                                 }
  66.                         }
  67.                         LD_min=LED_LD;                                                        //分针保持最大亮度128
  68.                         LD_sec=LED_LD;                                                        //秒针保持最大亮度128
  69.                 }break;
  70.                
  71.                 case Set_Timer_min :                                                //分针设置模式,分针快速闪烁
  72.                 {
  73.                         sec_count++;
  74.                         if(sec_count==255)
  75.                         {
  76.                                 if(PWM_Flag==0)                                                //PWM增加
  77.                                 {
  78.                                         LD_min+=10;
  79.                                         if(LD_min>=LED_LD)                                //默认最大128亮度
  80.                                         {
  81.                                                 PWM_Flag=1;
  82.                                         }
  83.                                 }
  84.                                 if(PWM_Flag==1)                                         //PWM减少
  85.                                 {
  86.                                         LD_min-=10;
  87.                                         if(LD_min<=10)
  88.                                         {
  89.                                                 PWM_Flag=0;
  90.                                         }
  91.                                 }
  92.                         }
  93.                         LD_hour=LED_LD;                                                        //时针保持最大亮度128
  94.                         LD_sec=LED_LD;                                                        //秒针保持最大亮度128
  95.                 }break;
  96.                
  97.                 case Set_Timer_sec :                                                //秒针设置模式、秒针快速闪烁
  98.                 {
  99.                         sec_count++;
  100.                         if(sec_count==255)
  101.                         {
  102.                                 if(PWM_Flag==0)                                                //PWM增加
  103.                                 {
  104.                                         LD_sec+=10;
  105.                                         if(LD_sec>=LED_LD)                                //默认最大128亮度
  106.                                         {
  107.                                                 PWM_Flag=1;
  108.                                         }
  109.                                 }
  110.                                 if(PWM_Flag==1)                                         //PWM减少
  111.                                 {
  112.                                         LD_sec-=10;
  113.                                         if(LD_sec<=10)
  114.                                         {
  115.                                                 PWM_Flag=0;
  116.                                         }
  117.                                 }
  118.                         }
  119.                         LD_hour=LED_LD;                                                        //时针保持最大亮度128                                                       
  120.                         LD_min=LED_LD;                                                        //分针保持最大亮度128
  121.                 }break;
  122.         }
  123. }

  124. //让所以灯珠都使用背景值,然后让时间决定那颗灯点亮
  125. void WS2812_Allot()
  126. {
  127.         u8 xdata WS2812_hour;
  128.         u8 xdata WS2812_min;
  129.         u8 xdata WS2812_sec;
  130.         static u8 data i;
  131.         i=i%180;
  132.         i++;
  133.         WS2812_Write_Buffer[i]=Back_R;                                        //先写入背景色
  134.         WS2812_Write_Buffer[i+1]=Back_G;                                //先写入背景色
  135.         WS2812_Write_Buffer[i+2]=Back_B;                                //先写入背景色
  136.         i++;
  137.         i++;
  138.        
  139.         WS2812_hour=DS3231_Timer.hour;                                        //当前时间赋值给2812小时
  140.         WS2812_hour=WS2812_hour%12;                                                //24小时制转换成12小时制
  141.         WS2812_hour--;                                                                        //先把小时减少1
  142.         if(WS2812_hour>24)                                                                //如果是0减去1=255,255大于24
  143.         {
  144.                 WS2812_hour=12;                                                                //说明当前时间是12点(也就是0点)因为WS2812是没有0号灯,只有60号灯
  145.         }
  146.         else
  147.         {
  148.                 WS2812_hour++;                                                                //否则,增加1,保持当前小时
  149.         }
  150.         WS2812_Write_Buffer[(WS2812_hour)*15-2]=LD_hour;//一个小时是5个灯,每个灯三种颜色
  151.         WS2812_min=DS3231_Timer.min;                                                        //当前时间赋值给2812分钟
  152.         WS2812_min=WS2812_min%60;                                                //最多60分钟
  153.         WS2812_min--;                                                                        //先把分钟减少1
  154.         if(WS2812_min>=240)                                                                //如果是0减去1=255,255大于250
  155.         {
  156.                 WS2812_min=60;                                                                //说明当前时间是60分(也就是0分)因为WS2812是没有0号灯,只有60号灯
  157.         }
  158.         else
  159.         {
  160.                 WS2812_min++;                                                                //否则,增加1,保持当前分钟
  161.         }
  162.         WS2812_Write_Buffer[(WS2812_min)*3-1]=LD_min;        //每个灯三种颜色
  163.         WS2812_sec=DS3231_Timer.sec;                                                        //当前时间赋值给2812分钟
  164.         WS2812_sec=WS2812_sec%60;                                                //最多60秒
  165.         WS2812_sec--;                                                                        //先把秒减少1
  166.         if(WS2812_sec>=240)                                                                //如果是0减去1=255,255大于100
  167.         {
  168.                 WS2812_sec=60;                                                                //说明当前时间是60秒(也就是0秒)因为WS2812是没有0号灯,只有60号灯
  169.         }
  170.         else
  171.         {
  172.                 WS2812_sec++;                                                                //否则,增加1,保持当前秒
  173.         }
  174.         WS2812_Write_Buffer[(WS2812_sec)*3]=LD_sec;                //每个灯三种颜色       
  175.        
  176.         WS2812_Display_Drive();                                                        //WS2812刷新显示
  177. }

  178. // DS3231 数据分配
  179. void Calendar_allot()
  180. {
  181.         /*static u16 xdata count=0;
  182.         count++;
  183.         if(count==100)
  184.         {
  185.                 count=0;*/
  186.                 DS3231_Read_Time_Drive();
  187.                 Calendar_Modify_Timer_Ser();
  188.         //}
  189. }

  190. //按键扫描
  191. void ROTARY_Allot()
  192. {
  193.         KEY_Scan_Drive_Up();
  194.         KEY_Scan_Drive_Down();
  195.         KEY_Scan_Drive_Set();
  196.         KEY_Scan_Drive_LED();
  197. }

  198. //LED背景设置 PWM是1,黑、红、绿、蓝、黄、青、紫、白
  199. void LED_Back_Set()
  200. {
  201.         if(Key_Read_LED==1)                                               
  202.         {
  203.                 Key_Read_LED=0;                                                                                //按键清除归位
  204.                 LED_Mode++;                                                                                        //状态机加一次
  205.                 LED_Mode=LED_Mode%Set_Back_RGB;
  206.         }
  207.         switch(LED_Mode)
  208.         {
  209.                 case Set_Back_OFF:Back_R=0;Back_G=0;Back_B=0;break;
  210.                 case Set_Back_R  :Back_R=1;Back_G=0;Back_B=0;break;
  211.                 case Set_Back_G  :Back_R=0;Back_G=1;Back_B=0;break;
  212.                 case Set_Back_B  :Back_R=0;Back_G=0;Back_B=1;break;
  213.                 case Set_Back_RG :Back_R=1;Back_G=1;Back_B=0;break;
  214.                 case Set_Back_GB :Back_R=0;Back_G=1;Back_B=1;break;
  215.                 case Set_Back_BR :Back_R=1;Back_G=0;Back_B=1;break;
  216.                 case Set_Back_RGB:Back_R=1;Back_G=1;Back_B=1;break;
  217.         }
  218.         Uart1_Up_Num_Buffer[4]=LED_Mode%100%10;
  219. }//*/

  220. //主函数
  221. void main()
  222. {
  223.         WS2812_Init();
  224.         Key_Init();
  225.         IIC_Init();
  226.         Uart1_Init();
  227.         while(1)
  228.         {
  229.                 LED_PWM_Allot();
  230.                 WS2812_Allot();
  231.                 Calendar_allot();
  232.                 ROTARY_Allot();
  233.                 Uart1_Up_Data_Drive();
  234.                 LED_Back_Set();
  235.         }
  236. }
复制代码
全部资料51hei下载地址:
WS2812全彩挂钟 程序源码 最简单的RGB测试.zip (68.17 KB, 下载次数: 246)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:78901 发表于 2021-1-7 23:35 | 显示全部楼层
谢谢分享,正好有一个60个转盘的ws2811,仿制一个试试
回复

使用道具 举报

ID:390416 发表于 2021-1-10 11:49 | 显示全部楼层
fsj5098 发表于 2021-1-7 23:35
谢谢分享,正好有一个60个转盘的ws2811,仿制一个试试

嗯 记得IIC要上拉电阻
回复

使用道具 举报

ID:60656 发表于 2021-1-12 20:49 | 显示全部楼层
多谢分享 原理图弄得漂亮
回复

使用道具 举报

ID:876085 发表于 2021-1-13 12:19 来自手机 | 显示全部楼层
你好,有编译好的固件吗?
回复

使用道具 举报

ID:876085 发表于 2021-1-13 14:43 来自手机 | 显示全部楼层
你好,有编译好的固件吗?
回复

使用道具 举报

ID:250631 发表于 2021-1-13 17:02 | 显示全部楼层
编译通过。感谢楼主的无私分享
回复

使用道具 举报

ID:65956 发表于 2021-1-14 08:51 | 显示全部楼层
很牛,曾经也有这样的想法,可是一时也条件作,如果你这个中间再加1个数码显示的时钟,那就更完美了,就可作商业销售了
回复

使用道具 举报

ID:872598 发表于 2021-1-17 19:33 | 显示全部楼层
建议在每个LED再加一条导光柱,这样看起来更像一个时钟。
回复

使用道具 举报

ID:91165 发表于 2021-1-20 16:16 | 显示全部楼层
刘工程 发表于 2021-1-17 19:33
建议在每个LED再加一条导光柱,这样看起来更像一个时钟。

不做批量的话,自己做导光柱困难吧
回复

使用道具 举报

ID:78901 发表于 2021-1-20 16:59 | 显示全部楼层
可以用15WK104单片机做吗
回复

使用道具 举报

ID:390416 发表于 2021-1-20 17:00 | 显示全部楼层
aking991 发表于 2021-1-14 08:51
很牛,曾经也有这样的想法,可是一时也条件作,如果你这个中间再加1个数码显示的时钟,那就更完美了,就可 ...

现在有条件 可以做了啊 这个简单点就用WS2812灯带做
回复

使用道具 举报

ID:390416 发表于 2021-1-20 17:03 | 显示全部楼层
本帖最后由 人人学会单片机 于 2021-1-20 17:04 编辑
fsj5098 发表于 2021-1-20 16:59
可以用15WK104单片机做吗

可以,修改一下WS2812的延迟,IIC总线必须外部上拉电阻就行。因为STC8G和STC8H 有内部上拉,所以原理图没有外部上拉。
回复

使用道具 举报

ID:3802 发表于 2021-6-22 15:10 | 显示全部楼层
谢谢分享,正好有一个60个转盘的ws2811,仿制一个试试
回复

使用道具 举报

ID:59830 发表于 2022-1-19 21:22 | 显示全部楼层
也有一个WS2812 时钟程序,60灯驱动. 参考学习一下.
回复

使用道具 举报

ID:515930 发表于 2022-1-20 14:01 | 显示全部楼层

也有一个WS2812 时钟程序,60灯驱动. 参考学习一下.
回复

使用道具 举报

ID:102189 发表于 2023-5-26 20:34 | 显示全部楼层
为什么我的不行呀
回复

使用道具 举报

ID:102189 发表于 2023-5-26 21:06 | 显示全部楼层
回复

使用道具 举报

ID:102189 发表于 2023-5-26 21:07 | 显示全部楼层
单片机需要加上拉电阻吗
回复

使用道具 举报

ID:339520 发表于 2023-6-19 13:39 | 显示全部楼层
1毛钱的应广PMS150G驱动WS2812代码写出来了。
回复

使用道具 举报

ID:339520 发表于 2023-6-19 13:41 | 显示全部楼层
1毛钱的应广单片机PMS150G驱动WS2812代码我写完了。
回复

使用道具 举报

ID:224580 发表于 2023-9-28 17:33 | 显示全部楼层
向高手致敬
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表