买了一个四位数码管,它长这样,有4个针脚,内部驱动芯片为TM1637,还有一种内部驱动芯片为74HC595,有5个针脚,千万要注意,不然就要996了,不过如果你买成了74HC585,可以参考阿迪王的这篇文章

    说回TM1637,这个模块是一个12脚的带时钟点的4位共阳数码管,只需要2跟线号线即可使单片机控制4位8段数码管,并且亮度8级可调。

接线

 

    接线如上图,VCC接5V,GND接GND,CLK接GPIO19,DIO接GPIO26。显示是通过时钟CLK和DIO共同控制。

    新建TLEDTM1637Driver类,用来封装显示模块,代码如下:

public class LEDTM1637Driver : IDisposable
{
    private byte[] Characters = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71 };//0~9,A,b,C,d,E,F 
    private int dataPin { get; set; }     // Serial Digital Input
    private int clockPin { get; set; }   // Serial Clock
    private GpioController gpio;

    public LEDTM1637Driver(int dio, int clock)
    {
        dataPin = dio;
        clockPin = clock;
        gpio = new GpioController(PinNumberingScheme.Logical);
        gpio.OpenPin(dataPin, PinMode.Output);
        gpio.OpenPin(clockPin, PinMode.Output);
        gpio.Write(dataPin, PinValue.Low);
        gpio.Write(clockPin, PinValue.Low);
    }
    public void Dispose()
    {
        gpio?.Dispose();
        gpio = null;
    }

    private void WriteByte(byte input)
    {
        for (int i = 0; i < 8; i++)//每次写入一个byte,一共8bit
        {
            gpio.Write(clockPin, PinValue.Low);//确保无误输入前再拉低一次时钟 ,代表开始写入数据
            if ((input & 0x01) == 1)
            {
                gpio.Write(dataPin, PinValue.High);
            }
            else
            {
                gpio.Write(dataPin, PinValue.Low);
            }
            input >>= 1;//每写入完毕一次,移动一位
            gpio.Write(clockPin, PinValue.High);//每次输入完一位,就拉高一次时钟
        }
        //应答信号ACK,这里本来是用来判断DIO脚是否被自动拉低,代表上面写入的数据TM1637已经接受到了,
        //但是我们这里闲麻烦,直接将CLK信号低高低的拉,让芯片直接执行下一步操作
        gpio.Write(clockPin, PinValue.Low);//先拉低
        gpio.Write(clockPin, PinValue.High);//需要判断D是否为低电平此期间C一直拉高
        gpio.Write(clockPin, PinValue.Low);//应答完毕以后拉低C
    }

    private void Write(byte input)
    {
        StartDiaplay();
        WriteByte(input);
        StopDiaplay();
    }

    public void Show(char[] msg)
    {
        Write(0x40);//指定功能参数为自动增加
        StartDiaplay();
        WriteByte(0xC0);//设置首地址,指向第一个字符
        for (int i = 0; i < 4; i++)
        {
            if (i != 1)
            {
                WriteByte(Characters[msg[i] - 48]);//从Characters数组根据索引获得字符显示的编码
            }
            else
            {
                WriteByte((byte)(Characters[msg[1] - 48] + 0x80));//第二个字符带有冒号,因此将第一位空置拉高
            }
        }
        StopDiaplay();//开始写入亮度
        Write(0x8f);
    }

    public void ShowV2(char[] msg)
    {
        //设置基本参数
        Write(0x44);//指定功能参数为固定地址显示

        //设置显示地址以及显示内容
        StartDiaplay();
        WriteByte(0xC0);//第一个字符
        WriteByte(Characters[msg[0] - 48]);
        StopDiaplay();

        StartDiaplay();
        WriteByte(0xC1);//第二个字符
        WriteByte((byte)(Characters[msg[1] - 48] + 0x80));//第二个字符带有冒号,因此将第一位空置拉高
        StopDiaplay();

        StartDiaplay();
        WriteByte(0xC2);//第三个字符
        WriteByte(Characters[msg[2] - 48]);
        StopDiaplay();

        StartDiaplay();
        WriteByte(0xC3);//第四个字符
        WriteByte(Characters[msg[3] - 48]);
        StopDiaplay();

        //开始写入亮度
        Write(0x8f);
    }

    private void StartDiaplay()
    {
        gpio.Write(clockPin, PinValue.High);//CLK拉为高电平
        gpio.Write(dataPin, PinValue.High);//DIO拉为高电平

        gpio.Write(dataPin, PinValue.Low); //和上面那句指令一起就是DIO由高变低
        gpio.Write(clockPin, PinValue.Low);//然后CLK上的时钟信号拉低,DIO接口的数据允许改变,代表开始写入数据
    }

    private void StopDiaplay()
    {
        //结束条件是CLK为高时,DIO由低电平变为高电平
        gpio.Write(clockPin, PinValue.Low);//先拉低CLK,代表允许DIO改变数据
        gpio.Write(dataPin, PinValue.Low);//拉低DIO

        gpio.Write(clockPin, PinValue.High);//CLK拉高,满足结束条件前半部分
        gpio.Write(dataPin, PinValue.High);//DIO由低变高,代表数据输入结束

    }
}

   该模块的现实,可以参考TM1637的文档,不想看文档可以参考 在树莓派Zero上使用C#+Mono驱动TM1637四位数码管  这篇文章,我在这篇文章代码的基础上进行了一点修改。

   要显示内容,调用代码如下:

static void Main(string[] args)
{
    Console.WriteLine("Hello World TM1637 4 Digit LED!");
    string s = args.Length > 0 ? args[0] : "";
    if (!string.IsNullOrEmpty(s))
    {
        Console.WriteLine("args:" + s);
    }
    using (LEDTM1637Driver ledtm1673Driver = new LEDTM1637Driver(26, 19))
    {
        while (true)
        {
            char[] date = s == "" ? DateTime.Now.ToString("hhmm").ToCharArray() : s.ToCharArray();//获得当前日期,并表示为小时分钟
            ledtm1673Driver.Show(date);
        }
    }
}

     可以接受4为数字输入显示,如果没有输入,就是个时钟,显示时分。显示效果如下:

▲996😂

▲ 1024 😁

 

参考


  1. https://www.cnblogs.com/ACDIV/p/11625977.html
  2. https://edi.wang/post/2016/4/29/windows-10-iot-74hc595-led-digital-tube