极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 2188|回复: 10

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

[复制链接]
发表于 2018-5-18 16:26:58 | 显示全部楼层 |阅读模式
    先上最终效果,感觉还是可以的,不过要是想完美,得像卖得挺火的那种木壳钟一样,平常像块木头,显示的时候才透出来,不过没找到合适的外壳。 4p.jpg
    最近想用arduino-esp8266网上抓点东西下来玩,先试了试OLED模块,网上0.9寸的多,怕小买了1.3寸的,倒是搞定了显示,不过感觉还是小,不够用。

     还有种办法是用电子纸模块,淘宝上也有现成的,不过2,3百的价钱感觉性价比不高。后来决定用下面这种Max7219 8段数码管模块
max7219.jpg

这种模块从5块多到10多块,样子都差不多,都宣称三线驱动,支持级联,有例程。有焊的也有没焊接口的,我省事买了7块多的焊了的,后的发觉要级联还是得焊,还不如买没焊接口的,自己接线还能紧凑点。

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

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

  18. void loop() {
  19.   // put your main code here, to run repeatedly:
  20.    Delay_xms(50);
  21.    Init_MAX7219();
  22.    Delay_xms(2000);
  23.    Write_Max7219(0x0f, 0x00);       //显示测试:1;测试结束,正常显示:0
  24.    Write_Max7219(1,8);
  25.    Write_Max7219(2,7);
  26.    Write_Max7219(3,6);
  27.    Write_Max7219(4,5);
  28.    Write_Max7219(5,4);
  29.    Write_Max7219(6,3);
  30.    Write_Max7219(7,2);
  31.    Write_Max7219(8,1);
  32.    while(1);
  33. }
  34. void Delay_xms(unsigned int x)
  35. {
  36.   unsigned int i,j;
  37.   for(i=0;i<x;i++)
  38.   for(j=0;j<112;j++);
  39. }
  40. //--------------------------------------------
  41. //功能:向MAX7219(U3)写入字节
  42. //入口参数:DATA
  43. //出口参数:无
  44. //说明:
  45. void Write_Max7219_byte(unsigned char DATA)         
  46. {
  47.     unsigned char i;   
  48.     digitalWrite(CS,LOW);               
  49.     for(i=8;i>=1;i--)
  50.     {                  
  51.       digitalWrite(CLK,LOW);   
  52.       if(DATA&0X80)
  53.            digitalWrite(DIN,HIGH);
  54.       else
  55.            digitalWrite(DIN,LOW);
  56.       DATA<<=1;
  57.       digitalWrite(CLK,HIGH);
  58.      }                                 
  59. }
  60. //-------------------------------------------
  61. //功能:向MAX7219写入数据
  62. //入口参数:address、dat
  63. //出口参数:无
  64. //说明:
  65. void Write_Max7219(unsigned char address,unsigned char dat)
  66. {
  67.    digitalWrite(CS,LOW);
  68.    Write_Max7219_byte(address);           //写入地址,即数码管编号
  69.    Write_Max7219_byte(dat);               //写入数据,即数码管显示数字
  70.    digitalWrite(CS,HIGH);                        
  71. }

  72. void Init_MAX7219(void)
  73. {
  74.    Write_Max7219(0x09, 0xff);       //译码方式:BCD码
  75.    Write_Max7219(0x0a, 0x03);       //亮度
  76.    Write_Max7219(0x0b, 0x07);       //扫描界限;4个数码管显示
  77.    Write_Max7219(0x0c, 0x01);       //掉电模式:0,普通模式:1
  78.    Write_Max7219(0x0f, 0x01);       //显示测试:1;测试结束,正常显示:0
  79. }
复制代码


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



