野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 8898|回复: 8

刚入门几天,写个七彩光球的程序

[复制链接]
发表于 2018-1-7 09:39:59 | 显示全部楼层 |阅读模式
先科普一下,七彩光球就是这样的一个球球
2.jpg



亮着的时候会不停变换各种颜色,不同颜色的变化都是平滑过渡不会发生颜色的突变

9.jpg
8.jpg
7.jpg
6.jpg
5.jpg



球底部有两个按钮,一个是Colorful,亮彩色灯光;
一个是White,亮白色灯光,白色灯光有3档亮度,按White按键切换亮度。
光球底部的按键和开发板上的K1、K2按键一一对应。

123.png



本人STM32初学者,目前跟着火哥的视频学了几天,刚学完GPIO和按键,就想做点东西出来玩玩,这样才能获得一点成就感。
刚好手边有个七彩光球,就在STM32F429开发板上也做一个试试,实现和这个光球一样的功能。


运行程序很简单,只要将附件的程序下载下来,解压后,用Keil5打开Project——>Colorful.uvprojx。
再编译一下,最后下载到野火F429开发板上,就可以看到效果了。
程序上有详细注释。

程序请点这里下载 ------------>>>>>   Colorful.zip (595.82 KB, 下载次数: 29)

上电默认是彩灯程序。
为了跟七彩光球实物颜色变化的速度保持一致,彩灯程序运行的时候颜色变化比较慢,请观看的时候稍微给点耐心哈


如果编译出错,看看编译路径设置有没有问题,也可以把下文的所有代码复制到确定能用的Main.c里面再编译。
不是F429开发板的需要改一下程序里的两个按键输入和3个LED输出端口。

下页贴代码









4.jpg
回复

使用道具 举报

 楼主| 发表于 2018-1-7 09:41:01 | 显示全部楼层
