| Arduino-ESP8266之MAX7219 8位数码管级联的实现 [复制链接] |
| duocool | 电梯直达1# 发表于 2018-5-18 16:26:58 | 只看该作者 先上最终效果,感觉还是可以的,不过要是想完美,得像卖得挺火的那种木壳钟一样,平常像块木头,显示的时候才透出来,不过没找到合适的外壳。最近想用arduino-esp8266网上抓点东西下来玩,先试了试OLED模块,网上0.9寸的多,怕小买了1.3寸的,倒是搞定了显示,不过感觉还是小,不够用。 还有种办法是用电子纸模块,淘宝上也有现成的,不过2,3百的价钱感觉性价比不高。后来决定用下面这种Max7219 8段数码管模块 这种模块从5块多到10多块,样子都差不多,都宣称三线驱动,支持级联,有例程。有焊的也有没焊接口的,我省事买了7块多的焊了的,后的发觉要级联还是得焊,还不如买没焊接口的,自己接线还能紧凑点。 然后就是填级联这个坑了。最省力的应该是用LedControl这个库了,论坛里也有用这个库max7219 级联LED点阵的例子。不过不管怎么试,都是报错,好象这个库是不支持esp8266的。问卖家要到例程,arduino的例程只有单个模块的,这个样子,没用什么库,感觉就是别的单片机的c代码直接移值过来的。 /******************************************************************************* * 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 }复制代码 试了下,可以用。级联怎么解决呢,网上反复找,本坛里有篇写的http://www.geek-workshop.com/for … p;highlight=max7219控制led点阵的,试着小改用了用,显示还是乱的,不行。又搜到这个贴http://lib.csdn.net/article/embeddeddevelopment/63594 MAX7219多级联串行控制多个点阵/数码管的详解 用的是c语言,都不是写给arduino用的,不过我一看注释那么熟,有些部分简直和卖家给的例程一模一样,可以肯定他们都有一个共同的祖先。仔细研究后,发现级联的关键是写后面的模块就得把它前面的模块写空。像这样/*第二片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; } 复制代码 我的代码如下: 定义了一个总的片数,然后用循环把初始化数码管模块和写每片的数据都统一起来了,这样不管是写一片,还是8片,代码都是一样的长度(好象max7219最多就支持8片),还自定义了一个DP参数,解决了卖家例程没写的小数点有无的问题。卖家例程是在loop中初始化模块的,这样显示感觉有闪烁,我移到setup中初始化,闪烁就没了 //模块引脚定义 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 } } 复制代码 |

发表于 2018-5-18 16:26:58 |
先上最终效果,感觉还是可以的,不过要是想完美,得像卖得挺火的那种木壳钟一样,平常像块木头,显示的时候才透出来,不过没找到合适的外壳。