我的代码如下: 定义了一个总的片数,然后用循环把初始化数码管模块和写每片的数据都统一起来了,这样不管是写一片,还是8片,代码都是一样的长度(好象max7219最多就支持8片),还自定义了一个DP参数,解决了卖家例程没写的小数点有无的问题。卖家例程是在loop中初始化模块的,这样显示感觉有闪烁,我移到setup中初始化,闪烁就没了
  1. //模块引脚定义
  2. int CLK = D6;
  3. int CS = D7;
  4. int DIN = D8; //这里定义了那三个脚
  5. int PIECENUM = 4;//数码管片数

  6. void setup() {
  7.   // put your setup code here, to run once:
  8.   pinMode(CLK, OUTPUT);
  9.   pinMode(CS, OUTPUT);
  10.   pinMode(DIN, OUTPUT); //让三个脚都是输出状态
  11.   Delay_xms(50);
  12.   Init_MAX7219(PIECENUM);
  13.   Delay_xms(2000);
  14. }

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

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

  18.   for (int i = 1; i <= 5; i++) {
  19.     Write_Mynum(1, i, i + 1, 1);
  20.   }
  21.   //Write_Mynum(1, 7, '_', 0);
  22. // Write_Mynum(1, 8, '_', 0);
  23.   for (int i = 1; i <= 8; i++) {
  24.     Write_Mynum(2, i, 2, 0);
  25.   }

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

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

  32.   while (1);
  33. }


  34. void Delay_xms(unsigned int x)
  35. {
  36.   unsigned int i, j;
  37.   for (i = 0; i < x; i++)
  38.     for (j = 0; j < 112; j++);
  39. }

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

  44. //--------------------------------------------
  45. //功能:向MAX7219写入字节
  46. //入口参数:DATA,dp显示小数点与否
  47. void Write_Max7219_byte(unsigned char DATA, int dp)
  48. {
  49.   unsigned char i;
  50.   digitalWrite(CS, LOW);
  51.   for (i = 8; i >= 1; i--)
  52.   {
  53.     digitalWrite(CLK, LOW);
  54.     if (i == 8 && dp == 1)
  55.       digitalWrite(DIN, HIGH);
  56.     else {
  57.       if (DATA & 0X80)
  58.         digitalWrite(DIN, HIGH);
  59.       else
  60.         digitalWrite(DIN, LOW);
  61.     }
  62.     DATA <<= 1;
  63.     digitalWrite(CLK, HIGH);
  64.   }
  65. }

  66. //-------------------------------------------
  67. //功能:向MAX7219写入数据
  68. //入口参数:pnum数码管片序号,address,dat,dp显示小数点与否
  69. void Write_Max7219(int pnum, unsigned char address, unsigned char dat, int dp)
  70. {
  71.   digitalWrite(CS, LOW);
  72.   Write_Max7219_byte(address, 0);          //写入地址,即数码管编号
  73.   Write_Max7219_byte(dat, dp);              //写入数据,即数码管显示数字
  74.   if (pnum > 1) {
  75.     digitalWrite(CLK, HIGH);
  76.     for (int i = 1; i < pnum; i++) {
  77.       Write_Max7219_byte(0X00, 0);
  78.       Write_Max7219_byte(0X00, 0);
  79.     }
  80.   }
  81.   digitalWrite(CS, HIGH);
  82. }


  83. //Max7219初始化
  84. void Init_MAX7219(int pienum)
  85. {
  86.   for (int i = 1 ; i <= pienum ; i++) {
  87.     Write_Max7219(i, 0x09, 0xff, 0);     //译码方式:BCD码
  88.     Write_Max7219(i, 0x0a, 0x03, 0);     //参数3:亮度
  89.     Write_Max7219(i, 0x0b, 0x07, 0);     //扫描界限;参数3:8个数码管显示
  90.     Write_Max7219(i, 0x0c, 0x01, 0);     //掉电模式:参数3:0,普通模式:1
  91.     Write_Max7219(i, 0x0f, 0x01, 0);     //显示测试:参数3:1;测试结束,正常显示:0
  92.   }
  93. }
复制代码


回复

使用道具 举报

发表于 2018-5-27 22:49:35 | 显示全部楼层
很好,每一怕贴代码的帖子都是好帖子。谢谢,大神,受用。
回复 支持 反对

使用道具 举报

发表于 2018-5-28 20:46:03 | 显示全部楼层
不错。
支持楼主。
学习一下。
回复 支持 反对

使用道具 举报

发表于 2018-6-3 09:58:28 来自手机 | 显示全部楼层
大神,小白问下,这个代码,可以写中横线吗?我想写温度,需要写负号,提示零下,怎么写,多谢了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-6-4 08:21:40 | 显示全部楼层
anqiw 发表于 2018-6-3 09:58
大神,小白问下,这个代码,可以写中横线吗?我想写温度,需要写负号,提示零下,怎么写,多谢了

中横就用":" 英文的冒号,
回复 支持 反对

使用道具 举报

发表于 2018-6-4 10:39:28 | 显示全部楼层
多谢了,我试了下,10也可以输出中横。11-15 还可以输出 E L H P 空白,请问还有更多的输出吗,比如F怎么弄。总共能输出多少种,怎么对应的,谢谢了。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-6-4 11:17:13 | 显示全部楼层
anqiw 发表于 2018-6-4 10:39
多谢了,我试了下,10也可以输出中横。11-15 还可以输出 E L H P 空白,请问还有更多的输出吗,比如F怎么弄 ...

空白我用的是"_",数字,小数点,还有空白,中横一般也就用这么多了,
回复 支持 反对

使用道具 举报

发表于 2018-7-12 14:50:39 | 显示全部楼层
写得很好,但有点疑问楼主有空解答一下吗?
我也在调595数码管,不知道小数点怎么点亮,请楼主指点一下、
具体在哪段代码呢,小数点的地址是什么呢
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-7-13 10:05:30 | 显示全部楼层
发烧的小学生 发表于 2018-7-12 14:50
写得很好,但有点疑问楼主有空解答一下吗?
我也在调595数码管,不知道小数点怎么点亮,请楼主指点一下、
...

void Write_Max7219_byte(unsigned char DATA, int dp)  最后一个dp参数就是显示小数点的开关,程序注释里已经说清楚了的
回复 支持 反对

使用道具 举报

发表于 2018-7-13 15:18:21 | 显示全部楼层
duocool 发表于 2018-7-13 10:05
void Write_Max7219_byte(unsigned char DATA, int dp)  最后一个dp参数就是显示小数点的开关,程序注释 ...

可以详细说一下点亮小数点的思路吗,代码看得很吃力,万分感谢
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-7-16 15:28:02 | 显示全部楼层
发烧的小学生 发表于 2018-7-13 15:18
可以详细说一下点亮小数点的思路吗,代码看得很吃力,万分感谢

其实就这句 if (i == 8 && dp == 1)
      digitalWrite(DIN, HIGH);     第8位且带小数点,就写高电平,第8位就是小数点
回复 支持 反对

使用道具 举报

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

本版积分规则

Archiver|联系我们|极客工坊 ( 浙ICP备09023225号 )

GMT+8, 2018-12-13 22:11 , Processed in 0.081414 second(s), 27 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

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