贴代码上来

  1. /*
  2. 功能:通过开发板上2个用户按键实现七彩灯光和白色灯光的切换,模拟七彩光球的工作状态。
  3. 第一个按键是七彩灯效果,开机默认运行七彩灯效果。
  4. 第二个按键是白光效果,不断按下第二个按键还可以调节白光亮度,从最亮到完全熄灭依次循环,共3档亮度可调。
  5. 特点:七彩灯光和白光模式都会不断检测按键,所以在不使用定时器和中断的情况下,按键切换基本无延迟。
  6. */


  7. #include "stm32f4xx.h"

  8. //前置函数声明
  9. void timeout(unsigned int count);
  10. uint8_t Key_Scan(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
  11. int Bright(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
  12. int Dark(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

  13. int main(void)
  14. {
  15.         //开启GPIOA、GPIOC和GPIOH的时钟
  16.         RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA|RCC_AHB1Periph_GPIOC|RCC_AHB1Periph_GPIOH, ENABLE);
  17.        

  18.         //有关LED的初始化
  19.         GPIO_InitTypeDef GPIO_InitStruct;
  20.         GPIO_InitStruct.GPIO_Pin=GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12;
  21.         GPIO_InitStruct.GPIO_Mode=GPIO_Mode_OUT;
  22.         GPIO_InitStruct.GPIO_Speed=GPIO_Low_Speed;
  23.         GPIO_InitStruct.GPIO_OType=GPIO_OType_PP;
  24.         GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_UP;
  25.         GPIO_Init(GPIOH, &GPIO_InitStruct);
  26.        
  27.        
  28.         //有关按键1的初始化
  29.         GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0;
  30.         GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN;
  31.         GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_DOWN;
  32.         GPIO_Init(GPIOA, &GPIO_InitStruct);
  33.        
  34.        
  35.         //有关按键2的初始化
  36.         GPIO_InitStruct.GPIO_Pin=GPIO_Pin_13;
  37.         GPIO_Init(GPIOC, &GPIO_InitStruct);
  38.        

  39.         //先将3个LED灯关掉
  40.         GPIO_SetBits(GPIOH, GPIO_Pin_10);
  41.         GPIO_SetBits(GPIOH, GPIO_Pin_11);
  42.         GPIO_SetBits(GPIOH, GPIO_Pin_12);
  43.        

  44.        
  45.        
  46.         /*
  47.         a的值决定了亮灯的颜色和方式。
  48.         a==0,是七彩灯光(红灯、绿灯、蓝灯交替点亮和熄灭,两种不同亮度的灯光可以混合成多种颜色,视觉上看是无缝衔接的七彩变化)。
  49.         a==1,是白光1档,高亮度。
  50.         a==2,是白光2档,中亮度。
  51.         a==3,是白光3档,低亮度。
  52.         a==4,所有灯熄灭。
  53.         a==-1,红灯逐渐亮起,用于七彩灯光程序运行的开头。
  54.         */
  55.   int a=-1;

  56.         while(1)
  57.         {
  58.                 switch (a)
  59.                 {
  60.                         case -1:
  61.                         {
  62.                                 if (Bright(GPIOH,GPIO_Pin_10)==1)//红渐亮,用于七彩灯光程序的开头
  63.                                 {
  64.                                         a=1;
  65.                                         break;
  66.                                 }
  67.                                         a=0;
  68.                                 break;
  69.                         }
  70.                        

  71.                         case 0:
  72.                         {
  73.                                 if (Bright(GPIOH,GPIO_Pin_12)==1)//蓝渐亮
  74.                                 {
  75.                                         a=1;
  76.                                         break;
  77.                                 }

  78.                                 if (Dark(GPIOH,GPIO_Pin_10)==1)  //红渐灭
  79.                                 {
  80.                                         a=1;
  81.                                         break;
  82.                                 }
  83.        
  84.                                 if (Bright(GPIOH,GPIO_Pin_11)==1)//绿渐亮
  85.                                 {
  86.                                         a=1;
  87.                                         break;
  88.                                 }

  89.                                 if (Dark(GPIOH,GPIO_Pin_12)==1)  //蓝渐灭
  90.                                 {
  91.                                         a=1;
  92.                                         break;
  93.                                 }

  94.                                 if (Bright(GPIOH,GPIO_Pin_10)==1)//红渐亮
  95.                                 {
  96.                                         a=1;
  97.                                         break;
  98.                                 }

  99.                                 if (Dark(GPIOH,GPIO_Pin_11)==1)  //绿渐灭
  100.                                 {
  101.                                         a=1;
  102.                                         break;
  103.                                 }
  104.                                
  105.                                 break;
  106.                         }
  107.                        

  108.                         case 1:                                //白光1档
  109.                         {
  110.                                 GPIO_ResetBits(GPIOH, GPIO_Pin_10);  //红、绿、蓝全部最大亮度
  111.                                 GPIO_ResetBits(GPIOH, GPIO_Pin_11);
  112.                                 GPIO_ResetBits(GPIOH, GPIO_Pin_12);
  113.                                
  114.                                 if ((Key_Scan(GPIOA, GPIO_Pin_0))==1)  //如果按下了第一个按键,则切换到七彩灯光模式(下同)
  115.                                 {
  116.                                         GPIO_SetBits(GPIOH, GPIO_Pin_10);
  117.                                         GPIO_SetBits(GPIOH, GPIO_Pin_11);
  118.                                         GPIO_SetBits(GPIOH, GPIO_Pin_12);
  119.                                   a=-1;
  120.                                 }

  121.                                 if ((Key_Scan(GPIOC, GPIO_Pin_13))==1) //如果按下了第二个按键,则切换到白光2档
  122.                                         a=2;
  123.                                
  124.                                 break;
  125.                         }
  126.                        
  127.                        
  128.                         case 2:                                //白光2档
  129.                         {
  130.                                 GPIO_ResetBits(GPIOH, GPIO_Pin_10);
  131.                                 GPIO_ResetBits(GPIOH, GPIO_Pin_11);
  132.                                 GPIO_ResetBits(GPIOH, GPIO_Pin_12);
  133.                           timeout(3000);
  134.                                 GPIO_SetBits(GPIOH, GPIO_Pin_10);
  135.                                 GPIO_SetBits(GPIOH, GPIO_Pin_11);
  136.                                 GPIO_SetBits(GPIOH, GPIO_Pin_12);
  137.                           timeout(4000);
  138.                                
  139.                                 if ((Key_Scan(GPIOA, GPIO_Pin_0))==1)
  140.                                         a=-1;

  141.                                 if ((Key_Scan(GPIOC, GPIO_Pin_13))==1) //如果按下了第二个按键,则切换到白光3档
  142.                                         a=3;
  143.                                
  144.                                 break;
  145.                         }
  146.                        
  147.                        
  148.                         case 3:                                //白光3档
  149.                         {
  150.                                 GPIO_ResetBits(GPIOH, GPIO_Pin_10);
  151.                                 GPIO_ResetBits(GPIOH, GPIO_Pin_11);
  152.                                 GPIO_ResetBits(GPIOH, GPIO_Pin_12);
  153.                           timeout(500);
  154.                                 GPIO_SetBits(GPIOH, GPIO_Pin_10);
  155.                                 GPIO_SetBits(GPIOH, GPIO_Pin_11);
  156.                                 GPIO_SetBits(GPIOH, GPIO_Pin_12);
  157.                           timeout(8000);
  158.                                
  159.                                 if ((Key_Scan(GPIOA, GPIO_Pin_0))==1)
  160.                                         a=-1;

  161.                                 if ((Key_Scan(GPIOC, GPIO_Pin_13))==1) //如果按下了第二个按键,则切换到全灭模式
  162.                                         a=4;
  163.                                
  164.                                 break;
  165.                         }
  166.                        
  167.                        
  168.                         case 4:                                //红、绿、蓝全部熄灭
  169.                         {
  170.                                 GPIO_SetBits(GPIOH, GPIO_Pin_10);
  171.                                 GPIO_SetBits(GPIOH, GPIO_Pin_11);
  172.                                 GPIO_SetBits(GPIOH, GPIO_Pin_12);
  173.                                
  174.                                 if ((Key_Scan(GPIOA, GPIO_Pin_0))==1)
  175.                                         a=-1;

  176.                                 if ((Key_Scan(GPIOC, GPIO_Pin_13))==1)
  177.                                         a=1;
  178.                                
  179.                                 break;
  180.                         }
  181.                 }
  182.         }
  183. }
  184.                

  185.        



  186. /*
  187. 简单的延时程序,传进来的数字在for循环里会一直递减,直到变0,则跳出循环。
  188. */
  189. void timeout(unsigned int count)
  190. {
  191.         for (;count!=0;count--);
  192. }


  193. /*
  194. 按键检测程序,此处定义的函数"uint8_t Key_Scan(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)"
  195. 和stm32f4xx_GPIO.h第565行的函数"uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)"
  196. 类型一样,只是命名不一样。
  197. 如果没有按下按键,就会返回0。
  198. 如果按下了按键,就会不停在while里面循环,直到松开了按键,才会继续往下跑,并返回1。
  199. 另外请注意:有返回值的函数前面不能用"Void",必须用一种数据类型定义这个函数,如int Key_Scan()。
  200. */
  201. uint8_t Key_Scan(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
  202. {                       
  203.         if(GPIO_ReadInputDataBit(GPIOx, GPIO_Pin) == 1 )  
  204.         {         
  205.                 while(GPIO_ReadInputDataBit(GPIOx, GPIO_Pin) == 1);   
  206.                 return 1;         
  207.         }
  208.         else
  209.                 return 0;
  210. }



  211. /*
  212. 七彩灯渐变程序,分为变亮程序和变暗程序。
  213. 原理:如果LED灯闪烁的频率非常高,人眼就无法辨别闪烁的过程,看到的就是常亮的灯光(参考日光灯)。
  214. 通过改变一个高频闪烁周期亮灯和灭灯的时间,就能让人眼看到不同亮度的常亮灯光。
  215. 此处用for循环不断改变一个高频闪烁周期亮灯和灭灯的时间,让人眼看到一个亮度渐变的过程。
  216. 循环中的timeout(i)是在一次闪烁中亮灯的时间,timeout(10000-(2*i))是在一次闪烁中灭灯的时间。
  217. j的值是同等亮度循环的次数,j的值越大,则同等亮度循环的次数越多,同等亮度保持的时间越长,总的亮灭过程就越长。
  218. */

  219. /*
  220. 变亮程序
  221. 在一次高频闪烁周期中,亮灯的时间(i的值)由0增加至5000,灭灯的时间(10000-(2*i)的值)由10000减至0。
  222. 在一次高频闪烁周期中亮灯时间所占的比例越来越高,所以视觉上看灯是越来越亮的。
  223. */
  224. int Bright(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
  225. {
  226.         int i,j;

  227.                 for(i=0;i<=5000;i++)
  228.                 {
  229.                         if ((Key_Scan(GPIOC, GPIO_Pin_13))==1)  //如果按下了第二个按键,则返回1(切换到白光模式,下同)
  230.                           return 1;

  231.                         for(j=0;j<=15;j++)
  232.                         {
  233.                                 GPIO_ResetBits(GPIOx, GPIO_Pin);
  234.                           timeout(i);
  235.                           GPIO_SetBits(GPIOx, GPIO_Pin);
  236.                           timeout(10000-(2*i));
  237.                         }
  238.                 }

  239.         GPIO_ResetBits(GPIOx, GPIO_Pin);
  240.                
  241. /*
  242. 边延时边检测按键的设计,解决了在亮灯保持延时期间按键不灵的问题,效果等同于timeout(120000000)+实时按键检测。
  243. */       
  244.                 for(i=1;i<=1200000;i++)
  245.                 {
  246.                         if ((Key_Scan(GPIOC, GPIO_Pin_13))==1)
  247.                     return 1;

  248.                   timeout(100);
  249.                 }
  250.                
  251.         return 0;
  252. }

  253.                
  254. /*
  255. 变暗程序
  256. 在一次高频闪烁周期中,亮灯的时间(i的值)由5000减至0,灭灯的时间(10000-(2*i)的值)由0增至10000。
  257. 在一次高频闪烁周期中亮灯时间所占的比例越来越低,所以视觉上看灯是越来越暗的。
  258.         */
  259. int Dark(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
  260. {
  261.         int i,j;
  262.         for(i=5000;i>=0;i--)
  263.                 {
  264.                         if ((Key_Scan(GPIOC, GPIO_Pin_13))==1)
  265.                     return 1;

  266.                         for(j=15;j>=0;j--)
  267.                         {
  268.                                 GPIO_ResetBits(GPIOx, GPIO_Pin);
  269.                           timeout(i);
  270.                           GPIO_SetBits(GPIOx, GPIO_Pin);
  271.                           timeout(10000-(2*i));
  272.                         }
  273.                 }

  274.         GPIO_SetBits(GPIOx, GPIO_Pin);

  275. /*
  276. 边延时边检测按键的设计,解决了在灭灯保持延时期间按键不灵的问题,效果等同于timeout(120000000)+实时按键检测。
  277. */       
  278.                 for(i=1;i<=1200000;i++)
  279.                 {
  280.                         if ((Key_Scan(GPIOC, GPIO_Pin_13))==1)
  281.                     return 1;

  282.                   timeout(100);
  283.                 }
  284.                
  285.         return 0;
  286. }
复制代码
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-1-7 09:45:31 | 显示全部楼层
这些程序的思路完全是自己想出来的,所以说,发光球实际的程序是不是这样就不得而知了,但逻辑上应该和这个差不多。代码100%纯手打,从构思到实现还是花了好些时间。调试的时候已经解决了明显的bug,但不排除还有别的,欢迎一起讨论,也希望这个程序对像我这样的初学者有所帮助。

另外,这个程序的看点并不在于实现了多高级、多复杂的功能,而在于不使用任何中断、定时器、PWM的情况下,就实现了七彩渐变灯光以及无延迟的按键切换效果。
换句话说,就算才刚入门STM32几天的初学者,也能写出稍微有点创意的程序。


当然,程序也是入门级的,比如尽量少用宏定义(几天前自己都搞不懂宏定义是什么鬼),不直接操作寄存器,尽量把所有内容都写到Main.c里面(不知诸位在刚开始写C程序的时候,是不是也像我一样,在Main.c里面从头写到尾?呵呵
)
今天更了第一个分享贴,以后如果做出了更多好玩的东西,还会继续发贴分享
回复 支持 反对

使用道具 举报

发表于 2018-1-7 09:53:06 | 显示全部楼层
咱创意和想法,我也买个发光球试试
回复 支持 反对

使用道具 举报

发表于 2018-1-7 09:54:47 | 显示全部楼层
楼主在哪里买的七彩球,能分享一下吗,谢谢
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-1-7 09:56:39 | 显示全部楼层
ljcllr 发表于 2018-1-7 09:54
楼主在哪里买的七彩球,能分享一下吗,谢谢

某宝挺多的
回复 支持 反对

使用道具 举报

发表于 2018-1-7 10:39:57 | 显示全部楼层

给个链接吧 没搜到这种,谢谢啦
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-1-7 11:09:32 | 显示全部楼层
ljcllr 发表于 2018-1-7 10:39
给个链接吧 没搜到这种,谢谢啦

买了好久,链接找不到了,直接搜七彩发光圆球、七彩球灯之类的肯定有了
回复 支持 反对

使用道具 举报

发表于 2018-1-7 21:57:12 | 显示全部楼层
看错了 以为你是自己买了一个七彩光球的半成品,然后自己开发的,后来认真看了看,原来是模拟了七彩光球,不过还是谢谢分享
回复 支持 反对

使用道具 举报

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

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-9-21 00:46 , Processed in 0.035033 second(s), 26 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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