MAX7219级联显示的初始化
初始化首先要知道MAX7219内部的命令,如下图
表格中REGISTER一列是方便我们区分命令的,是对命令的解释。
D15到D12用的是X,意思是无所谓,你写1写0都可以。
D11到D8是有效的命令。
HEX CODE就是命令的16进制表示,0x是16进制表示的格式,以X1为例,X代表的是这里可以是任意数,1为有效命令。
所以一般来说D15到D8不用关注,HEX CODE中一般X就用0代替,以0xX1为例,传输时的数据就是0x01。
然后逐一介绍每个命令。
No-Op的含义是,这个地址什么用也没有,为什么会有什么用也没有的命令呢,因为除了这条命令之外的15条命令都是有用的,所以需要一条没有用的命令。这话听着有点绕,举个例子:你级联了两个MAX7219,从机1的DIN直接接主机,从机2接从机1的DOUT。如下图所示。
简单演示一下,这不是完整连接图。如果你需要单独控制从机2,那么数据必定会通过从机1的移位寄存器,发送数据的格式也一定是8位命令加8位数据,而你要发送两次(因为需要把数据从从机1推到从机2中),如果所有的命令都是有意义的,那么,在锁存的时候,非常有可能把从机1的某个设置更改,然后产生莫名的错误。然后错误还难以发现,最后就是质疑芯片是否是好的,然后换了芯片发现还是有问题,然后就看着电脑的代码在那里emo。
Digit0到Digit7是数据显示寄存器,比如要向Digit0写入0x12,那就要先发送命令0x01,再发送数据0x12,max7219扫描时会从Digit0到Digit7,当扫描到Digit0时就会显示0x12。Digit0映射的就是DIG0引脚,扫描到哪个引脚,哪个引脚的电平就会变为低电平,其他DIG引脚的电平变为高电平,然后读取当前被扫描引脚内部寄存器的值,输出出来。以Digit0为例,扫描到DIG0时,Digit0里的数值为0x12,所以SEG端的输出为
DP | A | B | C | D | E | F | G | |
二进制 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 |
十六进制 | 1 | 2 |
Decode Mode是译码模式寄存器,什么是译码呢,看个例子,假设现在max7219正确连接了一个数码管,这个数码管接的共阴极引脚是DIG0。数码管如下图。
以DIG0为例, 如果要显示0的话,发送的是命令0x01+数据0xFE,才能显示0,对应上图中标号可以验证。0xFE的二进制表示如下图。
但是开启译码模式的话,还是以DIG0为例,要显示0,直接发送命令0x01+0x00就可以显示0了。
译码表格如下图所示。
译码与不译码的对比表如下图所示。
你也可以选择DIG0~7哪些进行译码,哪些不进行译码,如果需要译码,则在译码模式寄存器的相对位置将数据置1即可,数据手册解释如下图。
比如我想让DIG0,DIG5开启译码模式,则发送命令0x09+数据0x21即可。
Intensity是亮度寄存器,可以控制显示的亮度,亮度控制共有16级,从0x00~0x0F。官方数据手册如下图所示。
需要多亮,看自己的感觉就行了。
Scan Limit是扫描极限寄存器,这个寄存器是控制哪些扫描,哪些不扫描的,比如MAX7219可以控制8的数码管,但是你只用了2个数码管,分别接在DIG0和DIG1上,那DIG2~DIG7都是没用的,那就不用扫描,所以可以发送命令0x0B+数据0x01,设置扫描极限,只扫描DIG0和DIG1即可。要注意的是扫描极限只能从0开始。数据手册解释如下图。
Shutdown是关断寄存器,发送0x01是开启显示,0x00是关闭显示。官方数据手册解释如下图。
Display Test是显示器测试寄存器,0x00为关闭测试,0x01为开启测试。开启测试时,所有的LED灯被点亮,然后你就可以用你的眼睛去看LED灯是不是能正常显示了。非常的人性。当你开启时,其他设置大多是不生效的,所以正式的程序中一般不用。
命令就介绍完了,接下来就是代码实现,前面的文章说过,MAX7219的级联时通过移位寄存器的,所以在初始化的时候要最先传输级联中的最后一个芯片的指令。
代码中函数已经在前面文章介绍过了,不再进行介绍。
#define MAX7219_SHUTDOWN 0x0C //停机模式,0x00关闭,0x01开启
#define MAX7219_DECODE 0x09 //译码方式,0x00不译码
#define MAX7219_INTENSITY 0x0A //亮度设置,最低0x01,最高0x0F
#define MAX7219_SCAN 0x0B //扫描界限,不扫描0x00,全扫描0x07
#define MAX7219_TEST 0x0F //测试模式,0x00关闭测试,0x01开启测试
/**
* max7219初始化
*/
void MAX7219_init(void)
{
u8 i;
MAX7219_unlock();
for(i = 0; i < MAX7219_NUMBER; i++)
{
MAX7219_sendData(MAX7219_SHUTDOWN, 0x00);//关闭显示屏
}
MAX7219_lock();
MAX7219_unlock();
for(i = 0; i < MAX7219_NUMBER; i++)
{
MAX7219_sendData(MAX7219_TEST, 0x00);//关闭测试模式
}
MAX7219_lock();
MAX7219_unlock();
for(i = 0; i < MAX7219_NUMBER; i++)
{
MAX7219_sendData(MAX7219_DECODE, 0x00);//不采用译码模式
}
MAX7219_lock();
MAX7219_unlock();
for(i = 0; i < MAX7219_NUMBER; i++)
{
MAX7219_sendData(MAX7219_INTENSITY, 0x08);//设置亮度
}
MAX7219_lock();
MAX7219_unlock();
for(i = 0; i < MAX7219_NUMBER; i++)
{
MAX7219_sendData(MAX7219_SCAN, 0x07);//设置扫描边界
}
MAX7219_lock();
MAX7219_unlock();
for(i = 0; i < MAX7219_NUMBER; i++)
{
MAX7219_sendData(MAX7219_SHUTDOWN, 0x01);//开启显示屏
}
MAX7219_lock();
}
也可以把命令放在数组中然后用一个嵌套循环实现,但是后面单独改变某个设置的时候看着不够直观,我就按我自己的习惯来了。
这里每一个单独的命令都要发送4次,因为用了4个MAX7219芯片级联。建议不要把所有指令连续写,然后重复四次,这样不能保证芯片被完整初始化,因为可能会导致最后一组指令卡在从机移位寄存器中,没有读取到从机内部。
这样说可能有点抽象,走一下关闭屏幕的流程看看。
1.现在是没有发送数据的时候,从机里的数据都是未知数,此时处于开锁状态。
2.现在开始发送第一次数据,数据发送到了从机1的移位寄存器,现在还没有读取到从机1的内部。
3.发送第二次数据,为了方便观察,第二次发送的数据用蓝色表示,这时从机1的数据被推到了从机2中,从机1中存储的是主机新发来的数据。
4.发送第三次数据,方便观察用黄色表示,但是黄色不是很明显,将就着看一下吧,从机2的数据被推到了从机3,从机1的数据被推到了从机2,从机1中的数据是主机最新发来的。
5.发送第四次数据,用黑色表示,这时从机3的数据被推到了从机4,从机2推到从机3,从机1推到从机2,从机1中存储最新发来的数据。这时可以看到第一次发送的数据进入了从机4的移位寄存器。
6.最后将数据进行锁存,也就是关锁,传输到芯片内部。一条指令传输到芯片内部的流程就走完了。
通过上面的过程可以看到数据是被推着向前发送的,数据会被保存在移位寄存器中,所以如果对从机1,2,3进行单独控制时,一定要把前面的数据先用0x00+0xXX清空,否则可能会产生意想不到的错误。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~