Arduino-ESP8266之MAX7219 8位数码管级联的实现-Arduino中文社区 - Powered by Discuz!

Arduino中文社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 8344|回复: 2

Arduino-ESP8266之MAX7219 8位数码管级联的实现

[复制链接]
发表于 2018-5-22 08:44 | 显示全部楼层 |阅读模式
本帖最后由 duocool 于 2018-5-22 08:54 编辑

先上最终效果,感觉还是可以的,不过要是想完美,得像卖得挺火的那种木壳钟一样,平常像块木头,显示的时候才透出来,不过没找到合适的外壳。
4p.jpg
  最近想用arduino-esp8266网上抓点东西下来玩,先试了试OLED模块,网上0.9寸的多,怕小买了1.3寸的,倒是搞定了显示,不过感觉还是小,不够用。

     还有种办法是用电子纸模块,淘宝上也有现成的,不过2,3百的价钱感觉性价比不高。后来决定用下面这种Max7219 8段数码管模块
1637.jpg
这种模块从5块多到10多块,样子都差不多,都宣称三线驱动,支持级联,有例程。有焊的也有没焊接口的,我省事买了7块多的焊了的,后的发觉要级联还是得焊,还不如买没焊接口的,自己接线还能紧凑点。

   然后就是填级联这个坑了。最省力的应该是用LedControl这个库了,论坛里也有用这个库max7219 级联LED点阵的例子。不过不管怎么试,都是报错,好象这个库是不支持esp8266的。问卖家要到例程,arduino的例程只有单个模块的,这个样子,没用什么库,感觉就是别的单片机的c代码直接移值过来的。
[mw_shl_code=bash,true]/*******************************************************************************        
* Software Author:        HQ        
* Creation Date:        2015-2-10
* Software History:        2015-3-10
* Version:              2.0
* Sales address:       http://qifeidz.taobao.com/
********************************************************************************/
//模块引脚定义
int CLK = 2;
int CS = 1;
int DIN = 0; //这里定义了那三个脚

void setup() {
  // put your setup code here, to run once:
  pinMode(CLK,OUTPUT);
  pinMode(CS,OUTPUT);
  pinMode(DIN,OUTPUT); //让三个脚都是输出状态
}

void loop() {
  // put your main code here, to run repeatedly:
   Delay_xms(50);
   Init_MAX7219();
   Delay_xms(2000);
   Write_Max7219(0x0f, 0x00);       //显示测试:1;测试结束,正常显示:0
   Write_Max7219(1,8);
   Write_Max7219(2,7);
   Write_Max7219(3,6);
   Write_Max7219(4,5);
   Write_Max7219(5,4);
   Write_Max7219(6,3);
   Write_Max7219(7,2);
   Write_Max7219(8,1);
   while(1);
}
void Delay_xms(unsigned int x)
{
  unsigned int i,j;
  for(i=0;i<x;i++)
  for(j=0;j<112;j++);
}
//--------------------------------------------
//功能:向MAX7219(U3)写入字节
//入口参数:DATA
//出口参数:无
//说明:
void Write_Max7219_byte(unsigned char DATA)         
{
    unsigned char i;   
    digitalWrite(CS,LOW);               
    for(i=8;i>=1;i--)
    {                  
      digitalWrite(CLK,LOW);   
      if(DATA&0X80)
           digitalWrite(DIN,HIGH);
      else
           digitalWrite(DIN,LOW);
      DATA<<=1;
      digitalWrite(CLK,HIGH);
     }                                 
}
//-------------------------------------------
//功能:向MAX7219写入数据
//入口参数:address、dat
//出口参数:无
//说明:
void Write_Max7219(unsigned char address,unsigned char dat)
{
   digitalWrite(CS,LOW);
   Write_Max7219_byte(address);           //写入地址,即数码管编号
   Write_Max7219_byte(dat);               //写入数据,即数码管显示数字
   digitalWrite(CS,HIGH);                        
}

void Init_MAX7219(void)
{
   Write_Max7219(0x09, 0xff);       //译码方式:BCD码
   Write_Max7219(0x0a, 0x03);       //亮度
   Write_Max7219(0x0b, 0x07);       //扫描界限;4个数码管显示
   Write_Max7219(0x0c, 0x01);       //掉电模式:0,普通模式:1
   Write_Max7219(0x0f, 0x01);       //显示测试:1;测试结束,正常显示:0
}[/mw_shl_code]

试了下,可以用。级联怎么解决呢,网上反复找,这里有篇写的http://www.geek-workshop.com/for ... p;highlight=max7219控制led点阵的,试着小改用了用,显示还是乱的,不行。又搜到这个贴http://lib.csdn.net/article/embeddeddevelopment/63594 MAX7219多级联串行控制多个点阵/数码管的详解  用的是c语言,都不是写给arduino用的,不过我一看注释那么熟,有些部分简直和卖家给的例程一模一样,可以肯定他们都有一个共同的祖先。仔细研究后,发现级联的关键是写后面的模块就得把它前面的模块写空。像这样
[mw_shl_code=bash,true]/*第二片MAX7219的写入数据*/
void Write_Max7219_2(uchar add2,uchar dat2)
{
        Max7219_pinCS=0;
        Write_Max7219_byte(add2);
        Write_Max7219_byte(dat2);
        Max7219_pinCLK=1;
        Write_Max7219_byte(0x00);  //片1写入空
        Write_Max7219_byte(0x00);
        Max7219_pinCS=1;
}
/*第三片MAX7219的写入数据*/
void Write_Max7219_3(uchar add3,uchar dat3)
{
        Max7219_pinCS=0;
        Write_Max7219_byte(add3);
        Write_Max7219_byte(dat3);
        Max7219_pinCLK=1;
        Write_Max7219_byte(0x00); //片1写入空
        Write_Max7219_byte(0x00);
        Write_Max7219_byte(0x00); //片2写入空
        Write_Max7219_byte(0x00);
        Max7219_pinCS=1;
}[/mw_shl_code]

