|
本帖最后由 chinayanhui 于 2020-2-23 00:07 编辑
学习单片机的小学生第一次发帖,不足之处还请高人指正。
这期间,实再无聊,在网上看一些电子制作的视频。看了一个群主自己做了一个心形流水灯,效果实再不错,但是看到他写的代码,就是觉得太乱。不成系统,一大堆的数组组织起来的代码,没有注释,看的让人着实不爽。
频中的代码片段:
是不是看得有点晕?
正好家里还有几块洞洞板和LED灯,用了两天时间,加上代码总算是搞定了。旨当给孩子的玩具了,孩子也比较喜欢。
先看一个效果视频:
视频.7z
(5.26 MB, 下载次数: 5)
相关图片:
由于手头只有7*9的板子,用了26个LED,光拼这个心形就用了近一个半小时的时间。看似简单,拼起来要考虑线的走向等等问题。
手头还有几只STC98C52RC,占用了P1, P2, P3和ALE(4.5)以及4.6管脚。为啥不用P0脚?因为想起了要接上拉电阻,手头又没有,所以干脆没有用。虽然我的LED是共阳接法。。。其实是为了以后扩展用的
因为是用3节1.5V的电池带动,为了能亮一些,所以限流电阻接了100欧的。
流水灯嘛就是一堆IO口的输出,没啥复杂的,是51单片机初学者的Hello World,复杂之处在于设计led流水灯的算法。笔者因为是从软件转过来的,虽然在PC端有一大堆的内存可以使用,但是学习单片机,面对只有几百之字的内存和几K的存储空间。但是从算法上节约程序空间是笔者的习惯。另外程序看得也明白。主要是不想用一大堆数组,一堆看的头疼的循环加套循环,只想设计几个函数,解决问题。最终编译出来,程序代码686字节,占用内存23.0,我自己还能接受。
还有一些效果有些思路,但是真是没有时间写了,有兴趣的坛友可以在我的思路上完善。因为LED较多,代码中没有使用循环左右移的代码。觉得用unsign long左右移动就足够了。当然程序中也注释了一段笔者参考网上的uint32的循环左右移的代码,供有兴趣的坛友参考。
另外由于不需要精确定时也为了写程序方便,没有使用定时器,仅用了一个软件延时。有兴趣的坛友可以使用定时器试一下哈。
单片机代码如下:- #include "STC89C5xRC.H"
- #define int8 char
- #define uint8 unsigned char
- #define uint16 unsigned short
- #define uint32 unsigned long
-
- #define FUNJMP 79 // 函数跳转延时
- #define TIME 100 // 语句间延时
- /**********************************
- 函数功能:软件延时
- 入口参数:
- count uint16 软件延时的毫秒数
- 返 回:无
- 备 注:无
- **********************************/
- void Delay(uint16 count)
- {
- uint16 i;
- uint8 j;
- for(i = count; i > 0; i--)
- for(j = 110; j > 0; j--);
- }
- /**********************************
- 函数功能:全亮闪烁
- 入口参数:
- count uint8 闪烁次数
- ms uint16 闪烁时停留的毫秒数
- 返 回:无
- 备 注:无
- **********************************/
- void Flash(uint8 count, uint16 ms)
- {
- uint8 i;
-
- for(i = 0; i < count * 2; i++)
- {
- P1 = ~P1;
- P2 = ~P2;
- P3 = ~P3;
- P4 = ~P4;
-
- Delay(ms);
- }
- }
- /**********************************
- 函数功能:
- 循环移动无符号数
- 入口参数:
- uint32 val 待移动的数
- uint8 count 移动的位数
- 返 回:移动的结果
- 备 注:
- count < 0,左移
- count > 0, 右移
- **********************************/
- //uint32 CycleShift(uint32 val, int8 count)
- //{
- // uint32 temp = 0;
- //
- // if(count == 0)
- // return val;
- //
- // temp |= val;
- //
- // if(count < 0)
- // {
- // val <<= -count;
- // temp >>= (32 + count);
- // }
- // else
- // {
- // val >>= count;
- // temp <<= (32 - count);
- // }
- //
- // return val | temp;
- //}
- /**********************************
- 函数功能:根据参数设定LED的亮灯
- 入口参数:
- value uint32 设定led亮灯的数据
-
- 返 回:无
- 备 注:无
- **********************************/
- void LED(uint32 value)
- {
- P1 = value & 0xFF;
- P3 = (value & 0xFF00) >> 8;
- P2 = (value & 0xFF0000) >> 16;
- P44 = (value & 0x1000000) >> 24;
- P45 = (value & 0x2000000) >> 25;
- }
- /**********************************
- 函数功能:流水灯
- 入口参数:
- value uint8 流水灯初值(0.逆时针 1.顺时针)
- isOff uint8 是否关闭流过的灯(1.关闭 0.不关闭)
-
- 返 回:无
- 备 注:无
- **********************************/
- void Assembly(uint32 value, uint8 style)
- {
- uint8 i;
- for(i = 0; i < 26; i++)
- {
- LED(value);
-
- // 第7位为1,则为顺时针,否则为逆时针
- if((style & 0x80) == 0x80)
- value <<= 1;
- else
- value >>= 1;
-
- // 第0位为1则为单个流水灯(为0则是亮过的不再熄灭)
- if((style & 1) == 1)
- value++;
-
- // 第1位为1则为顺时针逐个灭灯
- if((style & 2) == 2)
- value |= 1;
-
- // 第5位为1则为逆时针单个灯
- if((style & 0x10) == 0x10)
- value |= 0x2000000;
-
- Delay(TIME);
- }
- }
- /**********************************
- 函数功能:双向流水灯
- 入口参数:
- dir uint8 0.双向点亮(从上到下) 1.双向熄灭(从上到下)
- 返 回:无
- 备 注:无
- **********************************/
- void Assembly2(uint8 dir)
- {
- uint8 i;
- uint16 clockwise;
- uint16 anticlockwise;
-
- Delay(TIME);
-
- clockwise = 0x1FFE;
- anticlockwise = 0x1FFF;
- for(i = 0; i < 14; i++)
- {
- uint32 temp = anticlockwise;
- temp = temp << 13;
- temp = temp | (clockwise & 0x1FFE);
-
- if(dir)
- temp = ~temp;
-
- LED(temp);
-
- clockwise = clockwise << 1;
- anticlockwise = anticlockwise >> 1;
- Delay(TIME);
- }
- }
- void main()
- {
- while(1)
- {
-
- //Delay(FUNJMP);
-
-
-
- // 全灭的状态下顺时针逐个流水亮灯
- Assembly(0xFFFFFFFE, 0x81);
-
- // 全灭的状态下顺时针堆积亮灯
- Delay(FUNJMP);
- Assembly(0xFFFFFFFE, 0x80);
-
- // 全亮状态下顺时针逐个堆积灭灯
- //P1 = 0xFF;
- Delay(FUNJMP);
- Assembly(1, 0x82);
-
- // 全灭状态下逆时针逐个流水亮灯
- Delay(FUNJMP);
- Assembly(0x1FFFFFF, 0x10);
-
- // 逆时针逐个堆积亮灯
- Delay(FUNJMP);
- Assembly(0x1FFFFFF, 0x00);
-
- // 全亮的状态下逆时针堆积灭灯
- Delay(FUNJMP);
- Assembly(0x2000000, 0x10);
-
- // 两边点亮
- Delay(FUNJMP);
- Assembly2(0);
-
- // 两边收缩
- Delay(FUNJMP);
- Assembly2(1);
-
- // 闪烁
- Delay(FUNJMP);
- Flash(3, FUNJMP - 10);
-
- Delay(3000);
- }
- }
复制代码
洞洞板的设计比较简单,为了美观,用了两块洞洞板,一个板子上是共阳的26根LED,另一块板子放单片机,晶振,然后是一堆插针。
洞洞板的设计:
|
评分
-
查看全部评分
|