zoukankan      html  css  js  c++  java
  • MF干活——C#数码管与跑马灯之舞(视频)

        通过C#点灯神话》,我们了解到单片机最基础的输入输出功能,也就是所谓的GPIO
        这一次,我们来点更多的“灯”——数码管,并且还是四位数码管
        先上结果,看视频:

        这个视频混合了四位数码管、液晶屏和跑马灯,比上一次的小灯闪烁要效果好点。

    数码管原理简述
        现 在的数码管也叫七段数码管,一个完整的数字8就刚好用到七段小灯,加上小数点就是8个小灯。嗯,每一段就是一个小灯,那么操作方式跟点灯神话里面是一样 的,只不过多了很多而已。四位数字,每个数字用8个小灯,那么一共就有32个,加上接地或者高电平,至少得33脚,接线那可是一个非常复杂的工程。
        但是,我们的四位数码管,只有12脚,其中8个负责每一个数字的同一段小灯,剩下四个选择给哪个数字供电。这就涉及一个非常悲催的事情:当你控制点亮个位,准备控制输出十位的时候,个位会熄灭,因为选择脚选择了十位;如果你同时选择个位,那么只会落得个位跟十位一样数字,因为它们不同数字的同一段共用同一个针脚
        怎么办??呵呵,有些人就以为数码管设计上有问题,应该有类似液晶屏一样的锁存的东西,每显示一位后就锁定。
        其 实,这些数码管设计没有问题,相反,还非常精妙!上面说了,如果采用传统的GPIO做法,那么四位数码管就得需要33脚,那是非常非常浪费针脚资源的。仿 照计算机串口硬盘的原理,我们也可以采用串口的方式来控制多位数码管。那么,N位数码管,其实只需要N+8个针脚就已经足够了。
        那个“锁存”问题怎么解决呢?其实不用解决,我们完全可以利用人眼的视觉误差,要知道,动画的基本原理也是这样子。在显示个位后,维持一小段时间,然后显示十位,然后百位千位,依次逐位显示,只要整个过程很快,我们人眼就会以为它们是一起亮起来的!

    接线
        先看看全局,这里接好了液晶屏、数码管(液晶屏上面那个)、10个小灯。别的东西都是摆设,东西太多太乱不好意思!杜邦线不够的同学可以分开实验。

    10个各种颜色的小灯,接在面包板上,准备做跑马灯。下方的线是接地GND。
    下右图是板子左针脚原理图,我们依箭头从PG0到PG1选10个,另外接左下角的GND即可。
    这里故意犯一个错误,用了那个PB2针脚,其实探索者一号上PB2是接蜂鸣器的,现在共用了,如果驱动能力足够,除了小灯亮以为,大家在视屏里面应该还能听到嘟嘟嘟的背景声。

    四 位数码管12脚的接法。这里有个地方不得不说,大家也许发现板子上很多针脚插有绿色跳线帽。其实那是我做的一个标记,标明这个脚已经别别的设备使用,避免 冲突。细心的同学可以发现,探索者一号板子的数码管例程,在没有接上液晶屏的时候是正常工作的,接上液晶屏后,就不动了,液晶屏也不正常了。这就是针脚冲 突,刚好那一片好多脚被液晶屏用了的。
    所以,这里另外取12个接数码管,从PC0依箭头的顺序到PC1。
    数码管方面,正面面向你,有小数点一边在下方,那么,背后左下角是针脚1,逆时针输下去,一直到左上角的12。按照这个顺序接好数码管和板子排针。


    源代码
    数码管源码
    。原理上很简单,开个线程不断的刷要显示的数字,不能停下来。哦,没错,单片机也可以用.Net里面的线程!

    数码管源代码
    using System;
    using System.Threading;
    using Microsoft.SPOT.Hardware;
    
    namespace MFTest
    {
        /// <summary>四位数码管</summary>
        class Led4
        {
            /// <summary>每个数字的段数,一个字节只用七位,表示数码管七段顺时针</summary>
            static readonly Byte[] LedDigitals = new Byte[] { 0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71 };
    
            /// <summary>数码管公共脚</summary>
            public Int32[] PublicPins = new Int32[] { 6, 8, 9, 12 };
            /// <summary>数码管七段脚</summary>
            public Int32[] SevenPins = new Int32[] { 11, 7, 4, 2, 1, 10, 5, 3 };
    
            /// <summary>实际控制板针脚</summary>
            public Cpu.Pin[] LedPins;
            OutputPort[] ports;
    
            private Int32 _Value;
            /// <summary>要显示的数字</summary>
            public Int32 Value { get { return _Value; } set { _Value = value; } }
    
            private Boolean _IsHex;
            /// <summary>进制。只支持十进制和十六进制</summary>
            public Boolean IsHex { get { return _IsHex; } set { _IsHex = value; } }
    
            Thread th;
            public void Start()
            {
                if (LedPins == null || LedPins.Length < 1) throw new Exception("No Pins For Led4!");
    
                ports = new OutputPort[LedPins.Length];
                for (int i = 0; i < LedPins.Length; i++)
                {
                    // i==2就是脚3,是DP
                    ports[i] = new OutputPort(LedPins[i], i == 2 || Array.IndexOf(PublicPins, i + 1) >= 0);
                }
                for (int i = 0; i < LedPins.Length; i++)
                {
                    ports[i].Write(false);
                }
    
                th = new Thread(dis);
                th.Start();
            }
    
            public void Stop()
            {
                if (th == null) return;
    
                th.Abort();
                th = null;
            }
    
            void dis()
            {
                if (IsHex)
                    while (true) ShowNumber16(Value);
                else
                    while (true) ShowNumber(Value);
            }
    
            void ShowNumber(Int32 n)
            {
                for (int i = 0; i < 4; i++)
                {
                    // 如果现在要显示的是0,并且不是第一个数字,那么应该关闭显示
                    if (n == 0 && i > 0)
                    {
                        ShowDigital(i, 0, false);
                    }
                    else
                    {
                        // 这一次应该显示的数字
                        ShowDigital(i, n % 10, true);
    
                        n = n / 10;
                    }
                }
            }
    
            void ShowNumber16(Int32 n)
            {
                for (int i = 0; i < 4; i++)
                {
                    // 如果现在要显示的是0,并且不是第一个数字,那么应该关闭显示
                    if (n == 0 && i > 0)
                    {
                        ShowDigital(i, 0, false);
                    }
                    else
                    {
                        // 这一次应该显示的数字
                        ShowDigital(i, n & 0xF, true);
    
                        n = n >> 4;
                    }
                }
            }
    
            void ShowDigital(Int32 index, Int32 n, Boolean show)
            {
                // 找到控制脚
                var pin = ports[PublicPins[index] - 1];
                // 如果不显示,关闭后直接返回
                if (!show)
                {
                    pin.Write(false);
                    return;
                }
    
                // 输出数字的七段表示
                var d = LedDigitals[n];
                for (int i = 0; i < 7; i++)
                {
                    var p = ports[SevenPins[i] - 1];
                    p.Write((d >> i & 0x1) == 0);
                }
                // 关闭小数点
                ports[SevenPins[7] - 1].Write(true);
    
                // 先输出数字,再打开开关
                pin.Write(true);
                // 然后停留一会,形成一个视觉效果
                Thread.Sleep(5);
                // 最后关闭,为下一个显示做准备
                pin.Write(false);
            }
        }
    }

    控制源码。

    控制代码
    // 探索者一号
    // 跑马灯针脚
    var pins = new Cpu.Pin[] {
        Pins.PG1, Pins.PF15, Pins.PF13, Pins.PF11, Pins.PB1,
        Pins.PC5, Pins.PG0, Pins.PF14, Pins.PF12, Pins.PB2 };
    var leds = new OutputPort[pins.Length];
    for (int i = 0; i < pins.Length; i++)
    {
        leds[i] = new OutputPort(pins[i], i % 2 == 0);
    }
    var led4 = new Led4();
    // 数码管针脚
    led4.LedPins = new Cpu.Pin[] {
        Pins.PC0, Pins.PF9, Pins.PF7, Pins.PF5, Pins.PF3, Pins.PF1,
        Pins.PF2, Pins.PF4, Pins.PF6, Pins.PF8, Pins.PF10, Pins.PC1 };
    led4.IsHex = true; // 按十六进制显示
    led4.Start();
    var k = 0;
    for (int i = 0; i < 20000; i++)
    {
        for (int j = 0; j < leds.Length; j++)
        {
            leds[j].Write(k == j);
        }
        if (k++ >= leds.Length) k = 0;
        led4.Value = i;
    
        Thread.Sleep(50);
    }
    led4.Stop();

     

    万事俱备!把程序写入探索者一号板子,重启后,数码管在数数,10个小灯从左到右依次亮过去。
    使用其它板子的同学,自己选好针脚,稍微修改控制代码即可!针脚不够可分开实验!

     

    欢迎感兴趣的同学一起学习研究!页头有群号和论坛资料地址。

     

    如果您认为本文对你有用,麻烦给个推荐,谢谢!o(∩_∩)o

    如果您觉得本文很烂,有误导他人的嫌疑,还请一定给个反对,给出您尊贵的意见,我们一定改进!谢谢!

    我不相信神话,我只相信汗水!我不相信命运,我只相信双手!
  • 相关阅读:
    jquery新知识
    jquery回顾
    Filter和Listener
    jsp,jstl,el
    cookie和session
    servlet和HTTP原理
    xml基本知识
    linux 相关操作
    linux mysql 相关操作、问题
    linux 文件结构
  • 原文地址:https://www.cnblogs.com/nnhy/p/Led4.html
Copyright © 2011-2022 走看看