我的代码如下: 定义了一个总的片数,然后用循环把初始化数码管模块和写每片的数据都统一起来了,这样不管是写一片,还是8片,代码都是一样的长度(好象max7219最多就支持8片),还自定义了一个DP参数,解决了卖家例程没写的小数点有无的问题。卖家例程是在loop中初始化模块的,这样显示感觉有闪烁,我移到setup中初始化,闪烁就没了


[mw_shl_code=bash,true]//模块引脚定义
int CLK = D6;
int CS = D7;
int DIN = D8; //这里定义了那三个脚
int PIECENUM = 4;//数码管片数

void setup() {
  // put your setup code here, to run once:
  pinMode(CLK, OUTPUT);
  pinMode(CS, OUTPUT);
  pinMode(DIN, OUTPUT); //让三个脚都是输出状态
  Delay_xms(50);
  Init_MAX7219(PIECENUM);
  Delay_xms(2000);
}

void loop() {
  // put your main code here, to run repeatedly:

  Write_Max7219(1, 0x0f, 0x00, 0);     //显示测试:1;测试结束,正常显示:0

  for (int i = 1; i <= 5; i++) {
    Write_Mynum(1, i, i + 1, 1);
  }
  //Write_Mynum(1, 7, '_', 0);
// Write_Mynum(1, 8, '_', 0);
  for (int i = 1; i <= 8; i++) {
    Write_Mynum(2, i, 2, 0);
  }

  for (int i = 1; i <= 8; i++) {
    Write_Mynum(3, i, 3, 0);
  }

  for (int i = 1; i <= 8; i++) {
    Write_Mynum(4, i, 8 - i, 1);
  }

  while (1);
}


void Delay_xms(unsigned int x)
{
  unsigned int i, j;
  for (i = 0; i < x; i++)
    for (j = 0; j < 112; j++);
}

//切换地址,方便写
void Write_Mynum(int pnum,  unsigned char address, unsigned char dat , int dp) {
  Write_Max7219(pnum, 9 - address, dat, dp);
}

//--------------------------------------------
//功能:向MAX7219写入字节
//入口参数:DATA,dp显示小数点与否
void Write_Max7219_byte(unsigned char DATA, int dp)
{
  unsigned char i;
  digitalWrite(CS, LOW);
  for (i = 8; i >= 1; i--)
  {
    digitalWrite(CLK, LOW);
    if (i == 8 && dp == 1)
      digitalWrite(DIN, HIGH);
    else {
      if (DATA & 0X80)
        digitalWrite(DIN, HIGH);
      else
        digitalWrite(DIN, LOW);
    }
    DATA <<= 1;
    digitalWrite(CLK, HIGH);
  }
}

//-------------------------------------------
//功能:向MAX7219写入数据
//入口参数:pnum数码管片序号,address,dat,dp显示小数点与否
void Write_Max7219(int pnum, unsigned char address, unsigned char dat, int dp)
{
  digitalWrite(CS, LOW);
  Write_Max7219_byte(address, 0);          //写入地址,即数码管编号
  Write_Max7219_byte(dat, dp);              //写入数据,即数码管显示数字
  if (pnum > 1) {
    digitalWrite(CLK, HIGH);
    for (int i = 1; i < pnum; i++) {
      Write_Max7219_byte(0X00, 0);
      Write_Max7219_byte(0X00, 0);
    }
  }
  digitalWrite(CS, HIGH);
}


//Max7219初始化
void Init_MAX7219(int pienum)
{
  for (int i = 1 ; i <= pienum ; i++) {
    Write_Max7219(i, 0x09, 0xff, 0);     //译码方式:BCD码
    Write_Max7219(i, 0x0a, 0x03, 0);     //参数3:亮度
    Write_Max7219(i, 0x0b, 0x07, 0);     //扫描界限;参数3:8个数码管显示
    Write_Max7219(i, 0x0c, 0x01, 0);     //掉电模式:参数3:0,普通模式:1
    Write_Max7219(i, 0x0f, 0x01, 0);     //显示测试:参数3:1;测试结束,正常显示:0
  }
}
[/mw_shl_code]

发表于 2020-7-15 14:26 | 显示全部楼层
您好,我按照您的代码连接了8个8字数码管,但是只有4个数码管显示,且只显示了全部灯都亮,能麻烦您在详细介绍一下这个代码么,十分感谢!
发表于 2020-7-16 11:44 | 显示全部楼层
楼主,你图中的数码管模块只有时钟的点,没有小数点呀。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|Archiver|手机版|Arduino中文社区

GMT+8, 2024-11-28 08:41 , Processed in 0.096319 second(s), 18 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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